I want to run a query to determine the number of rows in a tableView in Swift. When I use the query results.count method I get the following error:
Int? is not convertible to 'Void'
Here is the function that is throwing the error:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let user = self.user {
var currentUserQuery = PFQuery(className: "Game")
currentUserQuery.whereKey("user1", equalTo: PFUser.currentUser()!)
currentUserQuery.whereKey("isActive", equalTo: true)
var currentUserQuery2 = PFQuery(className: "Game")
currentUserQuery2.whereKey("user2", equalTo: PFUser.currentUser()!)
currentUserQuery2.whereKey("isActive", equalTo: true)
var query = PFQuery.orQueryWithSubqueries([currentUserQuery, currentUserQuery2])
query.findObjectsInBackgroundWithBlock{
(results: [AnyObject]?, error: NSError?) -> Void in
if error != nil {
println(error)
}
if error == nil{
//continue an active game that already exists with the user
if results != nil{
return results!.count as? Int
If I change (results: [AnyObject]?, error: NSError?) -> Void to (results: [AnyObject]?, error: NSError?) -> Int I get a different error:
Cannot invoke 'findObjectsInBackgroundWithBlock' with an argument list of type '(([AnyObject]?, NSError?) -> Int)'
What should I do?
Thanks!
You need to remove the ? from your return, it is up to the declaration of the function to decide if those values are optional or not.
(results: [AnyObject], error: NSError) -> Void in
Related
I want to retrieve the user score from Parse and assign it to a variable. This function returns 0 before the query finishes. I have found a similar answer at Retrieve object from parse.com and wait with return until data is retrieved. However, I expect the function have a return value and what argument should I use for the completionhandler when calling this function. Any help would be appreciated, thanks!
Here is my code
func loadCurrentUserData() -> Int {
let query = PFQuery(className: "userScore")
let userId = PFUser.currentUser()!
var currentUserScore: Int = 0
query.whereKey("user", equalTo: userId)
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
let scoreReceived = objects![0]["score"] as! Int
currentUserScore = scoreReceived
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.userScore.text = "\(scoreReceived)"
})
} else {
print("Error: \(error!) \(error!.userInfo)")
}
}
return currentUserScore
}
The way you have set this function will not work as the query method is asynchronous. This can be fixed in two ways:
1) Use the PFQuery synchronous category:
http://parse.com/docs/ios/api/Categories/PFQuery(Synchronous).html
The only disadvantage to this approach is that the method will become blocking so make sure to call it from a background thread.
2) Restructure the function to use a completion block instead of a return value..i.e:
func loadCurrentUserData(completion: (score: Int!, error: NSError?) ->()) {
let query = PFQuery(className: "userScore")
let userId = PFUser.currentUser()!
var currentUserScore: Int = 0
query.whereKey("user", equalTo: userId)
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
let scoreReceived = objects![0]["score"] as! Int
currentUserScore = scoreReceived
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.userScore.text = "\(scoreReceived)"
})
completion(score: currentUserScore, error: nil);
} else {
print("Error: \(error!) \(error!.userInfo)")
}
completion(score: currentUserScore, error: error);
}
}
I have the following function calling Parse written i swift:
func listCatalogItemsWithBlock(completion: (result: ([ParseCatalog], NSError)) -> Void)
{
let parseClassName = ParseCatalog.parseClassName()
let query = PFQuery(className: parseClassName)
query.findObjectsInBackgroundWithBlock { (ParseCatalog catalog, NSError error) -> Void in
}
}
What i want is to forward the result block of findObjectsInBackgroundWithBlock to listCatalogItemsWithBlock function's block, so i can process the results elsewhere.
How can i do that?
UPDATE 1
I have managed to do this quite easily:
func listCatalogItemsWithBlock(completion: PFQueryArrayResultBlock)
{
let parseClassName = ParseCatalog.parseClassName()
let query = PFQuery(className: parseClassName)
query.findObjectsInBackgroundWithBlock(completion)
}
But in this case i passed a PFQueryArrayResultBlock type. Which is:
public typealias PFQueryArrayResultBlock = ([PFObject]?, NSError?) -> Void
How do i return the same results if i keep my function the original way:
func listCatalogItemsWithCompletion(completion:([ParseCatalog]?, NSError?) -> Void)
/* What goes here? */
}
Update 2
Like this:
func listCatalogItemsWithCompletion(completion:(fvResponse: [ParseCatalog], fvError: NSError?) -> Void)
{
let parseClassName = ParseCatalog.parseClassName()
let query = PFQuery(className: parseClassName)
query.findObjectsInBackgroundWithBlock { (response:[PFObject]?, error: NSError?) -> Void in
completion(fvResponse: response as! [ParseCatalog], fvError: error)
}
}
In the user class I have a pointer "Friendship" to the user class, but when I run the program I get the error -
EDIT: I have figured out why I get the error. "Frinendship is not a pointer, it is a PFRelation, but I still want to access the ProPic and username. How would I do this?
Below is the user class
Below is the Pointer to the user class.
func getFriendPic(){
let imagequery = PFQuery(className: "_User")
imagequery.whereKey("username", equalTo: PFUser.currentUser()!)
imagequery.includeKey("Friendship")
imagequery.findObjectsInBackgroundWithBlock {( objects: [AnyObject]?, error: NSError?) -> Void in
for object in objects!{
let userPic = object["ProPic"] as! PFFile
userPic.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in
if(error == nil){
let image = UIImage(data: imageData!)
self.arrayOfFriends.append(image!)
print(self.arrayOfFriends)
}
// dispatch_async(dispatch_get_main_queue()) {
// self.collectionView.reloadData()
// }
})
}
}
}
func getFriendName(){
var query = PFQuery(className: "_User")
query.whereKey("username", equalTo: PFUser.currentUser()!)
query.includeKey("Friendship")
query.findObjectsInBackgroundWithBlock({
(objects: [AnyObject]?, error: NSError?) -> Void in
var objectIDs = objects as! [PFObject]
for i in 0...objectIDs.count-1{
self.arrayOfFriendsNames.append(objectIDs[i].valueForKey("username") as! String)
print(self.arrayOfFriendsNames)
}
})
}
The include query parameter doesn't work with Relation. Once you retrieved your user, you need to execute a second query to get the Friendship.
Here's an example to retrieve a PFRelation:
var relation = user.relationForKey("Friendship")
relation.query().findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if let error = error {
// There was an error
} else {
// objects contains the friendships of the user
}
}
I've been getting this Command failed due to signal: Segmentation fault: 11 error for 2 days now, and I cannot wrap my head around why its doing so. The error pointed at a specific query I made to parse.. However to test if it was my code or just a bug, I copied this EXACT block from Parse's query doc into my project as a function:
var query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
And it threw the error once again to that block.. Xcode is has also been throwing this message to my compiler :
Why is this happening ?
UPDATE
so it seems Kevin's answer below cleared the compiler bug by letting the compiler tell me the type rather than specifying it in the query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in line , by correcting it to :
query.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
}
however this other block is a little more complex, how do i adjust it to rid the error? :
func loadBooks() {
var query = PFQuery(className: "Books")
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
self.books.removeAll()
let bookObjects = objects as! [PFObject]
for (index, object) in enumerate(bookObjects) {
self.books.append(Book(pfBook: object))
}
}else if let secondMessage = error?.userInfo?["error"] as? String
where secondMessage == "The Internet connection appears to be offline." {
self.failedMessage(secondMessage)
self.activityIndicator.hidden = true
self.activityIndicator.stopAnimating()
}
dispatch_async(dispatch_get_main_queue()){
self.collectionView!.reloadData()
self.refreshControl.endRefreshing()
self.activityIndicator.stopAnimating()
}
}
}
objects is actually of type [PFObject]? not [AnyObject]?. A wild guess would say the root cause trying to downcast.
Anyway, just use the correct type to fix this
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
}
or just let the compiler tell you the type
query.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
}
let query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]?, error:NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
print(objects)
if let objects = objects {
for object in objects {
print(object.objectId)
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
Try this! It works!
I'm trying to use the getObjectInBackgroundWithId method, of a PFObject and it throws this error:
"Cannot invoke 'getObjectInBackgroundWithId' with an argument list of type (string, block: (PFObject!,NSError?) -> Void"
I have written the below code:
var result = PFQuery(className: "posts")
result.getObjectInBackgroundWithId("kk", block: {
(object: PFObject, error: NSError?) -> Void in
object["pLikes"] = object["pLikes"] + 1
object.save()
})
Any help?
You have to use getObjectInBackgroundWithId with
let query = PFQuery(className: "posts")
query.getObjectInBackgroundWithId("kk") { (objects, error) -> Void in
}
OR
let query = PFQuery(className: "posts")
query.getObjectInBackgroundWithId("kk") { (objects:PFObject?, error:NSError?) -> Void in
}
Change the object
let query = PFQuery(className: "posts")
query.getObjectInBackgroundWithId("kk") { (objects, error) -> Void in
let testObj = objects?.first as! PFObject
testObj.setObject(26, forKey: "pLikes")
testObj.saveInBackgroundWithBlock { (succeeded, error) -> Void in
if succeeded {
println("Object Uploaded")
} else {
println("Error: \(error) \(error!.userInfo!)")
}
}
}