Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Anuj Verma
11,825 PointsExtra Credit Relating Users in Parse: User Profiles: Do we really know our "Friends"?
I have successfully got all the fields stored in the parse database by having the below code in SignupViewController.m in viewDidLoad
- (IBAction)signup:(id)sender {
NSString *username = [self.usernameField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *password = [self.passwordField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *email = [self.emailField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *firstName = [self.firstName.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *lastName = [self.lastName.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *hometown = [self.hometown.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([username length] == 0 || [password length] == 0 || [email length] == 0){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops" message:@"Make sure you enter a username, password, and email address!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
else {
PFUser *newUser = [PFUser user];
newUser.username = username;
newUser.password = password;
newUser.email = email;
[newUser setObject:firstName forKey:@"firstName"];
[newUser setObject:lastName forKey:@"lastName"];
[newUser setObject:hometown forKey:@"hometown"];
[newUser signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error){
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Sorry!" message:[error.userInfo objectForKey:@"error"] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
else {
[self.navigationController popToRootViewControllerAnimated:YES];
}
}];
}
}
I am now getting stuck with how to get those to display in the new tableViewController I have made linked to ProfileViewController. I think that I have to make a relation to a user with all of it's keys and then set a query but keep getting stuck because I do not know how to set many objectForKey (like email, firstName, lastName, etc.) for the PFRelation. Hope this makes sense :).
5 Answers
Ben Jakuben
Treehouse TeacherIt sounds like you could just pass the user ID (objectId) of the user tapped in in your table view controller to your new ProfileViewController, and then query the back-end using that ID.
In this example, add a new NSString property to ProfileViewController named userId:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"<whatever your segue is named>"]) {
ProfileViewController *vc = (ProfileViewController *)segue.destinationViewController;
vc.userId = self.selectedUserId; // could set this in didSelectRowAtIndexPath
}
}
Anuj Verma
11,825 PointsIn my ProfileViewController.m I placed the below
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"showProfileView"]) {
ProfileViewController *vc = (ProfileViewController *)segue.destinationViewController;
vc.userId = self.selectedUserId; // could set this in didSelectRowAtIndexPath
}
}
and added the below in ProfileViewController.h
@property (nonatomic, strong) NSString *userId;
@property (nonatomic, strong) NSString *selectedUserId;
I think I might be reading your hint wrong because it's not working and I think I would have to put something in the didSelectRowAtIndexPath in the FriendsViewController.m
Really think I am close but missing something crucial. :/
Ben Jakuben
Treehouse TeacherYeah, so I'm assuming the segue occurs from FriendsViewController to ProfileViewController. In that case you need to prepare for the segue before it happens by putting that method in FriendsViewController. You'll also need to move your selectedUserId property and set it in the didSelectRowAtIndexPath method in FriendsViewController.
So think about how it will flow when a user taps on a friend. First, didSelectRowAtIndexPath is called, and you can grab which friend was selected based on the indexPath (gives you the number for the row). Tapping on the row causes the segue to occur, which means that prepareForSegue will be called before it actually happens. You set the data there and get segued to ProfileViewController. So then when that view controller loads, you can look at the data you set in prepareForSegue and use it to populate the fields in ProfileViewController.
Hope this helps!
Anuj Verma
11,825 PointsFirst of all thanks for all your help I think I am getting closer! So the first part of your hint makes much more sense to me.
In FriendsViewController.m I have this, which I think is now correct:
#import "FriendsViewController.h"
#import "EditFriendsViewController.h"
#import "ProfileViewController.h"
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:@"showEditFriends"]){
EditFriendsViewController *viewController = (EditFriendsViewController *)segue.destinationViewController;
viewController.friends = [NSMutableArray arrayWithArray:self.friends];
}
if ([segue.identifier isEqualToString:@"showProfileView"]) {
ProfileViewController *vc = (ProfileViewController *)segue.destinationViewController;
vc.userId = self.selectedUserId; // could set this in didSelectRowAtIndexPath
}
}
The part I am still stuck at right now in the didSelectRowAtIndexPath in FriendsViewController.m. Here is what I have attempted so far and not sure where to take it.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *user = self.selectedUserId;
}
After that I'll have to tackle how to "look at the data you set in prepareForSegue and use it to populate the fields in ProfileViewController."
Thanks again for your help!
Ben Jakuben
Treehouse TeacherYour table view has an array of PFUser objects as its data source. We can copy and paste this line from cellForRowAtIndexPath:
PFUser *user = [self.friends objectAtIndex:indexPath.row];
Pasting that in didSelectRowAtIndexPath will give you the user that was tapped on. Then you can get the user's ID with
self.selectedUserId = user.objectId;
Make sure you get the right object ID when ProfileViewController loads and then you can move on from there. :)
Anuj Verma
11,825 PointsAh that makes so much sense!
I think I am getting the right objectID, I put in an NSLog statement to make sure and it spits out some characters that Parse is associating with the selected user.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
PFUser *user = [self.friends objectAtIndex:indexPath.row];
self.selectedUserId = user.objectId;
NSLog(@"%@", self.selectedUserId);
}
Now in ProfileViewController I believe I have to set up a PFQuery to find the fields (firstName, lastName, etc.) of that selectedUserId but again I get stumped. My hunch is that I have to make another property in ProfileViewController but not sure what it should do exactly. I am really starting to get an understanding of this by working through the steps! Thanks Ben :).
Ben Jakuben
Treehouse TeacherSo glad to hear it! You learn so much by working through your own problems.
Let me know if you get your PFQuery working or if you come up with more questions! :) If you do end up with more questions, post them as new ones here in the Forum and tag me so I make sure I see them.
POKE !
88 PointsIs there a way to change the password?
Ben Jakuben
Treehouse TeacherIf you are talking about resetting user passwords, check out this section in the Parse docs: https://parse.com/docs/ios_guide#users-resetting/iOS
POKE !
88 PointsI was actually more thinking of way for the user to change the password themself. So the user can change their password by typing in the old at the top and then the new password twice.
Somthing like this maybe:
if(![oldPassword.text isEqualToString:[user password]]){ [alertMessagePassword setMessage:@"The old password is incorrect!"]; [alertMessagePassword show];
Ben Jakuben
Treehouse TeacherAh, I see. In that case you should be able to just overwrite the current user's password field (I think).
POKE !
88 PointsThanks! Yes that works. Looking for a way to check that the user knows the old password though
Rashii Henry
16,433 Pointsim not sure how efficient this may be, but maybe if you create a new NSString called *oldPassword (or whatever you fancy) in the same area that you created the original password string && whenever the user first signs up you now have two different references to one original password(this will be the case only in the beginning or for however long they don't decide to change their password. just say for instance the user keeps the same password forever).Anyways, so it will assign one value to the two different variables. So now since you have two references you can now check to see if oldPassword isEqualTo the whatever they are typing in the textfield. if it does then.. move on and save the newPassword value to the original password string && you can choose to keep the old password as the oldest password if that makes sense.On the other hand, if it doesn't match oldPassword, use an alertView or give them a certain amount of chances. that way, you can keep track of the two most recent passwords that the user has created. Might not be the best way but its only a suggestion.
Joaquin Beltran
Courses Plus Student 6,784 PointsBen Jakuben, I'm having trouble actually assigning the selectedUserId in my prepareForSegue method after I set it in the didSelectRowMethod. When I NSLog it in the prepareForSegue method the value shows up as null. I've created a public property: @property (strong, nonatomic) NSString *selectedUserId; but it doesn't seem to help.
''' objective-c
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.tableView deselectRowAtIndexPath:indexPath animated:NO];
PFUser *user = [self.friends objectAtIndex:indexPath.row];
self.selectedUserId = user.objectId;
NSLog(@"selectedUserId: %@",self.selectedUserId); // It shows the value
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:@"showEditFriends"]) {
JBEditFriendsTableViewController *viewController = (JBEditFriendsTableViewController *)segue.destinationViewController;
viewController.friends = [NSMutableArray arrayWithArray:self.friends];
} else if ([segue.identifier isEqualToString:@"showProfile"]) {
JBProfileViewController *vc = (JBProfileViewController *)segue.destinationViewController;
vc.userId = self.selectedUserId;
NSLog(@"userId from segue: %@",self.selectedUserId); // it shows up as null
}
}
'''
Michał Tubis
2,521 PointsMichał Tubis
2,521 PointsHow do you know you got all the fields stored in the Parse database? I have exactly the same code and I can't see any additional columns with new properties of the user object on Parse.com...