iOS开发常见问题集之Delegate

0 关键词

代理模式、delegate

1 概述

Delegate是Cocoa的精髓之一,Delegate在Cocoa及各大框架下出现频率极高,很少有框架像Cocoa这样对代理模式如此痴迷,因此Delegate在iOS/MacOS开发中的重要性不言而喻。不过近年来Block在官方新API出现的频率明显增多,Block取代Delegate完成了不少功能。但Delegate仍然大量存在于Cocoa框架之中。

2 Delegate的声明步骤

完整的代理声明步骤如图所示,左侧是委托方(如UITableView),右侧是代理方(如UIViewController或UITableViewController)。


Delegate声明步骤

3 使用Delegate的常见问题

3.1 代理不执行

  • 检查是否指定的代理人。如在ViewController中检查是否指定了TableView的代理_tableView.delegate = self;。这是很多人都会忘记的一步,当代理不执行时才会想起来还没有指定代理。

如何避免忘记指定代理
我个人一般会在添加子视图的时候指定代理,代码写法如下:

//Code in ViewController
[self.view addSubview:({
        _tableView = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStyleGrouped];
        _tableView.dataSource = self;
        _tableView.delegate = self;
        _tableView;
    })];

()是什么
GNU C支持一种叫作Statements and Declarations in Expressions(怎么翻译?)的语法形式,可以在小括号内写多行代码,最后一行必须为返回值。这种写法在GCC和LLVM下都可编译通过。如:

({ int y = foo (); int z;
        if (y > 0) z = y;
        else z = - y;
        z; })
 #define max(a,b) ((a) > (b) ? (a) : (b))

原文出处 Statements and Declarations in Expressions

  • 检查声明delegate的六步骤中的其余五步是否有遗漏。
  • 在特定情况下,部分代理方法确实不会执行。常见的比如UITableView的tableView:numberOfRowsInSection:返回0时,tableView:cellForRowAtIndexPath:协议方法不会执行。

3.2 通过恰当的内存语义设置,避免引用循环

代理对象不拥有委托对象,所以属性在ARC下使用weak修饰,在MRC下使用assign修饰(现在估计很少有人使用MRC了吧)。

3.3 由代理引起的Crash

  • 出现unrecognized selector sent to instance 情况一
    出现该问题是因为指定了代理人,但该代理人未实现协议方法。解决方案一般从两方面入手:
    一是,编译器提示。使用@requested和@optional区别哪有方法必须实现,哪些可以不实现。
    二是,添加防御性的自省代码。这样即便未实现方法,也不会crash。
if (self.delegate && [self.delegate respondsToSelector:@selector(didClickButton:)]) {
        [self.delegate didClickButton:button];
    }

*出现 unrecognized selector sent to instance情况二
出现该问题的原因是代理对象被释放了之后委托对象又向被释放了的代理对象发送了消息。在MRC中,代理对象被设置为assign,当委托对象被释放掉之后,delegate的指针并没有被置空。所以需要在合适的时间点(例如dealloc方法内)将delegate设置为nil。在ARC中,代理对象被设置为weak,委托对象被释放时,用weak修饰的属性会自动置nil,所以不会crash。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • *面试心声:其实这些题本人都没怎么背,但是在上海 两周半 面了大约10家 收到差不多3个offer,总结起来就是把...
    Dove_iOS阅读 27,400评论 30 472
  • 1.badgeVaule气泡提示 2.git终端命令方法> pwd查看全部 >cd>ls >之后桌面找到文件夹内容...
    i得深刻方得S阅读 10,256评论 1 9
  • 1.Difference between shallow copy and deep copy? 浅复制和深复制的...
    用心在飞阅读 4,612评论 0 9
  • 37.cocoa内存管理规则 1)当你使用new,alloc或copy方法创建一个对象时,该对象的保留计数器值为1...
    如风家的秘密阅读 4,383评论 0 4
  • *7月8日上午 N:Block :跟一个函数块差不多,会对里面所有的内容的引用计数+1,想要解决就用__block...
    炙冰阅读 7,359评论 1 14

友情链接更多精彩内容