How to add PFObjects to a tableview in swift - ios

I am building a checkin app, and am having trouble filling my tableview with guests stored using Parse. I get an error when trying to append the objects. I also have a user login that I followed from a Udemy course. In the course he showed how to display PFUsers, but I can't get it to work using PFObjects. Any help would be great on this.
Here is the working code with PFUsers.
var users = [""]
override func viewDidLoad() {
super.viewDidLoad()
var query = PFUser.query()
query!.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
self.users.removeAll(keepCapacity: true)
for object in objects! {
var user:PFUser = object as! PFUser
self.users.append(user.username!)
}
self.tableView.reloadData()
})
}
And here is the nonworking code with PFObjects.
var users = [""]
override func viewDidLoad() {
super.viewDidLoad()
var query = PFQuery(className: "TestObject")
query.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
self.users.removeAll(keepCapacity: true)
for object in objects! {
var guest = object as! PFObject
self.users.append(guest.foo!)
}
})
}
The error shows on the line
self.users.append(guest.foo!)
And the error says "'PFObject' does not have a member named 'foo'"

You define your PFUser object with the variable user, this will make the first example work (you get the name of the user) The second example doesn’t work cause you still define the PFObject as user but try to access the name of guest which is not defined.
You could either go with the first example or change
var user:PFObject = object as! PFObject
With
var guest:PFObject = object as! PFObject
Either way, it doesn’t matter for your code, it is just the name of the variable.
This explanation will fix your “Use of unresolved identifier ‘guest’”
But this isn’t your only problem,
the PFUser object which the first example uses is a special kind of a PFObject, the PFUser class does have a .name which refers to (obviously) the name of the user. Not every PFObject has a name though so you can’t just access the .name of a PFObject. Parse has an excellent documentation about retrieving objects I would first access this documentation. If this is still unclear to you, you can open another specific question about your new problem.
To retreive the data from an object you need to use []
Let’s suggest we have a class named gameScore with the following info
score: 1337, playerName: “Sean Plott”, cheatMode: false
We would do that as follows
var gameScore = PFObject(className:"GameScore")
gameScore["score"] = 1337
gameScore["playerName"] = "Sean Plott"
gameScore["cheatMode"] = false
gameScore.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
To retrieve the object you need to query (as you already did in your post)
Ones you’ve received the data you can extract it as follows:
let score = gameScore["score"] as Int
let playerName = gameScore[“playerName"] as String
let cheatMode = gameScore["cheatMode"] as Bool

I figured it out, I needed to get the object label as a string before I could append it to the array to then add it to the tableview.
Here is the working code:
var users = [""]
override func viewDidLoad() {
super.viewDidLoad()
var query = PFQuery(className: "TestObject")
query.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
self.users.removeAll(keepCapacity: true)
for object in objects! {
var foo = object.objectForKey("foo") as? String
self.users.append(foo!)
}
self.tableView.reloadData()
})
}

Related

Make a Query with a Pointer in Parse and Swift

I'm trying to make a Query with a Pointer in Parse.
Basically I have two classes "commentsTable" and "_User", I want to get the comment of the user from class "commentsTable" on a determined post, and then get the username and the profile_pic from the class "_User"
_User Class
commentsTable Class
func loadAndShowComments(){
let query2 = PFQuery(className: "commentsTable")
query2.orderByDescending("createdAt")
query2.whereKey("newsColumns", equalTo: printteste!)
query2.includeKey("username")
query2.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if let objects = objects as [PFObject]? {
for object in objects {
print(object["commentColumn"])
}
}
for cardset in objects! {
var lesson = cardset["username"] as! PFObject
var name = lesson["username"] as! String
print("By user: \(name)")
}
I'm able to see the query, I print the result an I have the following output:
This is a post!
This is a test post!
By user: teste#teste.com
By user: mmachado
And in my app I display this informations inside a TableView, I'm successfully can show the results for the Query in the func cellForRowAtIndexPath:
if let usuarioComentario = object?["commentColumn"] as? String {
cell?.usuarioComentario?.text = usuarioComentario
}
But I'm no able to return the values of my other class, _User
I think I misunderstood some concept but at this point I don't know what concept, any ideas?
Thanks.
By using query2.includeKey("username") you are already retrieving all of the User data associated with each commentsTable object.
You can access the related User data using the following.
if let commentUser = object["username"] as? PFUser {
let name = commentUser["username"] as! String
let profilePicture = commentUser["profile_pic"] as! PFFile
}
You need to store the query results to an array for later use if you aren't already. If you are using Parse's provided PFQueryTableViewController this will be handled for you by implementing the queryForTable() method and the results are automatically stored in an array of dictionaries called objects.
It is also worth noting that you will have to still have to load the PFFile because they are not included in query results. You will want to assign the PFFile to a PFImageView and then call loadInBackground. See the example below.
let imageView = PFImageView()
// Set placeholder image
imageView.image = UIImage(named: "placeholder")
// Set remote image
imageView.file = profilePicture
// Once the download completes, the remote image will be displayed
imageView.loadInBackground { (image: UIImage?, error: NSError?) -> Void in
if (error != nil) {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
} else {
println("image loaded")
}
}
Lastly, I'd recommend changing the name of the User pointer within commentsTable from "username" to "user" so there is no confusion with the username field of the user class. Here's a link to a great tutorial which you may also find helpful

Retrieve the userInfo using Pointer. Parse

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

findObjectInBackgroundWithBlock nested ios

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)

Using parse to query info in Swift

I am currently trying to implement a parse database into a Swift app. I am having trouble understanding how to use the data, when you query from parse. Here is a query I am using:
var query = PFQuery(className: "CompanyInfo")
query.findObjectsInBackgroundWithBlock({
(objects: [AnyObject]! , error: NSError!) -> Void in
if error == nil{
println("Successfully retrieved \(objects.count) specials.")
println(objects[0])
}else{
println(error)
}
})
So I know this works because it prints out all the data to the console.
Then when I do the objects[0] it prints out the first.
How would I use the objects to set data into my app? For instance, if I have a title section in my parse class CompanyInfo, how do I get that information for later on?
To get the objects as PFObjects just cast them..
query.findObjectsInBackgroundWithBlock({
(objects: [AnyObject]! , error: NSError!) -> Void in
var myPFObjects = objects as? [PFObject] // now you have your array of pfobjects
})
To get any attribute/column of a pfobject just call it like this
var aPFObject = myPFObjects[0]
var title = aPFObject["title"] as? String
A better way to do all these things is to subclass the pfobject and get them via class properties, which would make following code:
The subclass..
class CompanyInfo: PFObject, PFSubclassing {
var title: String? {
get {
return self["title"] as? String
}
set {
self["title"] = newValue
}
}
class func parseClassName() -> String! {
return "CompanyInfo"
}
}
and the code where you call the query:
var cpQuery = CompanyInfo.query()
cp.findObjectsInBackgroundWithBlock({
(objects: [AnyObject]! , error: NSError!) -> Void in
var myCompanyInfos = objects as? [CompanyInfo] //Directly cast them to your objects
for cp in myCompanyInfos {
println(cp.title) //print all the titles
}
})

'String"does not have a member named 'category

Here is what I'm trying, basically to query the key "categories" of the class "event" for only the current user:
class AllEntriesTableViewController: UITableViewController {
var allEntries = [""]
override func viewDidLoad() {
super.viewDidLoad()
var user = PFUser.currentUser()
var query = PFQuery(className:"event")
query.whereKey("user", equalTo: user)
query.includeKey("category")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
// The find succeeded.
self.allEntries.removeAll(keepCapacity: true)
// Do something with the found objects
for object in objects {
var allEnt:String = object as String
self.allEntries.append(allEnt.category)
}
} else {
// Log details of the failure
NSLog("Error: %# %#", error, error.userInfo!)
}
}
It looks like you're expecting allEnt to be a String and not an event.
var allEnt:String = object as String
self.allEntries.append(allEnt.category)
You should be creating allEnt as event vars instead if you are intending to access allEnt.category as a property on event. Perhaps you have forgotten a lookup of some kind? Something like:
convertToEvent(allEnt)
self.keyToEventDictionary[allEnt]
Or is it possible that your objects list is actually a list of category results and you should just be doing:
self.allEntries.append(allEnt)

Resources