I have an application setup so that there is an array that contains objectId's that the current user is friends/connected with. I'm attempting to create a button that deletes a single objectId from that array (kind of like an unfriend button). I'm currently passing the objectId value from a query in one view controller to another view controller that actually contains the friends profile and the delete/unfriend button. I'm getting the actual objectId as a string in the friends profile and I can print the objectId but I can't seem to figure out a way to delete this single objectId from the array.
Using PFUser.currentUser()?.removeObject() gives me an invalid field name error.
Anyone have an insight for me?
Let me know if there is more clarification needed! Thanks in advance.
Update
I have tried to also utilize this as my object code. userObjectId is received from another view controller and grabs the proper objectId of what I'd like to remove from the current users "accepted" array. This code gives me an error of "NSInternalInconsistencyException reason: Tried to save an object with a pointer to a new, unsaved object" I've tried to remove this objectId from the array in several different ways but can't seem to get it to stick. Thanks again.
var userObjectId = ""
var object: PFObject = PFObject(className: "User")
object["objectId"] = userObjectID
PFUser.currentUser()?.removeObjectsInArray([object], forKey: "accepted")
PFUser.currentUser()?.saveInBackground()
let object = PFObject(withoutDataWithClassName: "Your Class", objectId: "objectId from array")
object.deleteInBackgroundWithBlock { (success, error) -> Void in
if error == nil && success == true {
//Delete the objectId from the array
}
}
This will also remove the object from any array that holds it.
Related
I have a query "items" object. The class has a "parent" key that points to _User object.
The query is successful and fetches 'parent' object and i am able to access some custom keys from this 'parent' object but email is returned as nil !!
below is stripped down code.
Could anyone suggest why is this happening? This was working earlier and i have not made any code change. Running Parse-server ver 2.5.3 on Heroku.
let query = PFQuery(className: "items")
query.includeKey("parent") // parent points to _User
do {
let results = try query.findObjects()
for result in results {
let parent = result["parent"] as! PFUser
let foundUser = User()
foundUser.user = parent // User.user is of PFUser type
//custom keys in _User
foundUser.name = parent["name"] as! String
foundUser.city = parent["city"] as! String
foundUser.geoLocation = parent["location_geopoint"] as! PFGeoPoint
foundUser.userAddress = parent["user_address"] as! String
//this is failing with nil eventhough there is value in Parse
foundUser.email = parent["email"] as! String
// also tried this. parent.objectId returns a valid value
foundUser.email = parent.email
}
} catch...
Got the answer here enter link description here
In 2.3.0 there was a breaking change introduced which restricted the fields returned from a query on _User. If I remember correctly, email is taken out by default and you can specify additional fields to be removed from a query result in a configuration setting. In order to retrieve email you either have to specify the master key or be the owner of that object.
want some method like which do update the existing followers, and if not exists do add it to DB and link them to user something like
GETS CRASH OVER append in write block, due to duplicate primary key,
also, it works perfectly if no followers has been added in HKUser Table, once it comes to update it crashes
import UIKit
import RealmSwift
class HKUser: Object{
dynamic var full_name = ""
dynamic var email: String?
dynamic var user_id: String?
let followers = List<HKUser>()
override static func primaryKey() -> String? {
return "user_id"
}
}
I want to update the connection of a user in DB also, so I want to do some thing like
//1. updated the userFollower array with required data
let userFollowers:[HKUser] = []
//2. now need to link it with my user object and update it in db
if let user = realmWrapper.sharedInstance.getUser(forID: id) {
try! realm.write {
//want some method like which do update the existing followers,
//and if not exists do add it to db and link them to user something like
//realm.add(user, update: true)
user.followers.append(contentsOf: followers)
/**********
GETS CRASH OVER HERE,
due to duplicate primary key,
it works perfect if no followers has been added in HKUser Table,
once it comes to update it crashes
**********/
}
}
List<T>.append() method save to the Realm implicitly if the objects are unmanaged. That is why the duplicated primary key exception happens.
To avoid this, you can add or update the unmanaged objects before appending to the List. Then you append the objects to the List.
try! realm.write {
...
realm.add(followers, update: true) // Add or update the objects first
user.followers.append(contentsOf: followers)
...
}
Maybe it's not the case (not enough code in your question to tell) but it looks like you prepare the userFollowers array in step 1 to contain ALL the current followers for that specific user.
If this is the case then you'll end up re-adding all the existing followers not only the new ones, hence the duplicate keys.
I'm trying to increment a number in my parse table under the column "votes". Here's my code:
func upVote() {
var reviewQuery: PFQuery = PFQuery(className: "reviews")
reviewQuery.whereKey("content", equalTo: reviewTextView.text)
reviewQuery.findObjectsInBackgroundWithBlock{
(objects:[AnyObject]!, error:NSError!)->Void in
if error == nil{
for object in objects{
println(object)
let review:PFObject = object as! PFObject
review.incrementKey("votes", byAmount: 1)
}
}
}
}
When I print the object in the console I can see that it is the correct object that I'm looking for. It looks like this:
<reviews:ZqgSVL1Tsd:(null)> {
content = "njk\n";
reviewer = "<PFUser:6387CJtYI1>";
votes = 1;}
But when I look at my parse end, the number of votes has not changed. What am I doing wrong?
Save the object with
review.saveInBackground()
after incrementing the key.
After you modify an object, however small the modification, you must save it after. You are not saving your changes to the object review.
You have several options for saving, including save(), saveInBackground(), saveEventually(), and more. See the documentation for PFObject for more information:
https://www.parse.com/docs/ios/api/Classes/PFObject.html#//api/name/save
For example, you could save the object synchronously with
review.save() and you could save the object asynchronously with review.saveInBackground().
in my app there is a function that is analogous to liking a post. In my parse database, I have a "Like" class. In the Like class are 2 columns, one "from_user" that is a pointer column pointing to the user who liked it. The other is "to_post", pointing to the post that was liked. my code is:
var likeObject = PFObject(className: "Like")
likeObject["from_user"] = PFUser.currentUser()
likeObject["to_post"] = objectIDArray[0]
likeObject.saveInBackground()
For reference, the objectIDArray is an array that contains 1 element, the object ID of the given post that I want to like.
But when I try this, I get an error saying "expected type *Post, got String" which refers to the line of code:
likeObject["to_post"] = objectIDArray[0]
So how do I make it so that the object ID of the post (that I do have access to) can be used to point to that specific post?
thanks
What you want to do is use a pointer to the Post class.
The parameter you pass to the to_post key should be of type PFObject*, but instead you're passing a NSString* (the object id).
Considering you already have the ObjectID of the post, what you have to do is fetch the PFObject from that id and set it to your likeObject.
Try this:
var query = PFQuery(className:"Post")
query.getObjectInBackgroundWithId(objectIDArray[0]) {
(post: PFObject?, error: NSError?) -> Void in
if error == nil && post != nil {
likeObject["to_post"] = post
} else {
println(error)
}
}
I find only in the docs how the query can look like to select data.
As far as I see, there is only one way to collect 1 or many results:
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.
NSLog("Successfully retrieved \(objects.count) scores.")
// Do something with the found objects
for object in objects {
NSLog("%#", object.objectId)
}
} else {
// Log details of the failure
NSLog("Error: %# %#", error, error.userInfo!)
}
}
What I cant figure out (as I am a beginner!) is how to access the object data. Lets say I have the fields "name", how can I get it? What is the right syntax? Especially if I have more than 1 result?
For just one result I would do:
var name = object["name"] as String
myArray.append(name)
Even that can't be right? To use "var xx = xx" within the loop?
And what do I do when I have more than one result?
Other thought:
Declaring the var name: String! before I do the query and then:
name = object["name"] as String
self.myArray.append(name)
Returns the error: Immutable vaue of type [String] only has mutating members named 'append'
What would be the correct way to "work" with the data the query returns?
Another question: as those querys are async, they finished later and the method is "done" much more earlier, this way my array with names is empty when the view is shown and I receive the data at a later stage. What is the best practice here to have all data available before the view is delivered to the device?
Thanks so much!!
You can use objectForKey on your object. So instead of using var name = object["name"] as String you can use:
for object in objects {
var name = object.valueForKey("name") as String
}
But the other parts are absolutely fine. You can create an array somewhere in you code and then add the objects to it. to do that, you can loop through your objects and than add the objects to your array. Like that:
if error == nil {
// The find succeeded.
NSLog("Successfully retrieved \(objects.count) scores.")
// Do something with the found objects
for object in objects {
var name = object["name"] as String
myArray.append(name)
}
}
Because you can reuse the var name because every loop-element will be filled into the variable name and will erase the last value. But the array will get the new value appended. For example:
First loop. The value at the first index of your objects gets loaded into the object. For example with the value "John".
variable name's value is now the value of the object["name"] of the current loop. So name has the value John
Now you add the value to your array.
The second loop starts and the second element gets loaded inside object which now has the string Michael.
The Variable name's new value is now the value of object. So name's value is now Michael
and so on.