parse server creates a new entry every time it's saved - ios

Here is the code when a button is tapped.
#IBAction func sendTapped(_ sender: Any) {
let message = PFObject(className: "Message")
message["sender"] = PFUser.current()?.objectId
message["recipient"] = recipientObjectId
message.addUniqueObject(messageTextField.text, forKey: "messages")
message.saveInBackground(block: { (success, error) in
if success {
print("did it save?")
}
})
}
Everytime the button is pressed, it creates a new Objectid in the parse server dashboard. How do I make it so it uses the same ObjectId, and messages keep adding to the messages array?
Thanks,

Updating Objects
Updating an object is simple. Just set some new data on it and call
one of the save methods. Assuming you have saved the object and have
the objectId, you can retrieve the PFObject using a PFQuery and update
its data:
var query = PFQuery(className:"GameScore")
query.getObjectInBackgroundWithId("xWMyZEGZ") {
(gameScore: PFObject?, error: NSError?) -> Void in
if error != nil {
print(error)
} else if let gameScore = gameScore {
gameScore["cheatMode"] = true
gameScore["score"] = 1338
gameScore.saveInBackground()
}
More here in Parse-update-Docs

Related

Xcode Parse Query button Delete text and photo from a cell

each cell displays the according comments and photo of the user logged-on. They are loaded with parse.
Now you want to Löschen the button deletes the photo and the comments.
Unfortunately this does not work. Wen I click on the button nothing happens
Unfortunately I understand little of swift and can't get on the solution
The query works, and the app displays the photos and Commons.The query and post code:
override func viewDidLoad() {
super.viewDidLoad()
super.viewDidLoad()
let query = PFQuery(className: "Post")
query.whereKey("username", equalTo: PFUser.current()?.username)
query.findObjectsInBackground(block: { (object, error) in
if let posts = object {
for post in posts{
print(posts)
self.comments.append(post["message"] as! String)
self.imageFile.append(post["imageFile"] as! PFFile)
self.tableView.reloadData()
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
})
}
And here of the "delete"function code that I have tried:
#IBAction func remove(_ sender: Any) {
print("Entered remove")
let query = PFQuery(className: "Post")
query.whereKey("username", equalTo: PFUser.current()?.username)
query.findObjectsInBackground(block: { (object, error) in
if let posts = object {
print(posts)
for post in posts{
print(posts)
if let message = post["message"] as? String, let image = post["imageFile"] as? PFFile {
print("message and image read", message, image)
if let messageIndex = self.comments.index(of: message), let imageIndex = self.imageFile.index(of:image) {
self.comments.remove(at: messageIndex)
self.imageFile.remove(at: imageIndex)
}
}
self.tableView.reloadData()
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
})
}
The output:
I don't get an error message and nothing is deleted.
Thank you for your help
You do not have access to your current index where and object ids.
So based on that you can remove easy.
The more easy way to implement the delete function is to have an array of objectId for your messages:
self.ids.append(post.objectId)
And when you want to delete it:
let query = PFQuery(className: "Post")
query.whereKey("objectId", equalTo: self.ids.index(of: indexPath.row))
// Make a query in background to only get the object that you want to delete
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject?, error: NSError?) -> Void in
if error != nil || object == nil {
print("The getFirstObject request failed.")
} else if let object = object {
print("Successfully retrieved the object.")
object.deleteInBackground()
}
}
Having different arrays representing the same object is not really good to do. So a better way to handle you problem is have only one array for your post
When you fetch it you can do something like that:
guard let user = PFUser.current() else { return }
let query = PFQuery(className: "Post")
query.whereKey("username", equalTo: user.username)
query.findObjectsInBackground(block: { (posts, error) in
if let posts = posts {
self.posts = posts
}
})
With this way when you want to delete it in the remove function:
if indexPath.row < self.posts.count {
self.posts[indexPath.row].deleteInBackground()
}

Swift: Update Parse User (PFUser) and save image to it after new registration

I have been banging my head since yesterday. I have fetch profile picture from facebook and want to save it to parse. But I am stuck. I tried solution from this
How to update Parse user information in Swift?
That did not solved my case.
Updating user in Parse.com using Swift IOS8
I dont think this is the case, since I have just logged in. and my view changes too.
here's my code.
func updateCurrentUserProfilePicture(image: UIImage) {
let currentUser = PFUser.currentUser()
let id = currentUser?.objectId
let data = UIImagePNGRepresentation(image)
var query = PFUser.query()
query!.getObjectInBackgroundWithId(id!) {
(user: PFObject?, error: NSError?) -> Void in
if error != nil {
print(error)
} else if let usr = user {
// usr.setObject(data!, forKey: "image")
usr["image"] = data!
usr.saveInBackgroundWithBlock({ (result: Bool, error: NSError?) in
if error == nil {
self.delegate?.didUpdateProfilePictureWithResult!(true, error: error)
}else {
self.delegate?.didUpdateProfilePictureWithResult!(false, error: error)
}
})
}
}
}
I can see that didUpdateProfilePictureWithResult delegate is called with success. But when I go to back4app.com, I can see the user row but not the image column. And I dont see any error too.
What am I missing here?
Update
I tried to save in in the console. It saved without any error.
**expression do { try usr.save()} catch { print(error)}**
2016-06-10 17:29:32.264 GeofenceMe2[39334:91037] Warning: A long-running operation is being executed on the main thread.
Break on warnBlockingOperationOnMainThread() to debug.
NilError
but still no image column in my dashboaard
You cannot save NSData to parse. Checkout the valid data types here: https://parse.com/docs/ios/guide#objects-data-types.
You are querying for the user object using the same user object. You can just use PFUser.currentUser().
func updateCurrentUserProfilePicture(image: UIImage) {
let avatar = PFFile(name: PFUser.currentUser()!.username, data: UIImagePNGRepresentation(image)!)
PFUser.currentUser()!.setObject(avatar!, forKey: "avatar")
PFUser.currentUser()!.saveInBackgroundWithBlock { (success: Bool, error: NSError?) in
}
}
For Swift 5.x (based in above answer by #Santhosh):
func updateCurrentUserProfilePicture(profileImage: UIImage) {
guard let currentUser = PFUser.current(), let profileImgPngData = profileImage.pngData() else {
return
}
let avatar = PFFileObject(name: PFUser.current()!.username, data: profileImgPngData)
currentUser.setObject(avatar!, forKey: "profile_image")
currentUser.saveInBackground { success, error in
print(success, error as Any)
}
}

Check if a row exists in Parse, if it does update a column in the row instead of creating a new row each time. Swift

I have a className called SearchPreferences and it is empty until the current user makes a selection. When they make a selection a new row is created in this class with the updated info. The problem is if the user goes back and makes another selection I am creating a new row again instead of just updating the column. Here is the code that is saving the info but on a new row:`
let music = PFObject(className: "SearchPreferences")
music["music"] = table_data[indexPath.row]
// music["user"] = PFUser.currentUser()!.username!
music.saveInBackgroundWithBlock{(success, error) -> Void in
if error == nil {
music.saveInBackground()
print("success")
} else {
print("error")
}
}
`
All I can find is SQL and PHP online help. I tried the code below to call objId but I don't know it as its empty so it returns the below error.
The code below returns the error
No results matched the query. (Code: 101, Version: 1.7.5)
let query = PFQuery(className:"SearchPreferences")
query.getObjectInBackgroundWithId("musicSearch") {
(searchPreference: PFObject?, error: NSError?) -> Void in
if error != nil {
if let searchPreference = searchPreference {
searchPreference["musicSearch"] = self.table_data[indexPath.row]
searchPreference.saveInBackground()
if error == nil {
query.whereKeyDoesNotExist("musicSearch")
let searchPreference = PFObject(className: "SearchPreferences")
searchPreference["musicSearch"] = self.table_data[indexPath.row]
searchPreference.saveInBackgroundWithBlock{(success, error) -> Void in
The same can be send for this attempt:
var query = PFQuery(className:"SearchPreferences")
query.getObjectInBackgroundWithId("musicSearch") {
(searchPreference: PFObject?, error: NSError?) -> Void in
if error != nil {
print(error)
} else if let searchPreference = searchPreference {
searchPreference["musicSearch"] = self.table_data[indexPath.row]
searchPreference.saveInBackground()
}
}
I am trying to figure out how to either before running the query check if it is empty and if it is carry out my initial query. Parse docs only tell you how to save to classname _User not a second classname.
Here is an example on duplicated record update from parse community, you can use the same method to apply it with your code.
let adventureQuery = PFQuery(className: “Class Name“)
adventureQuery.limit = 1000
adventureQuery.addDescendingOrder(“Column Name”)
adventureQuery.getFirstObjectInBackground { (Success, error) in
Success?.setValue(self.toolsTitleTextField.text, forKey: "toolsTitle")
Success?.setValue(self.locationTextField.text, forKey: "location")
Success?.setValue(self.dateTextField.text, forKey: "createrDate")
Success?.saveInBackground(block: { (success, error) in
if (success){
Utility.showAlert("Success!", message: "Insert SuccessFully", viewController: self)
}
else{
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "") as! ViewController
self.navigationController?.pushViewController(viewController, animated: true)
}
})
}

how to get the currentUserInfo from _User class in Parse using Swift

I tried this:
var data:NSMutableArray = NSMutableArray()
func loadData() {
var userQuery = PFUser.query()!
userQuery.whereKey("objectId", equalTo: PFUser.currentUser()!.objectId!)
userQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if let objects = objects {
for object in objects {
self.data.addObject(object)
}
}
}
println(data) // this gives an empty NSMutableArray.
}
Is there any other way to get the data of current user? , I am doing this to make the profile Screen of the current user..Thanks for your time..
Use this to access the current user
if PFUser.currentUser() != nil {
PFUser.currentUser()!.fetchIfNeededInBackgroundWithBlock({ (user: PFObject?, error: NSError?) -> Void in
if user != nil {
var u = user as! PFUser
//Access the fetched user HERE
}
})
//NOT here, it will be nil here
}

Issues with changing existing Parse data

I am working with Parse for the first time in my application, and everything seems to be working well with the exception of when I go to change existing data. I am simply trying to change a string value that I have stored in a column of one of my items.
This is the code I currently have:
func sendTimeToParse() {
var query = PFQuery(className: "ClassName")
query.whereKey("Name", equalTo: rideNamePassed)
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject?, error: NSError?) -> Void in
if error != nil {
println("The getFirstObject request failed.")
} else {
// The find succeeded.
let object = PFObject(className: "ClassName")
object.setValue(self.timeSelected, forKey: "WaitTime")
object.saveInBackground()
println("Successfully retrieved the object.")
}
}
}
}
At the moment it just seems to create a new row of data and saves the time to that, however obviously I would like it to change the existing data in whatever row matches the name of the current record.
Anyone have any suggestions?
The problem is that you are creating a new PFObject with the line let object = PFObject(className: "ClassName") instead of using the retrieved object which is given as a parameter.
Simply delete the line let object = PFObject(className: "ClassName") and unwrap the received optional. It could look something like the following:
func sendTimeToParse() {
var query = PFQuery(className: "ClassName")
query.whereKey("Name", equalTo: rideNamePassed)
query.getFirstObjectInBackgroundWithBlock {
(object: PFObject?, error: NSError?) -> Void in
if error != nil {
println("The getFirstObject request failed.")
} else {
if let obj = object {
obj.setValue(self.timeSelected, forKey: "WaitTime")
obj.saveInBackground()
}
println("Successfully retrieved the object.")
}
}
}

Resources