I have a UITableView with 10 cells in it. I have a UIButton & UILabel inside all the 10 cells. Now if I select a UIButton in the 2nd cell, I will navigate to another page and select some values (string values). Now, I want that string to be placed in the UILabel of 2nd cell. Likewise, if i select the UIButton on 5th cell, I will navigate to another page, select some string and that string has to be placed in the UILabel of the 5th cell. How do I insert the values inside the UILabel of that particular cell.
Ideas are appreciated.
I'd recommend setting that second view controller to contain an instance of the first so you can then manipulate the first view controller's data array from that second view.
For example, in the section of the FirstViewController where you create the SecondViewController to perform the push (since as you said in the comments, you're pushing the view controller using a UINavigationController), also make the SecondViewController contain an instance of the FirstViewController.
FirstViewController .m:
// Method to handle the push transition
- (void)buttonPressed:(UIButton*)button {
// Set the view controller's `selectedRow` property
// to contain the selected row number as contained in
// the button tag in this particular scenario
self.selectedRow = (int)button.tag;
// Create an instance of SecondViewController
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
// Pass the view controller along by setting
// the secondViewController's firstViewController
// property to contain self, i.e. the current
// instance of the FirstViewController
secondViewController.firstViewController = self;
// Push to the SecondViewController
[self.navigationController pushViewController:secondViewController animated:YES];
}
And in the .h of SecondViewController, add the firstViewController property such that it's publicly accessible from the FirstViewController.
SecondViewController .h:
#import "FirstViewController.h"
#interface SecondViewController : UIViewController
#property (weak, nonatomic) FirstViewController *firstViewController;
Then in the .m of SecondViewController, you can manipulate the array acting as your table's data source in FirstViewController as needed, before popping the view.
SecondViewController .m:
// Method called after the string is selected
- (void)stringSelected:(NSString*)string {
// Update the array to contain the string
// (or do whatever manipulation to whatever data
// structure is fitting in your particular case)
[self.firstViewController.array replaceObjectAtIndex:self.firstViewController.selectedRow withObject:string];
// To go back to the previous view, pop the view controller
[self.navigationController popViewControllerAnimated:YES];
}
Also, you'll want the UITableView's data source array and selectedRow property to be contained in the .h of FirstViewController so it's publicly accessible from SecondViewController.
FirstViewController .h:
#property (weak, nonatomic) NSMutableArray *array;
#property (nonatomic) int selectedRow;
And in the .m of FirstViewController you want to make sure to reload the table data upon return from the other view so the UITableView reflects the updated data.
FirstViewController .m:
- (void)viewWillAppear:(BOOL)animated {
[self.table reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellName" forIndexPath:indexPath];
if(cell == nil)
{
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CellName"];
}
//Assigning the contents of cell
cell.labelName.text = [NSString stringWithFormat:#"%#", [self.arrCategoryTitle objectAtIndex:indexPath.row]];
[cell.buttonName addTarget:self action:#selector(buttonNamePressed:) forControlEvents:UIControlEventTouchDown];
// Configure the cell...
return cell;
}
- (void)buttonNamePressed:(UIButton *)sender
{
CGPoint swipepoint = sender.center;
CGPoint rootViewPoint = [sender.superview convertPoint:swipepoint toView:self.tableName];
NSIndexPath *indexPath = [self.tableName indexPathForRowAtPoint:rootViewPoint];
NSLog(#"%#", indexPath);
[self.tableName cellForRowAtIndexPath:indexPath];
self.defaultRowId = indexPath.row;
[self performSegueWithIdentifier:#"viewControllerIdentifierName" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
DetailsViewController *detailsViewController = (DetailsViewController *)[(UINavigationController *)segue.destinationViewController topViewController];
detailsViewController.defaultrow = self.defaultRowId;
}
Now when you navigate to the secondViewController, set the selecting string value to the property of the firstViewController then reload table.
Related
I have a CollectionView and in the didSelectItemAtIndexPath method I have instantiating a new ViewController, setting the String property on the ViewController to hold the image's name. And then in the viewDidLoad OR the viewDidAppear method in the new ViewController I am trying to set the image using the vc.imageName property.
Here is the code:
// collection.m
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
ViewController *vc = [[ViewController alloc] init];
NSString *imageName = [colouringPhotos objectAtIndex:indexPath.row];
vc.imageName = imageName;
[self presentViewController:vc animated:YES completion:nil];
}
// ViewController.h
#property (nonatomic, strong) NSString * imageName;
//ViewController.m
#property (strong, nonatomic) IBOutlet UIImageView *lineImageView;
-(void) viewDidAppear:(BOOL)animated{
self.lineImageView.image = [UIImage imageNamed:self.imageName];
}
But the image doesn't show. I have set the background colour on the ImageView to check that it is being displayed in the new ViewController and I can see it but the image never displays within the UIImageView.
You could use a Segue to show the next view controller. Assuming you use "ShowNextViewController" as the identifier for your Segue, you could use prepareForSegue:sender: to set the imageName property of the destination view controller:
- (void)prepareForSegue:(nonnull UIStoryboardSegue *)segue sender:(nullable id)sender {
if ([segue.identifier isEqualToString:#"ShowNextViewController"]) {
ViewController *destination = (ViewController *)segue.destinationViewController;
NSIndexPath *selectedIndex = [[self.collectionView indexPathsForSelectedItems] firstObject];
destination.imageName = self.colouringPhotos[selectedIndex.row];
}
}
If you have trouble setting up the segue, see this iOS Developer Library document for more information.
Also, see the UIViewController Class Reference for more information on the prepareForSegue:sender: method.
I have followed the tutorial Passing Data between View Controllers section Passing Data Forward. My code is:
MasterViewController.h:
-(void)pushViewController: (UIViewController *)detailVC animated:(BOOL)animated;
MasterViewController.m:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell=[tableView cellForRowAtIndexPath:indexPath];
NSInteger num = indexPath.row;
DetailViewController *detailVC = [[DetailViewController alloc] initWithNumber:indexPath.row];
detailVC.number = num;
[self pushViewController:detailVC animated:YES];
}
I want to pass the integer num to my DetailViewController. But I am getting Thread 1: SIGABRT. What is happening?
MasterViewController doesn't inherit from UINavigationController.
You can't push to the navigation stack if there isn't one.
You can either add one, or present the new VC, depending upon what the design of your GUI is intended to be.
P.S.
WHat's the point in setting the number twice as you are:
NSInteger num = indexPath.row;
DetailViewController *detailVC = [[DetailViewController alloc] initWithNumber:indexPath.row];
detailVC.number = num;
You either set it with init or set it directly, you're doing it both ways
My best guess (without seeing your #interface for DetailViewController) is that it's simply a matter of the detailVC instance going away after you put it on screen.
Simple solution: use an instance variable instead:
#interface WhateverClassYouAreIn
#property (nonatomic, strong) DetailViewController *detailVC
#end
// ...
self.detailVC = [[DetailViewController alloc] initWithNumber:indexPath.row];
The reason this is happening is that without the instance variable, the storage duration of the detailVC is the scope of the method in which it is declared. In general, any VC that goes on screen should be held 'strongly' by something else, all the way back to the root vc.
Is the method "initWithNumber" defined in DetailViewController.h ?
#interface DetailViewController : UIViewController
- (instancetype)initWithNumber:(NSInteger)number;
#end
In ViewControllerA I have a table with three rows of data right now (three messages). Clicking on a row, I'm trying to push to ViewControllerB with the text from one of the rows (the name). Problem I'm having is I'm trying to do everything programmatically, not using storyboard ids or storyboard segues. Is this possible? Here's what I have.
ViewControllerA m.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
Messages *cell = (Messages *)[tableView cellForRowAtIndexPath:indexPath];
NSString *from = [NSString stringWithFormat:#"%#", cell.from.text];
ViewControllerB *VCB = [[ViewControllerB alloc]init];
VCB.from = from;
[self.navigationController pushViewController:VCB animated:YES];
//using this^ creates a new view controller with a black screen but passes the variable
//[self performSegueWithIdentifier:#"pushMessage" sender:self];
using this^ shows my ViewControllerB perfectly but the value isn't set
}
ViewControllerB h.
#property (strong, nonatomic) NSString *from;
ViewControllerB m.
-(void)viewDidLoad{
NSLog(#"%#", from);
}
Is there a way to do this without initiating a new viewcontrollerB in VCA and getting the right push animation?
I believe I understand what you're asking and you are almost on the right track here. You said that it works when you use [self performSegueWithIdentifier:#"pushMessage" sender:self]; but the value is not set.
So, declare an NSString "from" in your header and in the previous code delete the [self.navigationController pushViewController:CVC animated:YES];
//ViewControllerA.h
#property (copy, nonatomic) NSString *from;
//ViewControllerA.m
#synthesize from;
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Messages *cell = (Messages *)[tableView cellForRowAtIndexPath:indexPath];
from = [NSString stringWithFormat:#"%#", cell.from.text];
[self performSegueWithIdentifier:#"pushMessage" sender:self];
}
Then you need to use the prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
//ViewControllerA.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"pushMessage"]) {
ViewControllerB *vcb = [segue destinationViewController];
[vcb setFrom:[self from]];
}
}
EDIT
Well, I feel like this is a really wrong way to do it. But, this will satisfy all of your conditions asked in the question. I have checked and this does in fact work:
First, Go to your storyboard, click on the View Controller B, click on the identity inspector and change the Storyboard ID. Also click the check that says "Use Storyboard ID".
In your ViewControllerA:
//ViewControllerA.h
- (void)callViewControllerWithCellString:(NSString *)str;
//ViewControllerA.m
- (void)callViewControllerWithCellString:(NSString *)str
{
NSString * storyboardName = #"Main";
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:storyboardName bundle: nil];
SecondViewController * vc = [storyboard instantiateViewControllerWithIdentifier:#"ViewControllerB"];
[vc setFrom:str];
[[self navigationController] pushViewController:vc animated:YES];
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Messages *cell = (Messages *)[tableView cellForRowAtIndexPath:indexPath];
NSString *from = [NSString stringWithFormat:#"%#", cell.from.text];
[self callViewControllerWithCellString:from];
}
So lets see if i understand this.
You want the text from the clicked row passed to the view controller that you want to present
You want to do this without using storyboards
Sounds simple enough. Check this out.
// I actually recommend this option
// Simply initialize your view controller with the text that you want to pass
ViewControllerB * VCB = [[ViewControllerB alloc] initWithText:from];
// For this to work, you'll have to declare a new init method in your .h file like this
-(void)initWithText:(NSSTring *)text;
// You should also declare an iVar to store your text
NSString * fromText;
// and implement it in your .m file like this
-(void)initWithText:(NSString *)text
{
self = [super init];
if (self)
{
fromText = text;
}
return self;
}
// Or, you could do this.
// In ViewControllerB.h, create a property
#property (nonatomic, strong) NSString * fromText;
// In ViewControllerB.m, synthesize it
#synthesize fromText;
// Then you can pass that property a value like this
ViewControllerB * VCB = [[ViewControllerB alloc] init];
VCB.fromText = from;
Variables shoudl be lower case.
Your ViewControllerB should be displaed. Do you create all view elements in there programatically too? If you don't then you better load it from a XIB or from the storyboard. You can do that without segueing to it.
But I guess it is much easer to overwrite the perpareForSegue: method and set the from property there. That is what perpareForSegue is made for when you need to do some customization programatically while using storyboards for all the easy stuff.
First off, you should check your code. You are pushing a viewController named CVC onto the navigation controller. I assume this is a typo.
Did you override ViewControllerB "initWithNibName:bundle:" as I see you are calling init. How would the ViewController know what nib to load if you didn't?
Also, it is recommended that you call [super viewDidLoad] in your viewDidLoad call.
You can push views programmatically as well.
You seem to do following
ViewControllerB *VCB = [[ViewControllerB alloc]init];
VCB.from = from;
[self.navigationController pushViewController:CVC animated:YES];
Which means you want to push VCB and not CVC. This change should fix your problem.
You can also put a breakpoint in viewDidLoad to verify your new ViewController is loaded.
If you are using storyboard for VCB as well, I think you should do following --
ViewControllerB *VCB = [self.storyboard instantiateViewControllerWithIdentifier:#"VCBIdentifier"];
where VCBIdentifier is the identifier to your ViewControllerB marked in Identity Inspector -> StoryBoardID.
With your current init, I think, it is creating a default viewcontroller which is blank/empty.
I have a HomeViewController which has a tableView populated with the array tableViewArray (originally empty). When I tap on a barButton, I segue modally to another View Controller called OutsideViewController which has another tableView populated by a different array.
What I would like to do is the following:
When I tap on a row in my OutsideViewController, I would like to add the selected string value to the tableViewArray so that when I go back to HomeViewController, the tableView has that new item listed in the tableView.
So far, this is what I have tried:
In the -didSelectRowAtIndexPath method of my OutsideViewController.m I have this piece of code:
NSString *selectedRow = [outsideArray objectAtIndex:indexPath.row];
NSMutableArray *temporaryArray = [NSMutableArray arrayWithObject:selectedRow];
HomeViewController *homeVC = [[HomeViewController alloc] init];
homeVC.tableViewArray = temporaryArray;
That code works but the tableView in HomeViewController is still empty when I return. Do I have to reload the tableView data?
Am I doing this right?
This is how I have set up my View Controllers in Storyboard:
HomeViewController -(modal segue)-> Navigation Controller --> OutsideViewController
Also, the return from OutsideViewController to HomeViewController is done by this line of code:
[self dismissViewControllerAnimated:YES completion:^{ }];
What you're doing wrong is you're allocationg a new HomeViewController. What I would do is keeep a reference to your HomeViewController in your OutsideViewController. Here is how.
First, in OutsideViewController.h, create a property, like this :
#property (nonatomic, weak) HomeViewController *homeVC;
Don't forget to add #class HomeViewController; in your .h, and #import "HomeViewController.h" in your .m
In HomeViewController, implement the prepareForSegue: method like this (replace ModalSegueIdentifier with your segue's identifier) :
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"ModalSegueIdentifier"]) {
OutsideViewController *modalVC = (OutsideViewController*)segue.destinationViewController;
modalVC.homeVC = self;
}
}
Then, in OutsideViewController.m, instead of doing :
HomeViewController *homeVC = [[HomeViewController alloc] init];
homeVC.tableViewArray = temporaryArray;
Do this :
_homeVC.tableViewArray = temporaryArray;
When you leave your modal VC, your HomeVC will have the correct array. Don't forget to refresh your UITableView !
NB: Of course, there are many other ways, and it's maybe not the best one. But still, it should work.
You can achieve this too using delegation. You have to create a protocol in your OutsideViewController with a method that is responsible for sending the new object to your HomeViewController. Do this in OutsideViewController.h:
#protocol OutsideViewDelegate <NSObject>
- (void)OutsideViewController:(OutsideViewController *)controller didAddObject:(NSString *)object;
#end
In the implementation file you have to change a little bit the didSelectRowAtIndexPath: method:
NSString *selectedRow = [outsideArray objectAtIndex:indexPath.row];
[self.delegate OutsideViewController:self didAddObject:selectedRow];
In your HomeViewController.h you have to make your class conforms to the protocol:
#interface HomeViewController : UIViewController <OutsideViewDelegate>
After, create a property for the delegate:
#property (nonatomic, weak) id <OutsideViewDelegate> delegate;
To finish the process, implement the protocol in your HomeViewController.m to receive the new object from the OutsideViewController:
- (void)OutsideViewController:(OutsideViewController *)controller didAddObject:(NSString *)object
{
if (object != nil)
{
[self.tableViewArray addObject:object];
}
[self dismissViewControllerAnimated:YES completion:nil];
}
The code above depends of if your tableViewArray object is mutable or not. If it's not, you can change the type of the object argument in the protocol method to an inmutable array object and just assign tableViewArray to the new array.
EDIT:
In the prepareForSegue: method don't forget to set the delegate:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"SEGUE_IDENTIFIER"]) {
OutsideViewController *outsideVC = (OutsideViewController *)[segue destinationViewController];
[outsideVC setDelegate:self];
}
}
First of all make sure you alloc, init your tableViewArray in HomeViewController
Second , In this line
HomeViewController *homeVC = [[HomeViewController alloc] init]
you are creating a new reference to your HomeViewController which is not correct, you need to pass correct reference, possibly creating HomeViewController variable in your OutsideViewController
Even though you correctly do first and second suggestion you will still see an empty tableview because you dont reload the tableview, somehow you need to fire [self.tableview reloadData]; method.
That means; you need to learn Delegate or NSNotifications pattern to communicate between child->parent scenarios
How do I set up a simple delegate to communicate between two view controllers?
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_nsnotificationcenter/
For your question just create a delegate in your Outside;
in your OutsideViewController.h
#import <UIKit/UIKit.h>
#protocol OutsideDelegate;
#interface{}//bunch of interface stuff
// Declare a property for the delegate
#property (weak) id <OutsideDelegate> delegate;
#end
// Protocol Header
#protocol OutsideDelegate <NSObject>
#optional
- (void)dismissPop:(NSMutableArray *)list;
#end
in your OutsideViewController.m
#synthesize delegate;
//run delegate method
[delegate dismissPop:temporaryArray];
[self dismissViewControllerAnimated:YES completion:^{ }];
in your HomeViewController.h
#import "OutsideViewController.h"
#interface OutsideViewController : UITableViewController<OutsideDelegate>
{}
#property (strong, nonatomic) OutsideViewController *pvc;
in your HomeViewController.m
#synthesize pvc;
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"your segue"]) {
pvc = [segue destinationViewController];
[pvc setDelegate:self];
}
}
// delegate callback function
- (void)dismissPop:(NSMutableArray *)list {
self.tableViewArray=list;
[self.tableView reloadData];
}
Another Solution Would be
Change your view stack to this:
Navigation Controller --> HomeViewController -(push segue)--> OutsideViewController
and apply rdurand's answer
and add this to your HomeViewController :
-(void)viewDidAppear:(BOOL)animated
{
[self.tableview reloadData];
}
In this solution since you are just push-pop viewcontrollers in a nabigation stack viewDidAppear will be called in HomeViewController everytime when you pop OutsideViewController.
I want to change the selected row in the table (in MasterViewController) from a button on a detailViewController.
I know that I cannot call didSelectRowAtIndexPath because it is a delegate method. I tried using selectRowAtIndexPath but that does not invoke the didSelectRowAtIndexPath nor the willSelectRowAtIndexPath method. As suggsted here,
https://stackoverflow.com/a/7496926/1050722 it is possible to some new method and then call that method from the other ViewController (detailViewController), but how should that method look like?
Here is some code:
MasterViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self pushDetailViewController:indexPath];
}
-(void)pushDetailViewController:(NSIndexPath *)indexPath
{
if (!self.detailViewController) {
self.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
}
[self.navigationController pushViewController:self.detailViewController animated:YES];
NSLog(#"pushDetailviewC and index %#", indexPath);
}
DetailViewController.m
-(IBAction)nextItem
{
MasterViewController *mVc = [[MasterViewController alloc] init];
[mVc pushDetailViewController:[NSIndexPath indexPathForRow:0 inSection:0]];
}
Can someone give me an example to fix this? Thanks.
EDIT: Here is the new code
MasterViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self pushDetailViewController:indexPath];
}
-(void)pushDetailViewController:(NSIndexPath *)indexPath{
if (!self.detailViewController) {
self.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
}
self.detailViewController.mVc = self;
[self.navigationController pushViewController:self.detailViewController animated:YES];
NSLog(#"pushDetailviewC and index %#", indexPath);
}
DetailViewController.h
#import <UIKit/UIKit.h>
#import "MasterViewController.h"
#interface DetailViewController : UIViewController <UISplitViewControllerDelegate, UITableViewDelegate>
#property (strong, nonatomic) id detailItem;
#property (strong, nonatomic) IBOutlet UILabel *detailDescriptionLabel;
#property (nonatomic, retain) MasterViewController *mVc;
DetailViewCOntroller.m
-(IBAction)test{
//MasterViewController *mVc = [[MasterViewController alloc] init];
[self.mVc pushDetailViewController:[NSIndexPath indexPathForRow:0 inSection:0]];
}
It does not call the NSLog part of the method and it is not selecting the row...
This answer is iPad specific as per your question.
The iPad version of the Master/Detail template uses a UISplitViewController two split the screen as you see it. This UISplitViewController instance keeps references to both of your navigations controllers. Which keep reference to your topmost view controllers. Here is sample code, do not use it verbatim except to test since it contains no error checking.
// Picking some arbitrary row
NSUInteger desiredRow = 3;//???
// The Master navigation controller is at index zero in the template, you can check in your app delegate's didFinishLaunching: method
UINavigationController *masterController = [self.splitViewController.viewControllers objectAtIndex:0];
// Next we want a reference to the topmost viewController again you shouldn't assume it's a UITableViewController
UITableViewController *tableController = (UITableViewController *)masterController.visibleViewController;
// Next we get the reference to the tableview in-question
UITableView *tableView = tableController.tableView;
// We translate our desired row to an index path
NSIndexPath *path = [NSIndexPath indexPathForRow:desiredRow inSection:0];
// We select the row , again this will not call didSelectRowAtIndexPath:
[tableView selectRowAtIndexPath:path animated:YES scrollPosition:UITableViewScrollPositionNone];
// We call didSelectRowAtIndexPath: on the tableview's delegate
[tableView.delegate tableView:tableView didSelectRowAtIndexPath:path];
When I put this code in an IBAction method in the detail view controller the linked button performs the appropriate actions, both selects the row and pushes a VC, as if I had selected the row by touch.
In DetailViewController.h add a property to the object that points to the MasterViewController. You will also need to import the MasterViewController.h so something like
#import "MasterViewController"
...
#property (nonatomic, retain) MasterViewController *mVc;
...
Don't forget in DetailViewController.m to #synthesize mVc;
Now in your pushDetailViewController you add a reference to join the two objects
if (!self.detailViewController) {
self.detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
}
[self.detailViewController.mVc = self]; // New line
[self.navigationController pushViewController:self.detailViewController animated:YES];
Then in the DetailViewController you reference the object
-(IBAction)nextItem{
[self.mVc pushDetailViewController:[NSIndexPath indexPathForRow:0 inSection:0]];
}
I think another issue you were having was alloc'ing a new version of mVC each time you click the nextItem button. IOS will happily let you make lots of MasterViewController objects and makes a new one each time you alloc it. You wanted just to get a handle to your original MasterViewController.
Another approach would be to explore using the parent methods to reference the MasterViewController. But I wanted to show you how to do this with an explicit property since I thought it would be clearer.
Also, this may or may not fix all of your issues, but it hopefully at least shows you how to talk back to the actual MasterViewController.