I have a parse back end for my iOS app. I have a parse class called \"quiz\". How can I read the number of rows in the Parse class, I have to use it in my iOS app?
Since the count is retrieved asynchronously, the way to return the count is inside a completion closure instead of using return cnt
.
Here is an example:
func countObjectsWithCompletion(completion: (Int?)->(Void))
{
var query = PFQuery(className:"quiz")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil
{
// The find succeeded.
print("Successfully retrieved \(objects!.count) scores.")
completion(objects!.count)
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
completion(nil)
}
}
}
countObjectsWithCompletion { (myObjectCount: Int?) in
if let cnt = myObjectCount {
print("count is \(cnt)")
} else {
print("error getting count")
}
}
findObjectsInBackgroundWithBlock
is constrained by the query limitation to return up to 100 objects by default. This limit can be increased, but only to a maximum of 1000. Because of this, you cannot rely on findObjects
and then counting the results.
Parse has included in the documentation a simple way to count the total number of objects for a class or particular query.
var query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.countObjectsInBackgroundWithBlock {
(count: Int32, error: NSError?) -> Void in
if error == nil {
print("Sean has played \(count) games")
}
}
Swift 3
let query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.countObjectsInBackground { (count, error) in
if error == nil {
print("Sean has played \(count) games")
}
}
It should also be noted that due to how costly count operations are, Parse has placed limitations on them
Count queries are rate limited to a maximum of 160 requests per minute. They can also return inaccurate results for classes with more than 1,000 objects. Thus, it is preferable to architect your application to avoid this sort of count operation (by using counters, for example.)
This inaccuracy is not due to the 1000 request object limit. The count query will try to get the total number of records regardless of size, but since the operation may take a large amount of time to complete, it is possible that the database has changed during that window and the count value that is returned may no longer be valid.
The recommended way to handle counts is to essentially maintain your own index using before/after save triggers in cloud code. However, this is also a non-ideal solution because save hooks can arbitrarily fail part way through and (worse) postSave hooks have no error propagation. To add on to this, here is another quote by Hector Ramos from the Parse Developers Google Group.
Count queries have always been expensive once you throw some constraints in. If you only care about the total size of the collection, you can run a count query without any constraints and that one should be pretty fast, as getting the total number of records is a different problem than counting how many of these match an arbitrary list of constraints. This is just the reality of working with database systems.
And lastly, to quote the Parse Engineering Blog Post: Building Scalable Apps on Parse.
Suppose you are building a product catalog. You might want to display the count of products in each category on the top-level navigation screen. If you run a count query for each of these UI elements, they will not run efficiently on large data sets because MongoDB does not use counting B-trees. Instead, we recommend that you use a separate Parse Object to keep track of counts for each category. Whenever a product gets added or deleted, you can increment or decrement the counts in an afterSave or afterDelete Cloud Code handler.