ios - Swift UITableView 委托(delegate)和数据源声明和保留周期

标签 ios swift

据我所知,要在 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/

相关文章:

ios - 动画 UIButton 的文本以捏合和捏开不起作用

javascript - 从源 WKWebView (window.opener) 访问 JavaScript 函数

ios - tableview 最后一个单元格内的动画

ios - 如何正确编写plutil命令(数组和字符串)

swift - 是否有一种简单的类似 swift 的方法来匹配 case 语句中的确切类?

ios - Swift:UIBezierPath bezierPathByReversingPath() 问题

ios - 有什么方法可以测试 UIAutomation 测试的代码覆盖率吗?

ios - iTunes Connect/Testflight - 请求的应用程序不可用或不存在

ios - 计算距离另一对纬度/经度坐标特定距离的纬度/经度坐标

swift - SwiftUI 应用程序的 NavigationView 中的 onAppear 和 onDisappear 是否按预期运行?