与容器视图通信的最佳实践是什么? [英] What are the best practices on communicating with container views

查看:79
本文介绍了与容器视图通信的最佳实践是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近经常使用容器VC,我一直想知道主Vc和容器VC之间的最佳通信方式是什么。现在我正在使用通知,但我宁愿使用更好的东西。如何获取指向容器VC的指针,以便至少可以使用委托?有没有更好的方法?

解决方案

容器视图控制器可以在自身和嵌入式视图控制器之间建立任何必要的连接,在其 prepareForSegue:sender:方法。



在iOS编程中,我们有这种沟通方式的模式视图控制器之间。您可以在



<我不确切知道这个应用程序是如何实现的。但是我们假设有一个顶级的 AppViewController 来管理搜索栏(在顶部)和位置栏(在底部),它嵌入了一个 MapViewController 在容器视图中。



视图控制器之间存在一些交互。当用户搜索时, AppViewController 需要告诉 MapViewController 放置一些地图标记并放大其中一个。当用户点击地图标记时, MapViewController 需要告诉 AppViewController 在该位置显示有关该标记的信息底部的栏。



所以这是模式。



首先,我们为消息定义一个协议 MapViewController (这是嵌入式视图控制器)将发送到 AppViewController (这是容器视图控制器):

  @class MapMarker; 
@class MapViewController;

@protocol MapViewControllerDelegate< NSObject>

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

@end

我们将制作 AppViewController 符合此协议。所以 MapViewController 不需要具体了解 AppViewController 。它只需要引用一些符合协议的对象。 MapViewController 还需要了解设置其标记的消息以及缩放到特定标记的消息。所以我们像这样声明 MapViewController

  @interface MapViewController:UIViewController 

@property(非原子,弱)id< MapViewControllerDelegate>代表;

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

@end

请注意委托属性是以避免保留周期。



AppViewController 需要符合 MapViewControllerDelegate 协议。通常我们在 AppViewController.m 中声明类扩展中的一致性,因为一致性不需要是 AppViewController 的公共界面。 AppViewController 还需要引用 MapViewController

  @interface AppViewController()< MapViewControllerDelegate> 

@property(非原子,强)MapViewController * mapViewController;

@end

接下来,我们进入故事板,选择嵌入segue,并给它一个标识符:





现在我们可以实现 prepareForSegue:sender:方法来连接属性:

  @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;

//我们可以在mapViewController上做任何额外的设置,
//就像设置它的初始视口一样。
}

请注意 AppViewController 还必须实现 mapviewController:didSelectMarker:,并且 MapViewController 需要实现 setMarkers: zoomToMarker:


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?

解决方案

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:

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:

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:.

这篇关于与容器视图通信的最佳实践是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆