Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What are the best practices on communicating with container views

I have been using container VCs often recently and I have been wondering what is the best way to communicate between the main Vc and the container VCs. Right now im using notifications, but I would rather use something better. How can I obtain a pointer to the container VCs so that I can at least use delegation? Any better ways?

like image 878
William Falcon Avatar asked Jul 01 '13 02:07

William Falcon


1 Answers

It is up to the container view controller to set up any necessary connections between itself and the embedded view controller, in its prepareForSegue:sender: method.

In iOS programming, we have a pattern for this style of communication betwixt view controllers. You can read about it in “Coordinating Efforts Between View Controllers” in the *View Controller Programming Guide for iOS”.

But I think it's easier to understand with a concrete example. Let's use the Google Maps app for iPhone:

Google Maps app for iPhone

I don't know exactly how this app is implemented. But let's suppose there's a top-level AppViewController that manages the search bar (at the top) and the location bar (at the bottom), and it embeds a MapViewController in a container view.

There are some interactions between the view controllers. When the user searches, the AppViewController needs to tell the MapViewController to place some map markers and zoom in on one of them. When the user taps a map marker, the MapViewController needs to tell the AppViewController to display information about that marker in the location bar at the bottom.

So here's the pattern.

First, we define a protocol for the messages that the MapViewController (which is the embedded view controller) will send to the AppViewController (which is the container view controller):

@class MapMarker;
@class MapViewController;

@protocol MapViewControllerDelegate <NSObject>

- (void)mapViewController:(MapViewController *)mapViewController didSelectMarker:(MapMarker *)marker;

@end

We will make the AppViewController conform to this protocol. So the MapViewController doesn't need to know about the AppViewController specifically. It just needs a reference to some object that conforms to the protocol. The MapViewController also needs to understand a message that sets its markers and a message that zooms to a specific marker. So we declare MapViewController like this:

@interface MapViewController : UIViewController

@property (nonatomic, weak) id<MapViewControllerDelegate> delegate;

- (void)setMarkers:(NSArray *)markers;
- (void)zoomToMarker:(MapMarker *)marker;

@end

Note that the delegate property is weak to avoid a retain cycle.

The AppViewController needs to conform to the MapViewControllerDelegate protocol. Usually we declare that conformance in a class extension in AppViewController.m, since conformance doesn't need to be part of AppViewController's public interface. The AppViewController also needs a reference to the MapViewController.

@interface AppViewController () <MapViewControllerDelegate>

@property (nonatomic, strong) MapViewController *mapViewController;

@end

Next, we go into the storyboard, select the embed segue, and give it an identifier:

embed segue identifier

Now we can implement the prepareForSegue:sender: method to wire up the properties:

@implementation AppViewController

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    if ([segue.identifier isEqualToString:@"MapEmbedding"]) {
        [self prepareForMapEmbeddingSegue:segue sender:sender];
    }
}

- (void)prepareForMapEmbeddingSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    self.mapViewController = segue.destinationViewController;
    self.mapViewController.delegate = self;

    // We can do any additional setup on mapViewController here,
    // like set its initial viewport.
}

Note that AppViewController also has to implement mapviewController:didSelectMarker:, and MapViewController needs to implement setMarkers: and zoomToMarker:.

like image 157
rob mayoff Avatar answered Nov 15 '22 06:11

rob mayoff