6

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

4

1 回答 1

22

由容器视图控制器在其prepareForSegue:sender:方法中设置其自身和嵌入式视图控制器之间的任何必要连接。

在 iOS 编程中,我们有一种在视图控制器之间进行这种通信方式的模式。你可以在 *View Controller Programming Guide for iOS 中的“Coordinating Efforts Between View Controllers”中了解它</a>。

但我认为用一个具体的例子更容易理解。让我们使用 iPhone 版 Google 地图应用程序:

iPhone 版谷歌地图应用

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

视图控制器之间存在一些交互。当用户搜索时,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 (nonatomic, weak) id<MapViewControllerDelegate> delegate;

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

@end

请注意,该delegate属性是weak为了避免保留循环。

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

@interface AppViewController () <MapViewControllerDelegate>

@property (nonatomic, strong) MapViewController *mapViewController;

@end

接下来,我们进入storyboard,选择embed segue,并给它一个标识符:

嵌入 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;

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

请注意,AppViewController也必须执行mapviewController:didSelectMarker:,并且MapViewController需要执行setMarkers:zoomToMarker:

于 2013-07-01T05:09:41.780 回答