0

I've looked all over and have found no joy. I was wondering if someone could help me figure out how to retrieve a random object from a class on parse.com using swift in an iOS app. By no means am I asking someone to write my code, because then what would I learn, but I was wondering if someone could maybe provide a generic example that I could adapt to my project and future projects.

Let's say the class is called ParseClass, and I will need to populate three variables with data from the object in parse., A, B, C -- two with strings, one as an array of strings. Let's say there are ... idk ... 50 objects in the parse class, and I need to retrieve them one at a time randomly.

Logically, I get it ... I need to do a count of the objects in the parseclass, then get a random number from that count, and then use that number to retrieve the object somehow (either directly from parse using a skip random query limit 1, or maybe by getting all the objects into an array (whichever is the best/most efficient code). I just don't know how to format/write the code in swift. Any one think they could help me (and many others apparently) with some generic code I could adapt to my specific project??

Here is some generic code ... I can start it -- I got a basic idea of how it should be, I just don't know swift well enough to complete the block.

var A  : String!
var B  : [String]!
var C  : String!

    var query : PFQuery = PFQuery(className: "ParseClass")
    query.findObjectsInBackgroundWithBlock {
        (objects : [AnyObject]!, error : NSError!) -> Void in

//now what? I've seen this in other questions here, but I don't know how to incorporate it.

let randomSkip = arc4random_uniform(count)

query.skip = randomSkip, and query.limit = 1.

Any help on this would be greatly appreciated.

Oh -- just saw this in another thread ... it's basically doing what I need, but in objective C and it looks like with only 2 variables... could someone help me rewrite in swift? Sorry to be so loquacious ... the burden of a novice. I promise as I grow more adept, I will help other novices most sympathetically. :-)

    - (void)randomQuestion:(void (^)(NSString *question, NSArray *answers))completion {
PFQuery *countQuery = [PFQuery queryWithClassName:@"ParseClass"];
[countQuery countObjectsInBackgroundWithBlock:^(int count, NSError *error) {
    NSInteger randomSkip = arc4random_uniform(count);
    PFQuery *query = [PFQuery queryWithClassName:@"ParseClass"];
    query.skip = randomSkip;
    query.limit = 1;
    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if (!error) {
            if (objects.count) {
                PFObject *ParseClassObject = objects[0];
                NSString *A = ParseClassObject[@"A"];
                NSArray *B = ParseClassObject[@"B"];
                completion(A, B);
            } else {
                NSLog(@"no error, but no ParseClass objects found");
            }
        } else {
            NSLog(@"there was an error %@", error);
            completion(nil, nil);
        }
    }];
}];

}

2 Answers 2

1

ObjectHolder should be objectHolder, or objects because it's a parameter name.

Your count for arc4random_uniform would be objects.count.

Downloading the objects and randomly accessing them locally will be most efficient if you need to display all of them anyway. Multiple downloads isn't great.

You're going to run into size limits eventually as the download row count is limited. Perhaps you could download pages and treat the items in each page as a separate collection to view randomly...

So, you wouldn't be using skip or limit, you would just be accessing elements in the objects array.

Removing the items from the array after you've used them is easiest. Or you can randomly sort the array so you don't need to remove

Sign up to request clarification or add additional context in comments.

4 Comments

Awesome, thank you!!! I won't have 100 objects any time soon, so the limitations aren't a concern yet, but when they become a concern I will look into the pagination option for sure. I like the idea of downloading all the objects on time and then accessing them locally! So ... any chance you could help me flesh out this generic code?
Derp ... accidentally hit enter. Any chance you could help me flesh out this code: var A : String! var B : [String]! var C : String! var query : PFQuery = PFQuery(className: "ParseClass") query.findObjectsInBackgroundWithBlock { (objects : [AnyObject]!, error : NSError!) -> Void in if (error == nil) { self.A = objects ["A"] as String! self.B = objects ["B"] as Array! self.C = objects ["C"] as String! } /// is this working so far? If so, now what??? Thank you for your time.
I don't write swift currently so I'm not 100% on syntax. You don't call objects ["A"] as String!, because you want to iterate objects like for object : PFObject in objects { and then get the string from each one (object)
Gracias amigo! Think I'm going to go looking for the swift solution here: developer.apple.com/swift/resources If I figure it out, I will come back and post the solution.
0

One way you can do it is to set another key called e.g. questionsNumber and each question will be be in that questionNumbers row. And then query the number from the arc4random_uniform(count) so something like this:

var query = PFQuery(className: "ParseClass")
        let randomNumber = arc4random_uniform(count)
        var randomNumberCast = Int(randomNumber)
        query.whereKey("questionNumber", equalTo: randomNumberCast)
        query.getFirstObjectInBackgroundWithBlock { (object: PFObject!, error: NSError!) -> Void in
            if error == nil {
                let questions = object["questions"] as String //This will equal your question at random.

        }

}

7 Comments

Wow, that's genius! :-) Thank you! I think I will use this method for sure, but Wain brought up a good point below -- it would be best to download them all to an array and then get them randomly. Might you know how to download the whole class (all the objects) first and then use this brilliant method??
Why would you want to download all of them at once when you can achieve the end results by just downloading one at random at a time? If you wanted to query all of the questions you wouldn't use a whereKey. You'd just query the key you want to download and then instead of using the query.getFirstObjectInBackgroundWithBlock you would use the query.findObjectsInBackgroundWithBlock to get all of the objects in that key.
Just taking what Wain said into consideration, "Downloading the objects and randomly accessing them locally will be most efficient if you need to display all of them anyway. Multiple downloads isn't great." So ... let me make sure I understand you ... to get them all I would need to do something like: query.findObjectsInBackgroundWithBlock {object: PFObject!, error: NSError!) -> and then if error == nil {assign objects to variables} ?? Thank you!
Are you querying an array of objects? and these objects are questions which you want to pick at random, am I correct? What you have put above will query your classes objects. if you want to be specific on what you want to query use the whereKey which will help you narrow it down to specific keys or even objects.
Still a novice, so sometimes I get lost in terminology ... but it's a class (table) on parse.com that has questions, answers (an array), and the correct answer, which just lists the position of the correct answer in the answers array. I marked this as answered b/c your solution totally works. Now I'm wondering how to incorporate what Wain suggested by grabbing everything off parse.com and then doing the random question query locally. Thank you for your answers.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.