Synopsis
Because of the way I am not getting my app to pass data as I intend, I am lead to ask the following questions:
- In general, how can I pass data from a Navigation Controller to its
imbedded View Controller?
- Specifically, does the
prepareForSegue
method in a Navigation Controller ever get called? If so, how?
The Setup
I have the following:
- A View titled User View Controller,
linked to a custom class JRMUserViewController
(which extends UIViewController
).
This view is imbedded in:
- A Navigation View titled Navigation To User View,
linked to a custom class JRMNavigationToUserViewController
(which extends UINavigationController
).
IMPORTANT NOTE:
To start with, I did not have User View Controller imbedded in the Navigation Controller. The Navigation Controller and its linked class did not exist.
- A Table View titled Issue Table View Controller,
linked to a custom class JRMIssuesTableViewController
(which extends UITableViewController
).
- A Button linked to a Modal Segue that goes to the Navigaton To User View.
The Segue is identified by the text "IssuesToUserView
".
Intended Functionality
The idea is that when I am on the Issue Table View Controller, I can click on the button and it will take me to the User View Controller, where I will see the current user's avatar, and a label with the current user's full name.
To accomplish this (before I embeded the User View Controller in the Navigation Controller), I passed data from the JRMIssuesTableViewController
to the JRMUserViewController
in the former's prepareForSegue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(@"\nSEGUE IDENTIFIER:\n%@", [segue identifier]);
if([[segue identifier] isEqualToString:@"IssuesToUserView"]) {
JRMUserViewController *vc = [segue destinationViewController];
vc.currentUser = self.currentUser;
NSURL *url = [[NSURL alloc] initWithString:[vc.currentUser.avatarUrls objectForKey:@"48x48"]];
NSLog(@"\nURL:\n%@", url);
NSData *data = [NSData dataWithContentsOfURL:url];
[vc.view addSubview:vc.avatar];
[vc.avatar setImage:[[UIImage alloc] initWithData:data]];
vc.userLabel.text = vc.currentUser.displayName;
}
}
And it worked. Clicking the button on the first view took me to the second view, where the current user's information was displayed:
Unexpected Behavior
After this, out of necessity, I had to embed User View Controller in the Navigation Controller that I mentioned earlier. Now of course, after doing this, I had uncaught exceptions at runtime because, in my overridden prepareForSegue, I was sending messages to the Navigation Controller instead of to the User View Controller. To fix this, I extended UINavigationController
, naming it JRMNavigationToUserViewController
, and linked the Navigation View to it, as I mentioned in the setup.
Then, figuring that a UINavigationController
would call its own prepareForSegue
before going to its embedded View, I overrode the prepareForSegue
method in JRMNavigationToUserViewController
:
- (id)passValuesToDesitinationOfSegue:(UIStoryboardSegue *)segue {
NSLog(@"Calling [JRMNavigationToUserViewController passValuesToDestinationOfSegue]");
JRMUserViewController *destination = [segue destinationViewController];
destination.server = self.server;
destination.currentUser = self.currentUser;
destination.avatar = self.avatar;
[destination.view addSubview:destination.avatar];
destination.userLabel = self.userLabel;
return destination;
}
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSLog(@"Calling [JRMNavigationToUserViewController prepareForSegue]");
[self passValuesToDesitinationOfSegue:segue];
}
This time, when I clicked on the button, the User View Controller did not receive the data. It looked like this:
Apparently, the prepareForSegue
method in JRMNavigationToUserViewController
was never called, as it would have logged the message:
Calling [JRMNavigationToUserViewController prepareForSegue]
Calling [JRMNavigationToUserViewController passValuesToDestinationOfSegue]
I could not find these lines printed anywhere in the console.
Summary
Here again are my questions:
- In general, how can I pass data from a Navigation Controller to its
imbedded View Controller?
- Specifically, does the
prepareForSegue
method in a Navigation Controller ever get called? If so, how?