0

In my app each user sets up a profile page and all this info is stored on Parse. When the current user hits a button it segues to a tableViewController that displays in cells all the other users on the app. In each cell there is a button which the user presses to view the full profile page of the user that they have selected. I have a VC set up to hold all the info I just don't know how to display the particular user that the current user has selected into it. How do I single out the chosen users information? I have read the Parse documentation on relational queries but I can't seem to get my head around it. https://parse.com/docs/ios/guide#queries-relational-queries

So in finer detail basically all my users are displaying on a VC. It has name and profile picture, when the user clicks on the info button beside a certain user it should open a new screen and display all of this users information stored on Parse.

I have tried creating a static outside the class

struct Data { var OtherName:String! var id:String! }

And then in my ViewDidLoad:

    let query = PFQuery(className: "_User")
    //  otherQuery.orderByDescending("createdAt")
    query.whereKey("username", notEqualTo:PFUser.currentUser()!.username!)
    query.findObjectsInBackgroundWithBlock { (users: [AnyObject]?, error: NSError?) -> Void in

        if error == nil {
            // success

            print(users!.count)
            for user in users! {
                self.imageFiles.append(user["image"] as! PFFile)
                self.instrumentText.append(user["instrument"] as! String)
                self.nameText.append(user["name"] as! String)
                self.ageText.append(user["age"] as! String)
                // self.locationText.append(user["location"] as! PFGeoPoint)

                var singleData = Data()
                singleData.id = user.objectId
                singleData.OtherName = user["name"] as! String
                print("\(singleData)")


            } // users

Then on the VC that the info button segues to I am trying to call it and upload each label with just the user that was selected.

        self.userName.text = "" as String

But the "" is staying blank.

Then I was thinking maybe if I add that when the more info button is pressed that the user it was pressed on gets chosen and is added to a chosen string on Parse and then I just have to call the user from the chosen string when I am on the chosen users profile page and call the info that way and then when the user clicks the back button the user is no longer chosen. It just seems like I would be adding and taking away a lot of users to "chosen" in Parse is there a better way?

I am able to display all the users info but how do I just display a chosen user from Parse without using the objectId because at the top of each cell it will return a different user here each time depending on settings previously set on a different VC such as only show users in a certain age bracket etc. I know I must set an Id of some sort on button touched but I am at a complete loss. The only online help out there that I can find is set for other languages eg. https://parse.com/docs/js/guide#users-querying> So I guess my question is :

1.Does anyone know a tutorial they could point me towards.

2.Does anyone know how I even get started and I can go from there myself.

3.Can anyone help?

*Swift and Parse newbie little to no experience in other languages.

New code in firstVC:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "userProfileDetailsSegue" {
    if let indexPath = resultsPageTableView.indexPathForSelectedRow {

        let controller = (segue.destinationViewController) as! UserProfileDetailsViewController

  ***error here: UserProfileDetailsViewController.userToShowDetail = indexPath.row
    //line above is the one I can't get to work it needs to equal to the cell selected?
    }
  }
}

New Code in destinationVC:

 var userToShowDetail: PFUser? {
    didSet {
        self.configureView()
    }
}

func configureView() {
    // Update the user interface for the detail item.
    if let userToShowDetail: PFUser = self.userToShowDetail {
        if let label = self.userName {
            nameText.append(userToShowDetail["name"] as! String)

           // self.nameText.append(user["name"] as! String)


    }
}
}
Grace
  • 377
  • 3
  • 19

1 Answers1

1

You're going to need to do a couple of things for this to work. First, in the view controller that you're using to show another user's information, you need to set a property like var userToShowDetail: PFUser?. Then in your view with all of the users of your app, you need to create a segue to bring them from the current view to the detail view. Assuming you're using a TableView, you can connect just one prototype cell to the detail view you're trying to navigate. Then you'll need to override prepareForSegue and set the new view controller's user equal to the user at the row that was selected. I don't know how you're storing your objects of user's of your app, but you should probably be able to do something like this.

override fun prepareForSegue(segue: UIStoryboardSegue) {
    if segue.identifer == "segueToShowDetailInfo" {
        //get the index path for the row that was selected
        let indexPath = self.tableView.indexPathForSelectedRow()
        //get the PFUser object for that particular row
        let userToShow = self.appUsers[indexPath.row]
        //create your new view controller
        let newVc = segue.destinationViewController as! DestinationVC
        //assign the new vc's property to your object
        newVc.userToShowDetail = userToShow
    }
}

But in your query, you probably shouldn't have a separate array of the the different parts of the user's data. You should just make one array, call it var appUsers = [PFUser]() and then when you get a user back in your query, just say:

for user in users! {
    self.appUsers.append(user) as! PFUser
}

There, now you have a whole array of objects that holds a reference to every user. When someone is using your app, and selects a cell, then you can perform the prepare for segue method as above.

Note that I also noticed you have a didSet on your variable in your new view controller. Calling a function to update the UI after this variable is set will not work, and may crash, because the view controller doesn't have a window yet.

pbush25
  • 5,228
  • 2
  • 26
  • 35
  • Hi @pbush25 thank for your help its definitely the right track. I nearly have it worked out except for the last line in the code on VC1. I edited my answer above to show the new code. Thanks again for your help! – Grace Nov 05 '15 at 14:59
  • How are your storing your objects that you're using to populate the tableView? – pbush25 Nov 05 '15 at 15:02
  • Sorry I wasn't clear. How are you storing the data? Are you using your own array? Or are you using a PFQueryTableViewController? – pbush25 Nov 05 '15 at 15:13
  • I'm not using PFQueryTableViweController, I was but then ran into trouble. I have all my users data stored on Parse as string columns under the className _Users. I am calling them then like this: var imageFiles = [PFFile]() var instrumentText = [String]() var nameText = [String]() Shite have I done something really stupid??? – Grace Nov 05 '15 at 15:23
  • I want to know, after you've queried for all the user's and their data, how are you storing this information. IN your `cellForRowAtIndexPath` function, you have to have something like `let object = myArrayOfObjects[indexPath.row] as? PFObject`, do you not? – pbush25 Nov 05 '15 at 15:29
  • This is my query I have it in the view did load. `let query = PFQuery(className: "_User") query.whereKey("username", notEqualTo:PFUser.currentUser()!.username!) query.findObjectsInBackgroundWithBlock { (users: [AnyObject]?, error: NSError?) -> Void in if error == nil { print(users!.count) for user in users! { self.imageFiles.append(user["image"] as! PFFile) self.instrumentText.append(user["instrument"] as! String) self.nameText.append(user["name"] as! String) } self.resultsPageTableView.reloadData() } else { print("error") } } ` – Grace Nov 05 '15 at 15:41
  • Ah okay, I'll update my answer to show yo what you should be doing then. – pbush25 Nov 05 '15 at 15:42
  • Sorry about this you probably think I am thick! I have been trying my hand at swift for the past while and I think I jumped in a bit too deep but it's too late to turn back now as I've too much done. – Grace Nov 05 '15 at 15:44
  • One last question where do these lines go: `self.imageFiles.append(appUsers["image"] as! PFFile) self.instrumentText.append(appUsers["instrument"] as! String) self.nameText.append(appUsers["name"] as! String)` now that I have replaced them with : ` for user in users! { self.appUsers.append(user as! PFUser) }` – Grace Nov 05 '15 at 16:14
  • You don't need them, or the arrays you were appending to anymore. In your `cellForRowAtIndexPath` now in order to set the properties of the cell, you can do something like `let userObject = appUsers[indexPath.row] as! PFObject!` and then get access to that information like `cell.instrumentText.text = object["instrument"]` and so on. – pbush25 Nov 05 '15 at 16:19
  • I am so sorry to be bugging you again... its returning error array index out of range. I know why, its the call to display image.Tried adding PFFile to the appUsers array but it didn't work. Will I just ask another question and leave you alone? `let userObject = appUsers[indexPath.row] as PFObject singleCell.usersName.text = userObject["name"] as? String imageFiles[indexPath.row].getDataInBackgroundWithBlock { (imageData: NSData?, error:NSError?) -> Void in if imageData != nil { let image = UIImage(data: imageData!) singleCell.usersProfileImage.image = image` – Grace Nov 05 '15 at 18:43
  • You're getting an array out of bounds exception because you never populate `imageFiles`. What you should be doing is something like `singleCell.usersProfileImage.file = object["image"] as! PFFile` and then `singleCell.usersProfileImage.loadInBackground` if you're using a `PFImageVIew` which I would recommend. – pbush25 Nov 05 '15 at 18:47
  • I have been trying since i was last talking to you to get the users info to display on the destinationVC and I can't seem to figure it out at all is there any chance you can help? I posted it as a new question here: [link](http://stackoverflow.com/questions/33572660/set-a-property-that-updates-information-on-display-on-a-vc-swift/33573021?noredirect=1#comment54926968_33573021) – Grace Nov 07 '15 at 16:56