How to have a nest queries in Parse in Swift - swift

I'm facing an issue with Parse.
I have three classes : Users, Posts, Likes
I'm using pointers for the Likes class User pointing to Users Class, and Post pointing to Posts class.
I'm retrieving all the posts and then I would like to see if the current user likes a post or not, and for that I'm nesting a query. the problem I have is that the posts are not updated with the like boolean value. I'm using that code :
func loaddata(limit:Int, skip:Int) {
MainFunctions.getphones{(phones) -> Void in
var indxesPath:[NSIndexPath] = [NSIndexPath]()
let query = PFQuery(className: "Feed")
query.whereKey("username", containedIn: phones)
query.limit = limit
query.skip = skip
query.includeKey("from")
query.addDescendingOrder("createdAt")
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects {
if objects.isEmpty {
}
else {
for object in objects {
let Date = object.createdAt
let post = Post(time: Date!)
let Type = object.objectForKey("type") as? String
post.Post = object
post.Post_message = object.objectForKey("Text") as? String
post.comments = object.objectForKey("commentaires") as? Int
post.likes = object.objectForKey("likes") as? Int
// See if the current user likes a post
let query_like = PFQuery(className:"Likes")
query_like.whereKey("Post", equalTo: object)
query_like.whereKey("User", equalTo: PFUser.currentUser()!)
query_like.getFirstObjectInBackgroundWithBlock{
(like: PFObject?, error: NSError?) -> Void in
if error == nil && like != nil {
post.DoILike = true
} else {
post.DoILike = false
}
}
self.posts.append(post)
indxesPath.append(NSIndexPath(forRow: self.posts.count - 1, inSection: 0))
}
self.tableView.beginUpdates()
self.tableView.insertRowsAtIndexPaths(indxesPath, withRowAnimation: UITableViewRowAnimation.Bottom)
self.tableView.endUpdates()
self.tableView.finishInfiniteScroll()
self.refreshControl.endRefreshing()
}
}
} else {
self.tableView.finishInfiniteScroll()
self.refreshControl.endRefreshing()
}
}
}
}

query_like.getFirstObjectInBackgroundWithBlock is asynchrone so when you are adding the post to the posts array self.posts.append(post) post.DoILike will get it's default value. So make sure when appending post to posts you have already get if the user liked the post or not.

Related

PFQuery adding data to tableview cells with for In Loops

I have two versions of code. Version 1 is the code I intend on using. I am trying to look up a current user's friends' in the friend array. For every friend, I want to append certain items to each array to display in a tableview cell. Version 1 incorporates a for in loop with i friends array contains: ["magellan"]. When I use a PFQuery to lookup data, it does not execute the query. However, version two is not run in a for in loop nor does it use friend. It uses the actual string "magellan" instead and works fine. What is my problem?. Thanks
Version 1:
override func viewdidload() {
for i in 0..<friendsArray.count {
friend = friendsArray[i]
print(friend)
let query2 = PFQuery(className: "CheckPost")
query2.whereKey("Username", equalTo: friend)
query2.findObjectsInBackground (block: { (objects:[PFObject]?, error: Error?) in
if let objects = objects {
for object in objects {
self.checkArray.append(object["Checks"] as! String)
self.checkArrayobjectId.append(object.objectId!);
self.checkTimeArray.append(object["UserTime"] as! String)
//append userimage
self.checkPicArray.append(UIImage(named: "randomguy")!)
print("successfully checked for friends checks")
}
} else if error != nil {
print(error)
}
})
}
Version 2:
override func viewdidload()
for i in 0..<friendsArray.count {
friend = friendsArray[i]
print(friend)
}
let query2 = PFQuery(className: "CheckPost")
query2.whereKey("Username", equalTo: "magellan")
query2.findObjectsInBackground (block: { (objects:[PFObject]?, error: Error?) in
if let objects = objects {
for object in objects {
self.checkArray.append(object["Checks"] as! String)
self.checkArrayobjectId.append(object.objectId!);
self.checkTimeArray.append(object["UserTime"] as! String)
//append userimage
self.checkPicArray.append(UIImage(named: "randomguy")!)
print("successfully checked for friends checks")
}
} else if error != nil {
print(error)
}
})
}
It looks like you are misunderstanding the async behavior of the findObjectInBackground function. This function is async and the callbacks will only be called after the loop has ended. You code should work with the find though. Something like this:
for i in 0..<friendsArray.count {
friend = friendsArray[i]
print(friend)
let query2 = PFQuery(className: "CheckPost")
query2.whereKey("Username", equalTo: friend)
let objects = query2.find()
if objects {
for object in objects {
self.checkArray.append(object["Checks"] as! String)
self.checkArrayobjectId.append(object.objectId!);
self.checkTimeArray.append(object["UserTime"] as! String)
//append userimage
self.checkPicArray.append(UIImage(named: "randomguy")!)
print("successfully checked for friends checks")
}
}
}

How do I retrieve data by using the Parse PFQuery?

Hi I'm trying to retrive data by using the PFQuery.
loadPosts in the tabelviewController.
My problem is commentsArray.
As you can see... commentsArray is not synchronized other arryas.
Because It has different db's class.
I want get all the data arrays to set the uilabel's text synchronizing
How do I achieve that?
I also had trying to parse's synchronized method. but It is really slow.
Here is my code. This function in the TableViewController.
func loadPosts() {
//STEP 1. Find posts related to people who we are following
let followQuery = PFQuery(className: "fans")
followQuery.whereKey("myfans", equalTo: PFUser.currentUser()!.username!)
followQuery.findObjectsInBackgroundWithBlock ({ (objects:[PFObject]?, error:NSError?) -> Void in
if error == nil {
//clean up
self.followArray.removeAll(keepCapacity: false)
//Appending where people following..
//find related objects
for object in objects! {
self.followArray.append(object.objectForKey("fan") as! String)
}
//append current user to see own posts in feed
self.followArray.append(PFUser.currentUser()!.username!)
//STEP 2. Find posts made by people appended to followArray
let query = PFQuery(className: "posts")
query.whereKey("username", containedIn: self.followArray)
query.limit = self.page
query.addDescendingOrder("createdAt")
query.findObjectsInBackgroundWithBlock({ (objects:[PFObject]?, error:NSError?) -> Void in
if error == nil {
//clean up
self.usernameArray.removeAll(keepCapacity: false)
self.profileArray.removeAll(keepCapacity: false)
self.dateArray.removeAll(keepCapacity: false)
self.postArray.removeAll(keepCapacity: false)
self.descriptionArray.removeAll(keepCapacity: false)
self.uuidArray.removeAll(keepCapacity: false)
//For Test
self.commentsArray.removeAll(keepCapacity: false)
self.isTappedLikeArray.removeAll(keepCapacity: false)
//find related objects
for object in objects! {
self.usernameArray.append(object.objectForKey("username") as! String)
self.profileArray.append(object.objectForKey("profileImg") as! PFFile)
self.dateArray.append(object.createdAt)
self.postArray.append(object.objectForKey("postImg") as! PFFile)
self.descriptionArray.append(object.objectForKey("title") as! String)
self.uuidArray.append(object.objectForKey("uuid") as! String)
//STEP 3.
//Check Comment
let countQuery = PFQuery(className: "comments")
countQuery.whereKey("to", equalTo: object.objectForKey("uuid") as! String)
countQuery.limit = 1
countQuery.addAscendingOrder("createdAt")
countQuery.countObjectsInBackgroundWithBlock({(count:Int32, error:NSError?) -> Void in
//if no any likes are found, else found likes
if count==0 {
self.commentsArray.append("")
}else{
let commentQuery = PFQuery(className: "comments")
commentQuery.whereKey("to", equalTo: object.objectForKey("uuid") as! String)
commentQuery.limit = 1
commentQuery.addDescendingOrder("createdAt")
commentQuery.findObjectsInBackgroundWithBlock({(objects:[PFObject]?, error:NSError?) -> Void in
if error == nil {
//clean up
//find related object
for object in objects!{
let comment = object.objectForKey("comment") as! String
let by = object.objectForKey("username") as! String
let commentString = by + " " + comment
self.commentsArray.append(commentString)
}
//reload tableView & end spinning of refresher
self.tableView.reloadData()
self.refresher.endRefreshing()
}else {
print(error?.localizedDescription)
}
})
}
})
}
} else {
print(error!.localizedDescription)
}
})
} else {
print(error!.localizedDescription)
}
})
}

Parse data in swift

I have a "Users" table and a "cDetails" table. Inside cDetails table I have a field called "full_name". I am trying to retrieve and output the value in this table based on the current user that is logged in.
In the cDetails table I have a field called "createdBy" which points to the objectID in the Users table that created it.
This is all I have so far:
let query = PFQuery(className: "cDetails")
let currentUser = PFUser.currentUser()
query.includeKey("full_name")
query.whereKey("createdBy", equalTo: currentUser!.objectId!)
print("CREATED BY " + PFUser.currentUser()!.objectId!);
query.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
if objects == nil {
print(objects)
print("called")
// self.full_nameLabel.text = "\(query)"
} else {
print("FAILED")
}
}
My approach:
let query = PFQuery(className: "cDetails")
let currentUser = PFUser.currentUser()
query.includeKey("full_name")
query.whereKey("createdBy", equalTo: currentUser!.objectId!)
print("CREATED BY " + PFUser.currentUser()!.objectId!);
query.findObjectsInBackgroundWithBlock {
(objects, error) -> Void in
if **objects == nil** {
print(objects)
print("called")
// self.full_nameLabel.text = "\(query)"
} else {
print("FAILED")
}
}
You are looking whether objects == nil. You want to have your error == nil and your objects != nil
After that proceed with
for object in objects {
let fullName = object["full_name"] as! String
}

[Error]: No results matched the query. (Code: 101, Version: 1.12.0) in Parse using Swift

I keep getting this error when trying to update a PFObject '[Error]: No results matched the query. (Code: 101, Version: 1.12.0)' here is my code:
let userQuery = PFQuery(className: "User")
userQuery.getObjectInBackgroundWithId("cE3DE48Fa9") {
(userQueryObject: PFObject?, error: NSError?) -> Void in
if error != nil {
print(error)
}
else if let userQueryObject = userQueryObject {
userQueryObject["House_Motto"] = self.campaignMottoTextBox.text
userQueryObject.saveInBackground()
} }
What do I do?
Here is my new code:
currentUser!.setObject(self.campaignMottoTextBox.text!, forKey: "House_Motto")
Here is an example of how to use PFUser.query() to query the user class in parse, note my example uses findObjectsInBackgroundWithBlock(), rather than getObjectsInBackgroundWithId()
var userData1 = [String]()
var userData2 = [Double]()
var allUsers = [PFUser]()
func fetchUserData() {
let userQuery: PFQuery = PFUser.query()!
userQuery.orderByAscending("username")
userQuery.whereKey("username", notEqualTo: (currentUser?.username)!)
userQuery.findObjectsInBackgroundWithBlock({
(users, error) -> Void in
var userData = users!
if error == nil {
if userData.count >= 1 {
for i in 0...users!.count-1 {
self.userData1.append(userData[i].valueForKey("columnNameInParse1") as! String)
self.startTimes.append(userData[i].valueForKey("ColumnNameInParse2") as! Double)
}
}
self.allUsers = users as! [PFUser]
self.tableView.reloadData()
} else {
print(error)
}
})
}
and in order to update a value for a given user you will do...
func updateObjectInParse(){
currentUser?.setObject(campaignMottoText.text, forKey: "columnNameInParse")
currentUser?.saveInBackground()
}
where "columnNameInParse" is the name of the column for the object of which you want to update in parse. This is case sensitive. And currentUser is the PFUser.currentUser

How can I return my string in swift by using parse?

func getParse (className:String,key:String,dataName:AnyObject) -> (String)
{
var result = String()
var query = PFQuery(className: className)
query.whereKey(key, equalTo: dataName)
query.findObjectsInBackgroundWithBlock{
(objects, error) -> Void in
if error == nil {
println("Found")
if let objects = objects as? [PFObject] {
for object in objects {
result = object[key] as! String
}
}
} else {
println("Error \(error) \(error!.userInfo!)")
}
}
return result
}
This is my function that can getting data from my class in parse database. I want to return that data in String but it returned nothing when I try to printed it.
Thank you for every comments.
You are using an asynchronous call. You need to use findObjects(), but this will stay on the main thread. Why do you need to return a string? You could set a variable from within the completion block that could update a label on your view or something like that.
Edit: Since you are trying to set a label, you don't need to return the string, you should just set the label from within your completion block. This would modify you're given code as follows:
func getParse (className:String,key:String,dataName:AnyObject)
{
var result = String()
var query = PFQuery(className: className)
query.whereKey(key, equalTo: dataName)
query.findObjectsInBackgroundWithBlock{
(objects, error) -> Void in
if error == nil {
println("Found")
if let objects = objects as? [PFObject] {
for object in objects {
// result = object[key] as! String
self.textLabel.text = result // NEW CODE HERE
}
}
} else {
println("Error \(error) \(error!.userInfo!)")
}
}
}