weak
引用似乎不适用于Swift,除非protocol
被声明为@objc
,我不想在纯粹的Swift应用中使用。< / p>
此代码给出了编译错误(weak
无法应用于非类类型MyClassDelegate
):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
我需要在协议前加上@objc
,然后才有效。
问题:什么是纯粹的&#39;快速完成weak
delegate
?
答案 0 :(得分:964)
您需要将协议类型声明为class
。
protocol ProtocolNameDelegate: class {
// Protocol stuff goes here
}
class SomeClass {
weak var delegate: ProtocolNameDelegate?
}
我的理解是使用class
,您可以保证此协议仅用于类,而不用于枚举或结构等其他内容。
答案 1 :(得分:244)
我一直很困惑代表们是否应该是弱者。最近我学到了更多关于代表以及何时使用弱引用的知识,所以让我在这里为了未来的观众添加一些补充点。
使用weak
关键字的目的是避免强引用周期(保留周期)。当两个类实例具有相互强引用时,就会发生强引用循环。他们的引用计数永远不会变为零,因此它们永远不会被释放。
如果委托是一个类,您只需要使用weak
。 Swift结构和枚举是值类型(它们的值在创建新实例时被复制),而不是引用类型,因此它们不会进行强大的引用循环。
weak
引用始终是可选的(否则您将使用unowned
)并始终使用var
(而非let
),以便将可选项设置为<{1}}何时被解除分配。
父类自然应该对其子类具有强引用,因此不使用nil
关键字。但是,如果孩子想要引用其父级,则应使用weak
关键字将其作为弱引用。
weak
。当两个非分层类需要相互引用时,选择一个为弱。你选择的那个取决于具体情况。有关详情,请参阅this question的答案。
作为一般规则,代理应标记为weak
,因为大多数代理都引用了他们不拥有的类。当孩子使用委托与父母沟通时,这肯定是正确的。但是,仍然有some situations代表可以而且应该使用强引用。
协议可用于reference types(类)和value types(结构,枚举)。因此,在您需要使委托变弱的情况下,您必须将weak
关键字添加到协议中,以便它知道它仅用于引用类型。
class
阅读以下文章有助于我更好地理解这一点。他们还讨论了相关问题,例如protocol MyClassDelegate: class {
// ...
}
class SomeClass {
weak var delegate: MyClassDelegate?
}
关键字以及闭包发生的强引用周期。
答案 2 :(得分:30)
AnyObject
是在Swift中使用弱引用的官方方式。
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate: AnyObject {
}
来自Apple:
为防止强引用周期,委托应声明为 弱参考。有关弱引用的更多信息,请参阅 类实例之间的强引用循环。标记协议 因为只有类才允许你声明委托必须 使用弱引用。您将协议标记为仅限类 继承自 AnyObject ,如“仅限类协议”中所述。
答案 3 :(得分:9)
<强>更新强> 看起来手册已经更新,我所指的示例已被删除。请参阅上面@ @ flainez的回复编辑。
<强>原始强> 即使您没有与Obj-C互操作,使用@objc也是正确的方法。它确保您的协议应用于类而不是枚举或结构。请参阅&#34;检查协议一致性&#34;在手册中。
答案 4 :(得分:0)
弱限定符仅适用于引用对象。除非您在协议中添加 @objc
、AnyObject
或 class
限定符,否则符合协议的对象可能不是引用对象。
因此您需要使用这些限定符(推荐使用 AnyObject
,因为预计 class
将被弃用。)
顺便说一下,即使在“纯 Swift”应用程序中,有时也需要将 @objc
添加到您的类和属性中。它与您的开发语言无关。它会导致编译器以与 Objective-C 运行时兼容的方式构建您的代码,这是某些操作系统接口(例如目标/操作和旧式键路径)所必需的
答案 5 :(得分:-2)
以下示例
protocol NameOfProtocol: class {
// member of protocol
}
class ClassName: UIViewController {
weak var delegate: NameOfProtocol?
}
答案 6 :(得分:-9)
Apple使用&#34; NSObjectProtocol&#34;而不是&#34; class&#34;。
public protocol UIScrollViewDelegate : NSObjectProtocol {
...
}
这也适用于我,并删除了我在尝试实现自己的委托模式时看到的错误。