Xcode(故事板和segues):为什么委托而不是引用?

时间:2012-03-08 14:56:32

标签: objective-c xcode reference delegates protocols

我已阅读有关故事板的following tutorial

基本上,本教程中创建的示例App允许用户在各种视图之间导航,并使用 segue 创建。

为了在视图之间导航,教程说要创建两个UITableViewController,并在从一个“走”到另一个时指定一个委托:

第一个控制器:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue.identifier isEqualToString:@"AddPlayer"])
    {
        UINavigationController *navigationController = segue.destinationViewController;
        PlayerDetailsViewController *playerDetailsViewController = [[navigationController viewControllers] objectAtIndex:0];
        playerDetailsViewController.delegate = self;
    }
}

第二控制器:

@protocol PlayerDetailsViewControllerDelegate <NSObject>

- (void)playerDetailsViewControllerDidCancel: (PlayerDetailsViewController *)controller;
- (void)playerDetailsViewController: (PlayerDetailsViewController *)controller didAddPlayer:(Player *)player;

@end

@interface PlayerDetailsViewController : UITableViewController

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

当“回去”时:

- (IBAction)cancel:(id)sender
{
    [self.delegate playerDetailsViewControllerDidCancel:self];
}



我的简单问题是为什么这个并发症?为什么要使用代理和协议?

我已经使用“Java”样式更改了代码,现在我将第一个引用传递给第二个控制器,一切正常。

第一个控制器:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
...
        playerDetailsViewController.playerViewController = self;
}

第二控制器:

@property (strong, readwrite) PlayerViewController *playerViewController;

那么,使用委托而不是简单地在ViewControllers之间传递引用有什么好处?

谢谢!

2 个答案:

答案 0 :(得分:1)

有几个原因:

  • As Leonardo says,使用引用将两个视图控制器连接在一起。您应该只传递所需的数据,而不是整个类
  • 这就是Objective-C应用程序倾向于构建的方式。通过使用不同的方法,您可以让经验丰富的开发人员更难理解您的应用
  • (你并不总是需要你的第二课中的代表 - 例如当它只显示时 - 所以你的示例代码比通常情况下更复杂)

与最后一点相关,您的代码已经比它需要的更难了。 UIStoryboardSegue具有指向源和目标视图控制器的属性;没有必要弄乱导航控制器。

答案 1 :(得分:0)

以Java方式放置,如果使用强类型,则绑定到单个类。 相反,委托最终是一个符合协议的类。 所以你可以将许多类作为委托传递给playerDetail,只要它们符合@protocol。

就像在java中转换和传递接口而不是具体类。 你可能知道List接口和所有ArrayList,LinkedList ......等具体实现。

有一点我不明白为什么他们通过导航来获得目标控制器。我一直用:

MyDestinationViewController *dvc = [segue destinationViewController];

这样您就可以在许多没有导航控制器的情况下使用。