PFQuery adding data to tableview cells with for In Loops - swift

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

Related

PFQuery returning blank query

I'm trying to run a PFQuery that will populate an array of custom structs.
Everything looks ok, but when I run the code the query returned is empty. I also tried this using PFUser.Query, which worked, but did not return a value for objectId, so tried to query the class instead.
Here is what I have:
var parseUsers:[ParseUsers] = []
var allUsers:[PFObject] = []
let query = PFQuery(className:"User")
let currentUser = PFUser.current()
query.whereKey("username", notEqualTo: currentUser?.username)
do {
allUsers = try (query.findObjects())
for i in allUsers{
var pImage = UIImage()
if i["profileImage"] != nil{
let imageFile = i["profileImage"] as? PFFileObject
imageFile?.getDataInBackground { (imageData: Data?, error: Error?) in
if let error = error {
print(error.localizedDescription)
} else if let imageData = imageData {
pImage = UIImage(data:imageData)!
}
}
}
let currentUserInfo = ParseUsers(objectID:i["objectId"] as! String,
username:i["objectId"] as! String,
userWorkouts:i["userWorkouts"] as! [Dictionary<String, String>],
profileImage:pImage)
parseUsers.append(currentUserInfo)
}
} catch {
print("Error")
}
Found out what the problem was!
For anyone experiencing similar issues in the future, when determining the class you want to query, you need to out _ in front. In the case above it would be let query = PFQuery(className:"_User").
Weird, as I couldn't see this mentioned in the parse documentation anywhere.
As mentioned by #William George in the Querying subsection of Users you can see how to construct a query on on the _User class.
A Below is an example of this (lifted straight from the docs):
var query = PFUser.query()
query.whereKey("gender", equalTo:"female")
var girls = query.findObjects()
You can query your Parse Server with PFUser just like with PFQuery but it can only be used on the _User class.

Swift & Parse - Am trying to retrieve a username with a query.

I am trying to retrieve the username belonging to a post. The username can be found in another class however.
These are the two classes I have:
Post
User
I am populating all the information from the Posts class in a UICollectionView but since the username is in the User class my query is not working. Here's my code...
//QUERY LOST
let querylost = PFQuery(className: "Post")
querylost.order(byDescending: "createdAt")
querylost.whereKey("lostfound", equalTo: "lost")
querylost.findObjectsInBackground { (objects, error) in
if let posts = objects {
for post in posts {
self.addresslost.append(post["address"] as! String)
self.breedlost.append(post["breed"] as! String)
self.phonelost.append(post["phone"] as! String)
self.imageFileslost.append(post["imageFile"] as! PFFile)
//HERE'S THE PROBLEM - username is in User Class
self.usernames.append(self.queryusers[post["userid"] as! String]!)
//ENDS here
self.lostCollectionView.reloadData()
self.refresherLost.endRefreshing()
}
}
}
//TO SHOW DATA
scrollView.delegate = self
lostCollectionView.delegate = self
lostCollectionView.dataSource = self
}
Instead of using the userid field, you should create a pointer to put on your Post object instead. Then you can access the User object via the Post object.
Your code would look something like this:
let querylost = PFQuery(className: "Post")
querylost.order(byDescending: "createdAt")
querylost.include("user")
querylost.whereKey("lostfound", equalTo: "lost")
querylost.findObjectsInBackground { (objects, error) in
if let posts = objects {
for post in posts {
self.addresslost.append(post["address"] as! String)
self.breedlost.append(post["breed"] as! String)
self.phonelost.append(post["phone"] as! String)
self.imageFileslost.append(post["imageFile"] as! PFFile)
//unwrap the user pointer, and get the username
if let user = post["user"] as? PFUser, let username = user.username{
self.usernames.append(username)
}
//ENDS here
self.lostCollectionView.reloadData()
self.refresherLost.endRefreshing()
}
}
}

How to have a nest queries in Parse in 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.

How to get all data for current user using Parse in Swift?

İ have a Parse app. İ want to get data from Parse class or database but for current user.
This is a poorly asked question, you provide no code nor do you show any effort on your own part to solve the problem. However, I myself remember struggling with this quite a but so here is how I accomplish this...
var arrayForData = Array()
var arrayForMoreData = Array()
var arrayForEvenMoreData = Array()
func fetchUserData() {
let userQuery: PFQuery = PFUser.query()!
userQuery.whereKey("username", equalTo: (currentUser?.username)!)
userQuery.findObjectsInBackgroundWithBlock({
(users, error) -> Void in
var someData = users!
var someMoreData = users!
var thirdSetOfData = users!
if error == nil {
if someData.count >= 1 {
for i in 0...users!.count-1 {
self.arrayForData.append(someData[i].valueForKey("columnNameParse1") as! Int)
self.arrayForMoreData.append(someMoreData[i].valueForKey("columnNameParse2") as! Double)
self.arrayForEvenMoreData.append(thirdSetOfData[i].valueForKey("columnNameParse3") as! String)
}
}
self.usersArray = users as! [PFUser]
self.tableView.reloadData()
} else {
print(error)
}
})
}

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