Home Articles

如何在'pure' Swift(没有@objc)中创建弱协议引用

Asked
Viewed 1752 times
482

weak 引用似乎在Swift中不起作用,除非 protocol 被声明为 @objc ,我在纯Swift应用程序中不需要它 .

此代码给出了编译错误( weak 不能应用于非类类型 MyClassDelegate ):

class MyClass {
  weak var delegate: MyClassDelegate?
}

protocol MyClassDelegate {
}

我需要在协议前加上 @objc ,然后才能工作 .

问题:什么是'pure' Swift方式完成 weak delegate

5 Answers

  • 898

    AnyObject 是在Swift中使用弱引用的官方方法 .

    class MyClass {
        weak var delegate: MyClassDelegate?
    }
    
    protocol MyClassDelegate: AnyObject {
    }
    

    来自Apple:

    为防止强引用循环,应将委托声明为弱引用 . 有关弱引用的详细信息,请参阅类实例之间的强引用循环 . 将协议标记为仅限类将稍后允许您声明委托必须使用弱引用 . 您通过继承AnyObject将协议标记为仅仅类,如“仅类协议”中所述 .

    https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276

  • 213

    Update: 看起来手册已更新,我所指的示例已被删除 . 请参阅上面@ @ flainez的回复编辑 .

    Original: 即使您没有与Obj-C互操作,使用@objc也是正确的方法 . 它确保您的协议应用于类而不是枚举或结构 . 请参见手册中的"Checking for Protocol Conformance" .

  • 22

    您需要将协议类型声明为 class .

    protocol ProtocolNameDelegate: class {
        // Protocol stuff goes here
    }
    
    class SomeClass {
        weak var delegate: ProtocolNameDelegate?
    }
    

    我的理解是使用 class ,您保证此协议仅用于类,而不用于枚举或结构等其他内容 .

  • 8

    Apple使用“NSObjectProtocol”而不是“class” .

    public protocol UIScrollViewDelegate : NSObjectProtocol {
       ...
    }
    

    这也适用于我并删除了我在尝试实现自己的委托模式时看到的错误 .

  • -6

    补充答案

    我一直很困惑代表们是否应该是弱者 . 最近我学到了更多关于代表以及何时使用弱引用的知识,所以让我在这里为了未来的 Spectator 添加一些补充点 .

    • 使用 weak 关键字的目的是避免强引用周期(保留周期) . 当两个类实例具有相互强引用时,就会发生强引用循环 . 他们的引用计数永远不会变为零,因此它们永远不会被释放 .

    • 如果委托是一个类,您只需要使用 weak . Swift结构和枚举是值类型(它们的值在创建新实例时被复制),而不是引用类型,因此它们不会产生强引用循环 .

    • weak 引用始终是可选的(否则您将使用 unowned )并始终使用 var (而不是 let ),以便在取消分配时可选将 nil 设置为 nil .

    • 父类自然应该对其子类具有强引用,因此不使用 weak 关键字 . 但是,当孩子想要对其父级的引用时,应该使用 weak 关键字使其成为弱引用 .

    当您想要引用您不拥有的类时,应该使用

    • weak ,而不仅仅是引用其父级的子类 . 当两个非等级类需要相互引用时,选择一个为弱 . 你选择的那个取决于具体情况 . 有关详细信息,请参阅this question的答案 .

    • As a general rule, delegates should be marked as weak 因为大多数代表都引用了他们不拥有的类 . 当孩子使用委托与父母沟通时,这肯定是正确的 . 但是,仍有some situations代表可以而且应该使用强引用 .

    • 协议可用于reference types(类)和value types(结构,枚举) . 因此,在您需要使委托变弱的情况下,您必须将 class 关键字添加到协议中,以便它知道它仅用于引用类型 .

    protocol MyClassDelegate: class {
        // ...
    }
    
    class SomeClass {
        weak var delegate: MyClassDelegate?
    }
    

    进一步研究

    阅读以下文章有助于我更好地理解这一点 . 他们还讨论了 unowned 关键字等相关问题以及闭包发生的强引用周期 .

    相关

Related