Implementing delegation between views embedded in

2019-06-20 09:54发布

问题:

The relevant part of my storyboard appears as follows: You can see the custom "Container Controller" view houses two Container Views, one which links to a Navigation Controller via embedded segue, and another that links to a custom "Master View Controller" (which implements a Table View Controller) via embedded segue. The Navigation Controller component further has a relationship with a custom "Location Filter Controller."

I need to implement delegation such that when one of the UISteppers in the Location Filter Controller is incr./decr., the table view in the Master View Controller knows to update the data it displays accordingly.

I am not unaccustomed to working with protocols/delegates, but this unique situation of talking between views housed in segues is really tricking me! For the most part I have had success following the example here: Passing Data between View Controllers. In this case however, I am not able to directly link instantiated views as he indicates to do in 'Passing Data Back' step 6.

I had considered using a singleton object from which each of these views could get/set the necessary data, but the issue here is that the table view would not necessarily know when to update its contents, despite having data with which it could/should update.

Here is a code snippet from ContainerController.m where I setup the embedded segues to function:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    DataHold *data = [[DataHold alloc] init]; // <-- this actually is a singleton object

    if([segue.identifier isEqualToString:@"locationEmbedSegue"])
    {

    }
    else if([segue.identifier isEqualToString:@"tableEmbedSegue"])
    {
        [[segue destinationViewController] setDelegate:data.detailTableViewController];
        // ^ This part actually sets up a delegate so that the table view (Master View Controller)
        // delegates to the detail view controller of the overarching split view controller
        // and tells it what to display when a row is pressed.
    }
}

Thanks for any help!

回答1:

I think you are on the right track setting the table view delegate to your Location Filter Controller.

I found that a simple way to work with embeded view controller is to add "placeholders" property for them, and set these property when the segue is "performed".

// MyContainerController.h
@property (strong, nonatomic) MyLocationFilterController *detailViewController;
@property (strong, nonatomic) UITableViewController *masterViewController;

// MyContainerController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"locationEmbedSegue"])
    {
        UINavigationViewController *dest = (UINavigationViewController *)segue.destinationViewController;
        self.detailViewController = dest.topViewController;
    }
    else if([segue.identifier isEqualToString:@"tableEmbedSegue"])
    {
        self.masterViewController = (UITableViewController *)segue.destinationViewController;
        [self.masterViewController.tableView setDelegate:self.detailViewController];
    }
}


回答2:

I came to this question recently and found there may be one problem with the answer above.

  • Move the setDelete: method out. This makes sure no controller is nil.

Then code becomes:

// MyContainerController.h
@property (strong, nonatomic) MyLocationFilterController *detailViewController;
@property (strong, nonatomic) UITableViewController *masterViewController;

// MyContainerController.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"locationEmbedSegue"])
    {
        UINavigationViewController *dest = (UINavigationViewController *)segue.destinationViewController;
        self.detailViewController = dest.topViewController;
    } else if([segue.identifier isEqualToString:@"tableEmbedSegue"])
    {
        self.masterViewController = (UITableViewController *)segue.destinationViewController;

    }

    [self.masterViewController.tableView setDelegate:self.detailViewController];
}