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!)")
}
}
}
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
}
}
func queryForPhotosFromLocalDatastore()
{
var xquery = PFQuery(className: "Follows")
xquery.fromLocalDatastore()
//xquery.whereKey("Follower", equalTo: PFUser.currentUser()!.objectId!)
xquery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let xobjects = objects
{
if xobjects.count > 0
{
for yobject in xobjects
{
println("Done")
}
}
else
{
println("number of objects is \(xobjects.count)")
}
}
else
{
println(error?.userInfo)
}
}
}
func queryForPhotosFromParse()
{
PFObject.unpinAllObjectsInBackgroundWithBlock(nil)
var xquery = PFQuery(className: "Follows")
xquery.whereKey("Follower", equalTo: PFUser.currentUser()!.objectId!)
xquery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let xobjects = objects
{
println("xobjects are \(xobjects.count)")
println("querying from parse")
for yobject in xobjects
{
var followedUser = yobject["Following"] as! String
var query = PFQuery(className: "Images")
query.whereKey("userID", equalTo: followedUser)
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock { (xobjects, error) -> Void in
if let objects = xobjects
{
PFObject.pinAllInBackground(objects, block: { (success, error) -> Void in
if error == nil
{
println("Pinned \(objects.count) objects")
self.queryForPhotosFromLocalDatastore()
}
})
}
else
{
println(error?.userInfo)
}
}
}
}
}
}
// The number of objects its returning (xobjects.count) is 0. Why is that so ?
I tried to have query localdatastore in my app but The number of objects its returning (xobjects.count) is 0. Why is that so ?
i have tried to query before with the previous versions but same thing happened. The latest version on parse says that they have fixed the error but I'm still getting the number of objects retrieved from localdatastore as "0". Please Help.
I've a table 'preferences' where user preferences are saved along with username. I created this method to update current user's preference' but somehow it doesn't seem to work. I am not sure if the portion "prefQuery.getObjectInBackgroundWithId(object.objectId)" is required at all.
I am new to Parse, could somebody please help me point what could be the issue.
func userPreferences(){
var currUser = PFUser.currentUser()
var prefQuery = PFQuery(className: "preferences")
var prefObj = PFObject(className: "preferences")
if let currUserName = PFUser.currentUser()?.username {
prefQuery.whereKey("username", equalTo: currUserName)
}
prefQuery.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
prefQuery.getObjectInBackgroundWithId(object.objectId){
(object: PFObject?, error: NSError?) -> Void in
if error == nil || object != nil {
prefObj["agestart"] = self.fromAge.text
prefObj["ageend"] = self.toAge.text
prefObj["location"] = self.location.text
ProgressHUD.showSuccess("Update successful")
} else {
ProgressHUD.showError("Update failed")
}
}
}
}
}
}
}
I found the issue and have updated my codes. The working codes are below; the issue was with the "prefObj["agestart"]" block of codes where I was using the wrong Query instance. You can compare the two snippets:
func userPreferences(){
var currUser = PFUser.currentUser()
var prefQuery = PFQuery(className: "preferences")
var prefObj = PFObject(className: "preferences")
if let currUserName = PFUser.currentUser()?.username {
prefQuery.whereKey("username", equalTo: currUserName)
}
prefQuery.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
prefQuery.getObjectInBackgroundWithId(object.objectId){
(prefObj: PFObject?, error: NSError?) -> Void in
if error != nil {
println(error)
ProgressHUD.showSuccess("Error while updating")
} else if let prefObj = prefObj {
prefObj["agestart"] = self.fromAge.text
prefObj["ageend"] = self.toAge.text
prefObj["location"] = self.location.text
ProgressHUD.showSuccess("Update successful")
prefObj.saveInBackgroundWithBlock({ (Bool, error: NSError!) -> Void in })
}
}
}
}
}
}
}
The best way to cut your code to the maximum, you can see below:
func userPreferences() {
let prefQuery = PFQuery(className: "preferences")
if let currUserName = PFUser.current()?.username {
prefQuery.whereKey("username", equalTo: currUserName)
}
prefQuery.findObjectsInBackground {
(objects, error) in
if error == nil {
if let objects = objects {
for object in objects {
object["agestart"] = "ur value"
object["ageend"] = "ur value"
object["location"] = "ur value"
print("Update successful")
object.saveInBackground()
}
}
}
}
}