Parse.com - Fetching relation using Swift - ios

I have a user favorites class that's storing a user object and an event object, it get set when a user favorites an event.
I'd like to display the full list of a given user's favorites. So I query favorites class to get the event objects and then attempt to query the events table to match the event object from favorite with the actual event class to pull in the event name and ID. In ruby for example, assuming relations/associations are setup, I would just call:
favorite.event.name
favorite.event.id
What's the equivalent in Swift? Here's what I have so far, but something tells me I'm overcomplexifying it and I would hope there's simple methods available for retrieving data through relations.
let query = PFQuery(className: "Favorite")
query.includeKey("eventId")
query.whereKey("createdBy", equalTo:userId!)
query.findObjectsInBackgroundWithBlock { (favorites:[PFObject]?, error:NSError?) -> Void in
if (error == nil){
print("Favorite Count: \(favorites!.count)")
print("Favorite Event IDs: \(favorites!)")
for favorite in favorites! {
print("Favorite: \(favorite)")
let eventNameQuery = PFQuery(className: "Event")
eventNameQuery.whereKey("eventId", equalTo:favorite )
eventNameQuery.findObjectsInBackgroundWithBlock { (events:[PFObject]?, error:NSError?) -> Void in
if (error == nil){
print(events!.count)
print(events!)
for event in events! {
self.favoriteListItems.append(event.objectId! as String)
self.favoriteListIds.append(event.objectId! as String)
}
}
}
}
self.savedEventsListTableView.reloadData()
} else {
print("error fetching objects")
}
}
}
When I run this, I get zero results...when I know in parse core I have objects that match both as shown below:
Favorite Class:
Event Class:

First of all query for a pointer to a User object, not user's objectId.
query.whereKey("createdBy", equalTo:PFUser.currentUser()!)
Next in here you probably want to add name of event.
for event in events! {
self.favoriteListItems.append(event["eventName"] as! String)
self.favoriteListIds.append(event.objectId! as String)
}

Related

Struggling to append arrays across Parse classes

Hi guys I'm trying to build a simple swipe app to like and dislike uploaded photos. I'm struggling with adding the likes/dislikes to Parse the way that I want them to. I've tried two ways so far:
adding the objectId of the posted image to the User who liked/disliked it but the problem is only one of the objectId's shows up in the array.
staying in the Parse class where the images are posted to (Post), add the userID of the liker/disliker to the image. This doesn't happen at all, new rows are created with new objectId's everytime an image is liked/disliked.
Ideally I want the users who have liked/disliked the photo in a single array so I can query this later. I don't have a great understanding of Parse, it's my first time using it so any help will be massively appreciated.
Here is the code I'm using when an image is swiped (adding to Post class):
if gesture.state == UIGestureRecognizerState.Ended {
var likedOrDisliked = ""
if label.center.x < 100 {
print("Dislike")
likedOrDisliked = "disliked"
} else if label.center.x > self.view.bounds.width - 100 {
print("Like")
likedOrDisliked = "liked"
}
if likedOrDisliked != ""{
var post = PFObject(className: "Post")
post.addUniqueObjectsFromArray([(PFUser.currentUser()?.objectId!)!], forKey: likedOrDisliked)
post.saveInBackground()
}
This is the snippet of when I try adding to User class:
PFUser.currentUser()?.addUniqueObjectsFromArray([displayedUserID], forKey: likedOrDisliked)
do {
try PFUser.currentUser()?.save()
} catch {
}
Here is what happens in the dashboard,
new rows created
What you wanted is to update the actual Post with the like/dislike user
Create a Post (This part you have not explained but i am show a simple assumption - pseuodo code)
var post = PFObject(class:"Post")
post["image"] = PFFile(image)
post.save()
Next you show the image on screen by getting the image from the post
When the user dislikes/likes
you add the current PFUser to the liked/disliked column and save back the object.
let arrayMut = NSMutableArray()
var array = NSArray()
if let arrayData = post.objectForKey("likedUser") as? NSArray {
array = arrayData
}
loop through now the array to find if current user is there.. if not find .. add current PFUser
arrayMut.addObject(PFUser.currentUser().objectId);
post.setObject(arrayMut, forKey: "likedUser")
post.save()
I've tried a lot of things and eventually something stuck, the desired effect was achieved through (added the current user to the liked or disliked fields) :
if likedOrDisliked != ""{
var post = PFQuery(className: "Post")
post.findObjectsInBackgroundWithBlock({ (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects {
for object in objects {
var objId = object["objectId"]
var query = PFQuery(className: "Post")
query.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error == nil {
object.addUniqueObjectsFromArray([(PFUser.currentUser()?.objectId)!], forKey: likedOrDisliked)
object.saveInBackground()
}
})
}
}
}
})

Parse database is replacing objects when it should create a new one

I have been trying to figure out this problem for a while without success. I have a button works like this:
Query the videosTable class in Parse and if the value for videoID (that I get from youtube's API) is not existent, create a new PFObject with rating 0. Otherwise, increase the rating by one.
The result however, is that the first new object I try to create every time I launch the app has no problem, but if I create another new object during the same run/session, the object previously created gets replaced by this new one.
The objectID stays the same, so I'm guessing this has something to do with the query not getting closed (or something similar), resulting in me modifying the previous object, instead of creating a new one.
Can someone shed some light in this?
#IBAction func recomBtn(sender: AnyObject) {
let query = PFQuery(className: "VideosInfo")
query.whereKey("Video_ID", equalTo: videoID)
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if objects?.count == 0 {
print(objects)
videosTable["Video_ID"] = self.videoID
videosTable["Rating"] = 1
videosTable.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
print("Rating Created")
} else {
print(error?.description)
}}
} else {
objects![0].incrementKey("Rating")
print("Rating Increased")
videosTable.saveInBackground()
}} else {
print(error?.description)
}
}
}
After much reviewing, I found out I was making a very dumb mistake! I declared the PFObject outside of the function! So when I was done with my button, the PFObject remained! (Since I don't really close the view after I go to another video, the PFObject remained as a property of the class until I closed the app).
Thanks anyway for your help!

How to create pointer to Parse PFUser from facebook ID

I'm doing a Facebook graph call to get friends of the user that are using my app. I get the facebook ID of the user's friends back from the graph call. Below is what I'm attempting to obtain from Parse with that ID, but's it's not getting all the users back, I believe since its an async call. How can I save an array of pointers of the user's fb friends that are using the app? Thanks in advance!!
graphConnection.addRequest(requestFriends, completionHandler: { (connection: FBSDKGraphRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
if result.objectForKey("friends") != nil {
// parsing dictionary to get results
let firstDict = result.objectForKey("friends")
let dataArray = firstDict!.objectForKey("data")
let myFriendsUsingTheAppCount = dataArray!.count
print("\(myFriendsUsingTheAppCount)")
let friendsArray:NSMutableArray = []
for var i = 0; i < dataArray!.count; i++ {
let friend = dataArray![i]
let friendFbObjectID = friend.objectForKey("id")!
let query = PFUser.query()
query!.whereKey("facebookID", equalTo: friendFbObjectID)
query!.findObjectsInBackgroundWithBlock({ (objects, error) -> Void in
if error == nil {
// this is where I was going to save this specific user as a pointer
} else {
// some error
}
})
// this is saving just the friend's name/fb id to an array, but I want an array of pointers to the PFUser
friendsArray.addObject(friend)
}
} else {
// fb friends is nil
print("FB friends came back nil")
}
})
This could be simplified into a single query by using whereKey:containedIn:
let facebookIDs = dataArray.map { $0.objectForKey("id")! }
let query = PFUser.query()!
query.whereKey("facebookID", containedIn: facebookIDs)
The query will now contain all users whose facebook id is in the array passed to the query.
(swift syntax may be incorrect did not double check)

Parse: How can I update all rows with the same key value

How can I update all rows with the same key value in a Parse class?
As my code, I think Parse would cost a lot of my money if there are 100 objects per user.
Is there any other way to do that?
let username = PFUser.currentUser()?.username
let objectQuery = PFQuery(className: "FriendList")
objectQuery.whereKey("username", equalTo: username!)
objectQuery.findObjectsInBackgroundWithBlock { (friendList:[AnyObject]?, error:NSError?) -> Void in
if let friendList = friendList as? [PFObject] {
for myInfo in friendList {
myInfo["contact"] = contact
myInfo["portrait"] = PFFile(data: portraitNSData)
myInfo["company"] = company
myInfo["position"] = position
myInfo.save() // create a request?
}
}
}
Form array of needed objects and than just
PFObject.saveAllInBackground(objectsArray)
Parse has a functions to object see to save many objects (see documentation here)
PFObject.saveAllInBackground(array, block: {
(succeeded: Bool, error: NSError!) -> Void in
if (error != nil) {
println("Error saving: \(error)")
}
})
Unfortunately the documentation is not update to Swift but you can see a list of the function in objective-c
saveAll:
saveAll:error:
saveAllInBackground:
saveAllInBackground:block:
It would be best to create a CloudCode function. Then call that function from iOS. It's not difficult, see their documentation here: Parse.com

Parse: deleting object value in column using Swift

I've used Parse successfully in other apps before but never used the delete function. I'm trying to delete a value ( an alphabetical letter) in a column (column title is 'letter') associated with a user in Parse. I'm using Swift. The code is finding the correct value as evident via a println in the deletion code, but nothing is happening after the remove and save functions are executed. The value is still there in the column. And I'm not getting any Parse errors. The code is below. Any help, as always, will be greatly appreciated.
var query = PFQuery(className: "game")
query.whereKey("player", equalTo:PFUser.currentUser())
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if !(error != nil) {
for object in objects {
var myLetter = object["letter"]! as String
println("The object for key letter is \(myLetter)") //This prints the correct letter in the current user's Letter column
PFUser.currentUser().removeObjectForKey("letter")
PFUser.currentUser().saveInBackgroundWithBlock{
(success: Bool, error: NSError!) -> Void in
if (success) {
// The object has been saved.
println("success")
} else {
// There was a problem, check error.description
println(error)
}
}
}
}
}
I think the issue is that you are creating a new Parse query and deleting it locally as opposed to retrieving the item and then deleting it. So, retrieve the item you want to delete and then call the deleteInBackground method.

Resources