Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

iOS

prepareForSegue error (extra credit for Relating Users in Parse.com)

When I define self.selectedUserId = user.objectId; in the didSelectRowAtIndexPath method and I NSLog self.selectedUserId it logs it.

In my prepareForSegue method I have:

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if([segue.identifier isEqualToString:@"showEditFriends"]) {
        EditFriendsViewController *viewController = (EditFriendsViewController *)segue.destinationViewController;
        viewController.friends = [NSMutableArray arrayWithArray:self.friends];
    }

    //added for profile
    else if ([segue.identifier isEqualToString:@"showProfileView"]) {
        ProfileViewController *pvController = (ProfileViewController *)segue.destinationViewController;
        pvController.userId = self.selectedUserId;
        NSLog(@"%@", self.selectedUserId);
    }
}

That logs null. I need to pass this information in order for my query to work in ProfileViewController. Does anybody know why this wouldn't be working? Is the variable out of scope? If it is how do I fix it?

Cathal Farrell
Cathal Farrell
7,190 Points

Have you checked the @property of the userId on ProfileViewController? If you have defined it as 'weak', try changing it to 'strong'. I had a similar problem and making this change solved it.

Hi Cathal Farrell, I will have a look at it as soon as I get home from work. I hope that is the problem! I appreciate you offering assistance. If that is the case I will make sure that I update this thread for others who have the same problem.

Edit: Unfortunately the iserId is defined as strong.

4 Answers

Does anybody have any other suggestions?

Amit Bijlani, Stone Preston, or maybe Ben Jakuben I'd love to move on but I can't for the life of me figure this out. I appreciate any help that anybody can offer.

Stone Preston
Stone Preston
42,016 Points

can you post your property declaration for selectedUserId, your didSelectRowAtIndexPath method, and your prepareForSegue method please

Hi Stone,

Here's my code:

didSelectRowAtIndexpath

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];

    //get user of current index path
    PFUser *user = [self.friends objectAtIndex:indexPath.row];
    //get the object ID of the user and assign it to selected user ID
    self.selectedUserId = user.objectId;
}

prepareForSegue

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if([segue.identifier isEqualToString:@"showEditFriends"]) {
        EditFriendsViewController *viewController = (EditFriendsViewController *)segue.destinationViewController;
        viewController.friends = [NSMutableArray arrayWithArray:self.friends];
    }

    //added for profile
    else if ([segue.identifier isEqualToString:@"showProfileView"]) {
        ProfileViewController *pvController = (ProfileViewController *)segue.destinationViewController;
        pvController.userId = self.selectedUserId;
        NSLog(@"%@", self.selectedUserId);
    }
}

FriendsViewController.h

#import <UIKit/UIKit.h>
#import <Parse/Parse.h>

@interface FriendsViewController : UITableViewController

@property(strong, nonatomic) PFRelation *friendsRelation;
@property(strong, nonatomic) NSArray *friends;
@property (strong, nonatomic) NSString *selectedUserId;

@end

One thing that I noticed when I set logs on both didSelectRowAtIndexPath and prepareForSegue is that the log on prepareForSegue is being logged first which leads me to believe that the definition of selectedUserId is not defined because the method that defines it is running after it. Does this make sense? If it does maybe there's a way to fix that (if it is the issue)?

Stone Preston
Stone Preston
42,016 Points

where are you calling performSegueWithIdentifier at?

Hi Stone Preston,

I am not. I wasn't calling it when I segued to EditFriendsViewController and it works. so I didn't think I had to for this.

Here is my entire FriendViewController.m just in case I did call it and I am overlooking it.

//
//  FriendsViewController.m
//  Ribbit
//
//  Created by Eric Ellenbrook on 6/29/14.
//  Copyright (c) 2014 Eric Ellenbrook. All rights reserved.
//

#import "FriendsViewController.h"
#import "EditFriendsViewController.h"
#import "ProfileViewController.h"
#import <Parse/Parse.h>


interface FriendsViewController ()

@end

@implementation FriendsViewController


- (void)viewDidLoad
{
    [super viewDidLoad];
    self.friendsRelation = [[PFUser currentUser] relationForKey:@"friendsRelation"];
    //Query the DB on Parse
    PFQuery *query = [self.friendsRelation query];
    //Order by username ascending
    [query orderByAscending:@"username"];

    [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
        if(error) {
            NSLog(@"Error: %@ %@", error, [error userInfo]);
        } else {
            self.friends = objects;
            [self.tableView reloadData];
        }
    }];
}


//This prepares the segue and if the sque is showEditFriends then viewcontroller.friends is an array of this class's friends query (make sure the future VC"s header file is included)
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if([segue.identifier isEqualToString:@"showEditFriends"]) {
        EditFriendsViewController *viewController = (EditFriendsViewController *)segue.destinationViewController;
        viewController.friends = [NSMutableArray arrayWithArray:self.friends];
    }

    //added for profile
    else if ([segue.identifier isEqualToString:@"showProfileView"]) {
        ProfileViewController *pvController = (ProfileViewController *)segue.destinationViewController;
        pvController.userId = self.selectedUserId;
        NSLog(@"Prepare %@", self.selectedUserId);
    }
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.friends count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    PFUser *user = [self.friends objectAtIndex:indexPath.row];
    cell.textLabel.text = user.username;

    return cell;
}

#pragma mark - Selected Row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];

    //get user of current index path
    PFUser *user = [self.friends objectAtIndex:indexPath.row];
    //get the object ID of the user and assign it to selected user ID
    self.selectedUserId = user.objectId;
    NSLog(@"Did Select");
}

@end
Stone Preston
Stone Preston
42,016 Points

ok add another log to didSelectRow

#pragma mark - Selected Row
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.tableView deselectRowAtIndexPath:indexPath animated:NO];

    //get user of current index path
    PFUser *user = [self.friends objectAtIndex:indexPath.row];
    //get the object ID of the user and assign it to selected user ID
    self.selectedUserId = user.objectId;
    NSLog(@"Did Select");
NSLog(@"user id in didSelectRow is: %@", self.selectedUserId);
}

and see what happens. I assume you connected your segue to a button in your storyboard, so that segue should not be running before the cell is selected

The log: 2014-07-01 13:58:28.189 Ribbit[18882:60b] user id in didSelectRow is: b0JFFyAc0l Edit: The ID changes with different cells and the ID lines up with the information on Parse.com

I connected my segue by dragging it from the prototype cell to the new view controller while holding control. It's style is push.

I should also note that I got it working perfectly by using willSelectRow instead of didSelectRow. I assume that's because willSelect is being called prior to prepareForSegue.

Anyway, that's my information.