How to prevent Parse from saving children PFObject?

I ran into a very common problem with Parse and iOS.

I have a POST class with the following structure:

  • text(String)
  • Image (PFFile)
  • LikesUsers (Array of String)
  • LikesCount (Int)
  • From (Pointer to User who posted it)

and if the user (already logged in) likes the message. I just increase the number of likes and add the user Objectid to the array

For example: User-2 likes the message User-1.

 PostObject.incrementKey("Likes") PostObject.addObject((PFUser.currentUser()?.objectId)!, forKey: "LikesUsers") PostObject.saveEventually() 

The problem is here. I cannot save a PostObject if it has a pointer to another user (than logged in). I get an error message:

A user cannot be saved if he has not been authenticated through logIn or Registration

So, how to prevent saving ParseObject Children ("From")

I do not want to use CloudCode, I want to keep it simple and use SaveEventually for a better user experience.

+7
ios swift pfobject
source share
3 answers

From the parse.com forums:

When you save an object with a pointer, Parse looks at the entire object and saves the fields that are dirty (changed since the last save). It also checks all objects pointed to by pointers. If your object has a pointer to PFUser and the PFUser instance is dirty, then Parse will save the object and then try to save the PFUser instance. My hypothesis is that somewhere in your code you are setting a value for the user and then not saving the user. This, I suspect, is the source of your error. Browse your code and look wherever you install the PFUser instance, and make sure there is a corresponding save. If you cannot find it at first glance, be sure to check all the blocks and make sure that you do not pollute the user asynchronously and then try to save it.

Are you trying to make any changes to the user that the message was created?

+2
source share

Short answer:

Try setting the from field to:

 let author = PostObject["from"] as! PFObject PostObject["from"] = PFObject(withoutDataWithClassName: "_User", objectId: author.objectId) 

This is not verified.

But I suggest you change the architecture

I ran into the same problem and finally decided to move the likes field to the User class and make it Relation<Post> . The analysis documentation states that the Relation type is better for storing many objects. Since LikesUsers is an array of objects, performance can be significantly reduced if the message receives a lot of views: the application will download all users who liked this post. See This for more information: https://parse.com/docs/ios/guide#objects-relational-data

Here's what my class structure (simplified) looks like:

User:

  • postLikes (Attitude)

Message:

  • author (PFObject)
  • likesCount (Int)

I also used logic / dislike for the CloudCode function:

 /// The user liked or disliked the post. Parse.Cloud.define("likeDislikePost", function(request, response) { var userProfileId = request.params.userProfileId var postId = request.params.postId // Shows whether the user liked or disliked the post. Bool value var like = request.params.like var query = new Parse.Query("_User"); query.equalTo("objectId", userProfileId); query.first({ success: function(userProfile) { if (userProfile) { var postQuery = new Parse.Query("Post"); postQuery.equalTo("objectId", postId); postQuery.first({ success: function(post) { if (post) { var relation = userProfile.relation("postLikes"); if (like) { relation.add(post); post.increment("likesCount"); } else { relation.remove(post) post.increment("likesCount", -1); } post.save(); userProfile.save(); console.log("The user with user profile id " + userProfileId + " " + (like ? "liked" : "disliked") + " the post with id " + postId); response.success(); } else { response.error("Unable to find a post with such ID"); } }, error: function() { response.error("Unable to like the post"); } }); } else { response.error("Unable to find a user profile with such ID"); } }, error: function() { response.error("Unable to like the post"); } }); }); 

It works well.

+2
source share

I created a project for you from scratch. I think you will miss something when you create your PFClass. I dont know. Whatever my codes look like

This is a ViewController , and it contains an Action button;

  import UIKit class ViewController: UIViewController { private let test = Test() // PFObject SubClass private let post = Post() // PFObject SubClass @IBAction func likeButton() { self.test.fromUser = PFUser.currentUser() // Current User self.test.likedUsers.append(Post().user // In there your post should be a Subclass of PFObject too like your this Test class and it should be contains Owner property. So you can grab the Post owner PFUser or User Object ID.) self.test.saveEventually() { (let success, error) in if error == nil { // Success } else { print(error?.localizedDescription) } } } } 

In AppDelegate init, your ParseSDK and Register new Parse subclasses.

  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { // Override point for customization after application launch. Parse.setApplicationId("YOUR_API_KEY", clientKey: "YOUR_CLIENT_KEY") Test.registerSubclass() Post.registerSubclass() return true } 

Test Subclass ;

 import Foundation import Parse class Test: PFObject, PFSubclassing { // Your Properties @NSManaged var likedUsers: [PFUser] @NSManaged var fromUser: PFUser static func parseClassName() -> String { return "Test" // Your Class Name } } 

Message Subclass ;

  class Post: PFObject, PFSubclassing { // Your Properties @NSManaged var owner: PFUser @NSManaged var likeCount: NSNumber static func parseClassName() -> String { return "Post" // Your Class Name } } 

In my case, this works fine. If you get an error message, let me know.

Have good coding.

0
source share

All Articles