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

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!

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.com - Fetching relation using Swift

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)
}

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 Local Datastore: Unpin objects seems broken in Swift

I want to unpin a list of objects, which I had successfully locally stored earlier, and replace it with a new one. The code below should do that trick, but the locally pinned objects simply don't get updated. I tried everything including PFObject.unpin, nothing removes the old pinned objects except a complete reset of the simulator
func updateCountryList(server:Int, local:Int) {
let query = VEPCountry.queryAll()
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error != nil {
// throw error
} else {
if local != 0 {
VEPState.unpinAllObjectsWithName(String("countryListVersion\(local)"))
}
VEPState.pinAll(objects, withName: String("countryListVersion\(server)"))
defaults.setObject(server, forKey: "localCountryListVersion")
}
}
}
Appreciate help or pointer to known issues around unpinning in Swift
I wonder if your unpin has't really finished, it's going off to the database after all.
Can you try:
query
.findObjectsInBackground()
.continueWithSuccessBlock({ (task: BFTask!) -> AnyObject! in
// ...
return VEPState.unpinAllObjectsWithNameInBackground("name"))
})
.continueWithSuccessBlock({ (task: BFTask!) -> AnyObject! in
// ...
return VEPState.pinAllInBackground(objects, withName: "name"))
})
I may have the syntax a little off and the background method names not quite right. Also I'm using promises/tasks which is not a bad habit to get into.

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