什么是委派,为什么它在iOS编程中很重要?


11

目前,我正在自学iOS编程,我发现真正难以理解的一个概念是委托。它是什么?为什么以及如何使用?有什么好处?我正在阅读的书中的技术性著作很难理解。


4
您可能会发现堆栈溢出上的目标c + delegates标签交集很有用。

Answers:


16

要了解delegates,您必须了解protocols

A protocol就像服务合同。当一个对象(通常是UIViewController子类,但并非总是)签署该合同时,它说的是“我有兴趣提供逻辑来支持您发送给我的消息”。这类似于NSNotificationCenter在签署兴趣级别方面,区别在于使用委派的对象一次只能拥有一个delegate,而多个对象可以同一对象进行签名NSNotification

苹果公司普遍使用授权。不过,您越来越多地看到Apple将其许多API移至blocks,与callbacks其他语言类似。

话虽如此,即使我认为委托本身就是一种设计模式,委托也有助于维护MVC。它有助于将模型与控制器分离。例如在约翰·卡特赖特(John Cartwright)的示例中,a UITableView知道如何显示行和节。UITableViewCells由于性能原因,它知道如何重用。它知道所有其他UIScrollView已知的东西。但是它不知道显示哪些单元格。它不知道用什么填充这些单元格。它不知道要为给定重用哪些单元格NSIndexPath。无论如何,这确实应该是控制器的工作。委托允许表视图将这种非视图逻辑卸载到应该承担该责任的对象上。

不仅如此,您在对象的整个生命周期中都不会被锁定在一个委托中。您可以轻松地为给定拥有多个数据源,UITableView并根据需要在运行时切换它们。

因此,一方面,委派对于将数据提供给对象并响应对象的交互非常有用。你会看到它在很多UIKit类,这样的的UITableViewUIPickerViewUICollectionView,等。

但是,当您要在对象之间传递信息时,委托也非常有用。您可以非常轻松地创建自己的协议并注册自己的对象以遵循它们。此外,协议方法是@required默认设置,但是您可以指定一些方法@optional。如果需要,可以为您提供一些不错的灵活性。假设您有一个父视图控制器和一个子视图控制器。也许您正在使用新的Containment API来执行此操作。通常,如果您需要将信息从父级传递给子级,则可以使用属性来实现。做完了 但是,如果您需要将信息从孩子传回给父母,该怎么办?也许孩子有所改变,您需要通知父母。当然,您可以对某些值进行一些KVO。但是也许您想知道何时按下按钮。只需在子视图控制器中创建一个新协议

@protocol MyChildDelegate
- (void)buttonWasTappedInChild:(MyChildViewController *)childViewController;
@end

@interface MyChildViewController : UIViewController

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

@end

在MyChildViewController中,点击按钮时,只需检查委托是否响应委托消息(如果是必需的,并且委托未实现该方法,则会崩溃。@optional如果需要,可以创建该方法)并发送它:

- (IBAction)someButtonTapped:(id)sender {
    if ([self.delegate respondsToSelector:@selector(buttonWasTappedInChild:)]) {
        [self.delegate buttonWasTappedInChild:self];
    }
}

然后将MyChildViewController的委托设置为self- (void)buttonWasTappedInChild:(MyChildViewController *)childViewController在父视图控制器中实现。繁荣!您有从孩子传到父母的信息。这两个对象之间的关系甚至不必像父/子一样紧密。这是一项服务合同,只要签约的对象通过实施所需的方法来维持其讨价还价的条件,您就可以做到!

注意:委托应该是弱属性/分配属性,否则,您将进入一个保留周期,在该周期中无法释放任何对象。

希望这可以帮助!


2

委托是在正常对象上无济于事的情况下实现某些功能的对象。它是依赖注入的一种形式。

对于一个具体的示例,请查看UITableViewDelegate协议。这些方法对于直接实现表格视图没有意义,因为选择表格视图行的操作在每个应用程序(可能在每个表格视图)中都不同。委托有一个方法,-tableView:didSelectRowAtIndexPath:因此您可以创建一个处理行选择的对象,而不必为要实现的每个单独操作将表视图子类化。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.