I am calling the following function in the viewDidLoad of my collection view controller. I am trying to retrieve a value from the User class of my parse server. My problem is that the for loop is not being called which is not allowing the string value to be retrieved from the column and stored in the array.
func loaduuid(){
let query = PFQuery(className: "_User")
query.whereKey("uuid", equalTo: guestname.last!)
query.findObjectsInBackgroundWithBlock ({ (objects:[PFObject]?, error:NSError?) -> Void in
if error == nil {
print("no error")
for object in objects!{
// add found data to arrays
self.newuuid.append(object.valueForKey("uuid") as! String)
print("uuid added")
}
}
else {
print(error?.localizedDescription)
}
})
}
Why is my for loop not being called and how can I fix this?
You should try to print(objects!.count) to see if the array of PFObjects is empty, that might be why is not iterating through the array. If it prints 0, it means that your query is not finding any results on the server.
If the user is logged in you have every information of his row from _User class in local device, you can access it with
let uuid = PFUser.currentUser()!["uuid"] as! String
or if there are some updated values in _User row you can use
PFUser.currentUser()?.fetchInBackgroundWithBlock...
Related
How can I fetch data for user which I want.
For this I want use text field where I write username, and button which will load all information about user.
Now my code load all user from data base:
let query = PFUser.query()
query?.findObjectsInBackground(block: { (object, error) in
for objects in object! {
let user = objects["username"] as! String
print(user)
}
})
How I can make it for user which I want?
You could filter the users locally like this:
query?.findObjectsInBackground {(objects, error) in
let users = objects as? [PFUser]
for object in (users!.filter { $0.username == something }) {
// do something
}
}
But that's a pretty bad idea because your list of users might be huge and this is wildly inefficient. If you're using PFQuery, you might want to add a constraint:
let query = PFUser.query()
query.whereKey("username", equalTo: something)
Now, when you call findObjectsInBackground, you'll only get relevant results.
You are getting user list in object at:
query?.findObjectsInBackground(block: { (object, error) in
Put a where clause in for loop, to get a single user by matching your required username as:
for objects in object! where (objects["username"] as! String) == "Your_Text_Field.text" {
print(objects)
let userName = objects["username"] as! String
print(userName)
}
If you don't want to match exact name rather you want to get a list of user by searching with entered text, then you can apply filter:
query?.findObjectsInBackground {(object, error) in
if let users = object as? [PFUser] {
let filteredUsers = users.filter { $0.username.contains("Your_Text_Field.text") }
print(filteredUsers)
}
}
I've made a function that creates a "favorite" object back in parse with the tap of a favorite button on the UI :
//MARK: Create the favorite object
func createFavorite(){
let currentUser = PFUser.currentUser()
let currentBook = PFObject(withoutDataWithClassName: "Books", objectId: objectIdSelected)
let favorite = PFObject(className:"Favorites")
favorite["user"] = currentUser
favorite["books"] = currentBook
favorite.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// success
} else {
// There was a problem, check error.description
}
}
}
Now I am attempting to create a query that checks to see if a favorite object with those exact properties exists using the following logic, I've placed it in the viewDidLoad of a VC that shows a specific book:
//MARK: Check if there is a favorite object available
func isFavoritedByUser(){
let currentUser = PFUser.currentUser()
let currentBook = PFObject(withoutDataWithClassName: "Books", objectId: objectIdSelected)
let query = PFQuery(className:"Favorites")
query.whereKey("user", equalTo: currentUser!)
query.whereKey("books", equalTo: currentBook)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if objects != nil {
print("this book was favorited by this user")
} else if objects == nil {
print("this book WAS NOT favorited by this user")
} else if error == nil {
// succeed
} else if error != nil {
// There was a problem, check error.description
}
}
}
However, even if no favorite object with those properties exists back in my parse class, it still prints "this book was favorited by this user".. what am i missing here?
The list existing is not proof. That simply proves that some kinda of error weren't observed.
You should check that there was no error first, then you should check that the list of objects has one item in it.
If the list has more than one item then you're creating duplicates and you should fix that...
What you're getting returned is an array, as long as there isn't an error. So, rather than checking for nil, you should be checking the content of the returned array (objects) to see if there is anything in there.
In Parse's guide, you can see what they recommend for this function call:
https://parse.com/docs/ios/guide#queries
Additionally, Parse recommends considering getFirstObjectInBackground instead if this query only ever needs to return a single object, so that might be something to consider as an alternative.
So the problem was i was checking to see if object was nil rather then checking for the count, here is the correct code:
//MARK: Check if there is a favorite object available
func isFavoritedByUser(){
let currentUser = PFUser.currentUser()
let currentBook = PFObject(withoutDataWithClassName: "Books", objectId: objectIdSelected)
let query = PFQuery(className:"Favorites")
query.whereKey("user", equalTo: currentUser!)
query.whereKey("books", equalTo: currentBook)
query.findObjectsInBackgroundWithBlock { (object, error) -> Void in
if error == nil {
if object?.count > 0{
print("this book was favorited by this user")
} else {
print("this book WAS NOT favorited by this user")
}
} else {
}
}
}
For iOS, you can just check the dictionary on an object like so:
rideParse["driver"] == nil
If it exists, then you will get the pointer. If it doesn't/you did not query to include the pointer, then it will just return nil.
I am building and app that saves an object in the local datastore with parse. I then run a query to retrieve the objects that are in the local datastore and it is working fine. however, I would like to grab the object, and the contents in it, and set some labels in a table view cell based on the items that are stored in the parse local data store object. for example, i make an object with attributes like "objectID", "name", "date", "location". what i'd like to do is to have a table view on the home screen that displays the name, date, location ...etc. of each item that was saved in local datastore in labels in each cell.
i know that im saving it correctly:
// parse location object
let parseLighthouse = PFObject(className: "ParseLighthouse")
parseLighthouse.setObject(PFUser.currentUser()!, forKey: "User")
parseLighthouse["Name"] = self.placeTitle.text
parseLighthouse["Note"] = self.placeNote.text
parseLighthouse["Locality"] = self.placeDisplay.text!
parseLighthouse["Latt"] = self.map.region.center.latitude
parseLighthouse["Longi"] = self.map.region.center.longitude
parseLighthouse["LattDelta"] = 0.5
parseLighthouse["LongiDelta"] = 0.5
parseLighthouse["Date"] = dateInFormat
parseLighthouse.pinInBackground()
parseLighthouse.saveInBackgroundWithBlock { (success: Bool, error: NSError?) -> Void in
println("Object has been saved. ID = \(parseLighthouse.objectId)")
}
and when i run the query, im able to access the attributes by running println(object.objectForKey("Name"))
func performQuery() {
let query = PFQuery(className: "ParseLighthouse")
query.fromLocalDatastore()
query.whereKey("User", equalTo: PFUser.currentUser()!)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) lighthouses.")
// Do something with the found objects
if let light = objects as? [PFObject] {
for object in light {
println(object.objectId)
println(object.objectForKey("Name"))
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
because when running the query, i get back the object id and name as expected.
Successfully retrieved 2 lighthouses.
Optional("A3OROVAMIj")
Optional(happy)
Optional("bbyqPZDg8W")
Optional(date test)
what I would like to do is grab the name field within the parse object local data store, and that be the name of the label on a cell in a table view controller.
i dont know how to access that info from the object, and set the label correctly.
does anyone know how this is possible?
It's always a good idea to avoid pointer lol ... so why not saving the userid or username with the specific object..
so change this line:
parseLighthouse.setObject(PFUser.currentUser()!, forKey: "User")
TO
parseLighthouse["username"] = PFUser.currentUser().username
Answer
NOW let's create a struct that contains the objectID and the Name outside of your Controller Class.
struct Data
{
var Name:String!
var id:String!
}
then inside of the Controller class, declare the following line of code globally
var ArrayToPopulateCells = [Data]()
Then your query function will look like :
func performQuery() {
let query = PFQuery(className: "ParseLighthouse")
query.fromLocalDatastore()
query.whereKey("User", equalTo: PFUser.currentUser()!)
query.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(objects!.count) lighthouses.")
// Do something with the found objects
if let light = objects as? [PFObject] {
for object in light {
print(object.objectId)
print(object.objectForKey("Name"))
var singleData = Data()
singleData.id = object.objectId
singleData.Name = object["Name"] as! String
self.ArrayToPopulateCells.append(singleData)
}
}
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
}
In the tableView numberOfRowinSection()
return ArrayToPopulateCells.count
In the cellForRowAtIndexPath()
var data = ArrayToPopulateCells[indexPath.row]
cell.textlabel.text = data.objectID
cell.detailLabel.text = data.Name
VOila that should be it
I have a class called Posts in which i've postedBy column where i am saving the PFUser.currentUser() (pointer). so i want to retrieve the username, profile picture and stuff from the _User class using postedBy in the Posts class. What is the shortest and efficient way to achieve this? i am not much familiar with relation queries.
I believe that instead of saving the user pointer, you should save the user's username then it comes easier for you to retrieve everything.
var query = PFQuery(className:"Posts")
var username = PFUser.currentUser()?.username
query.whereKey("username", equalTo: username!)
query.findObjectsInBackgroundWithBlock { (objects:[AnyObject]?, error:NSError?) -> Void in
if error == nil
{
if let objects = objects as? [PFObject]
{
for one in objects {
var pictureImage = one["theFile"] as! PFFile
pictureImage.getDataInBackgroundWithBlock({ (dataToget:NSData?, error:NSError?) -> Void in
if error == nil {
if let Image = UIImage(data: dataToget!){
// then you have the image
// save the image to array
// reload the tableview
}
}
})
}
}
}
}
I am developing app using ios, swift and parse.com as backend.
My problem is I need one query object result in second query object like below code. but when i use below code GUI become unresponsive for some time because of findObjects() method. I have used findObjectsInBackgroundWithBlock() instead but than tableview self.posts display only one record in tableview. I have 10 record in post table.
Can you guide me proper way how to resolve below issue.Actually I does not want to use findObjects() method.
var query = PFQuery(className:"Post")
var fquery = PFQuery(className: "Friends")
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
let user = PFUser.currentUser()
if let objects = objects as? [PFObject] {
for object in objects {
friendArray.removeAll(keepCapacity: false)
fquery.whereKey("whosefriend", equalTo: object["postusername"])
var fobjects = fquery.findObjects()
for fobject in fobjects {
friendArray.append(fobject["friendname"] as String)
}
if (contains(friendArray, user["fullname"] as String)) {
let post = Post(.......)
self.posts.append(post)
}
}
}
self.tableView.reloadData()
} else {
println("Error: \(error) \(error.userInfo!)")
}
}
One option is to make your "postusername" a pointer column in class Post that points to Friends class and then you would only need one query that would go something like:
var query = PFQuery(className:"Post")
query.includeKey("postusername") //this would include the object that it points to i.e. the Friends object you saved there
... then in your for loop ...
for object in objects! {
let friend = object["postusername"] // now friend is the Friends object
let friendName:String = friend["friendname"] as? String
friendArray.append(friendName)
}
Note: this requires you saving "postusername" as a PFObject of Class Friends. Parse iOS docs explain this well.
https://parse.com/docs/ios/guide
I have resolve the issue by using relational query.
var query = PFQuery(classWithName: "Post")
var fQuery = PFQuery(className:"Friends")
fQuery.whereKey("friendname", equalTo: cuser["fullname"])
query.whereKey("postusername", matchesKey:"whosefriend", inQuery:fQuery)