据我所知,要在 swift 中使用委托(delegate)模式,我必须像这样声明一个属性:
weak var delegate: TheDelegateProtocol!
像这样的协议(protocol):
@class_protocol protocol TheDelegateProtocol {
}
为了避免保留循环并坚持我们在 objective-c 中习惯做的事情。
现在,如果我查看它们在 UITableView 定义中的内容,我只会看到:
var dataSource: UITableViewDataSource!
var delegate: UITableViewDelegate!
和:
protocol UITableViewDelegate : NSObjectProtocol, UIScrollViewDelegate {
[...]
}
我想这与它实际上只绑定(bind)到 Objective C 的事实有关,并且 Objective C 定义可能优先于 swift 定义,但我在文档中找不到官方解释。
最佳答案
这与通常许多 Cocoa 代表并不弱的原因相同。 Cocoa 的大部分内容不是使用 ARC 编写的——因为它们先于它。他们手动管理内存,就像我们在过去的美好时光里不得不做的那样。所以他们没有得到 ARC-weak 的乐趣(weak
在这里表示)。他们使用纯粹的、非内存管理的委托(delegate)分配(和数据源)。他们不保留它,所以没有保留周期;但由于它们不使用 ARC,因此它们不是碰撞安全的。
因此,您有责任在主实例的生命周期内不让这样的委托(delegate)消失,以免它试图向悬挂指针发送消息并崩溃。
您可以通过实验看到这一点(这是 Objective-C,但您会很容易明白这一点):
self->_obj = [NSObject new];
nav.delegate = self->_obj // nav is our navigation controller, the root view controller
dispatch_async(dispatch_get_main_queue(), ^{
// cry havoc, and let slip the dogs of war!
self->_obj = nil; // releases obj - now what is nav.delegate pointing to??
NSLog(@"Nav Controller delegate: %@", ((UINavigationController*)self.window.rootViewController).delegate); // if you're lucky it might print something!
// or more likely it will just crash, or maybe print and *then* crash
});
这种崩溃正是 ARC-weak 所防止的,因为它会自动将悬空指针替换为 nil - 并且在 Objective-C 中向 nil 发送消息是无害的。
关于ios - Swift UITableView 委托(delegate)和数据源声明和保留周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24468661/