本文翻译自:How can I make a weak protocol reference in 'pure' Swift (without @objc)

weak references don't seem to work in Swift unless a protocol is declared as @objc , which I don't want in a pure Swift app. weak引用似乎在Swift中不起作用,除非将protocol声明为@objc ,我不想在纯Swift应用程序中使用它。

This code gives a compile error ( weak cannot be applied to non-class type MyClassDelegate ): 此代码给出了编译错误( weak不能应用于非类型MyClassDelegate ):

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

I need to prefix the protocol with @objc , then it works. 我需要在协议前加上@objc ,然后@objc

Question: What is the 'pure' Swift way to accomplish a weak delegate ? 问题:完成weak delegate的'纯'Swift方法是什么?


#1楼

参考:https://stackoom.com/question/1cykC/如何在-纯-Swift中创建弱协议引用-不带-objc


#2楼

Update: It looks like the manual has been updated and the example I was referring to has been removed. 更新:看起来手册已更新,我所指的示例已被删除。 See the edit to @flainez's answer above. 请参阅上面@ @ flainez的回复编辑。

Original: Using @objc is the right way to do it even if you're not interoperating with Obj-C. 原文:即使你没有与Obj-C互操作,使用@objc也是正确的方法。 It ensures that your protocol is being applied to a class and not an enum or struct. 它确保您的协议应用于类而不是枚举或结构。 See "Checking for Protocol Conformance" in the manual. 请参阅手册中的“检查协议一致性”。


#3楼

You need to declare the type of the protocol as class . 您需要将协议的类型声明为class

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

My understanding is that using class , you guarantee that this protocol will be used only on classes and no other stuff like enums or structs. 我的理解是使用class ,你保证这个协议只能用在类上,而不能用于其他东西,比如枚举或结构。


#4楼

Supplemental Answer 补充答案

I was always confused about whether delegates should be weak or not. 我一直很困惑代表们是否应该是弱者。 Recently I've learned more about delegates and when to use weak references, so let me add some supplemental points here for the sake of future viewers. 最近我学到了更多关于代表以及何时使用弱引用的知识,所以让我在这里为了未来的观众添加一些补充点。

  • The purpose of using the weak keyword is to avoid strong reference cycles (retain cycles). 使用weak关键字的目的是避免强引用循环 (保留循环)。 Strong reference cycles happen when two class instances have strong references to each other. 当两个类实例具有相互强引用时,就会发生强引用循环。 Their reference counts never go to zero so they never get deallocated. 他们的引用计数永远不会变为零,因此它们永远不会被释放。

  • You only need to use weak if the delegate is a class. 如果委托是一个类,你只需要使用weak Swift structs and enums are value types (their values are copied when a new instance is made), not reference types, so they don't make strong reference cycles. Swift结构和枚举是值类型(它们的值在创建新实例时被复制),而不是引用类型,因此它们不会产生强引用循环。

  • weak references are always optional (otherwise you would used unowned ) and always use var (not let ) so that the optional can be set to nil when it is deallocated. weak引用总是可选的(否则你会使用unowned )和总是使用var (未let ),使得可选可以设置为nil ,当它被释放。

  • A parent class should naturally have a strong reference to its child classes and thus not use the weak keyword. 父类自然应该对其子类具有强引用,因此不使用weak关键字。 When a child wants a reference to its parent, though, it should make it a weak reference by using the weak keyword. 但是,当一个孩子想要引用它的父元素时,它应该通过使用weak关键字使它成为弱引用。

  • weak should be used when you want a reference to a class that you don't own, not just for a child referencing its parent. 当您想要引用您不拥有的类时,应该使用weak ,而不仅仅是引用其父级的子类。 When two non-hierarchical classes need to reference each other, choose one to be weak. 当两个非分层类需要相互引用时,选择一个为弱。 The one you choose depends on the situation. 你选择的那个取决于具体情况。 See the answers to this question for more on this. 有关此问题的更多信息,请参阅此问题的答案。

  • As a general rule, delegates should be marked as weak because most delegates are referencing classes that they do not own. 作为一般规则,代理应标记为weak因为大多数代表都引用了他们不拥有的类。 This is definitely true when a child is using a delegate to communicate with a parent. 当孩子使用委托与父母沟通时,这肯定是正确的。 Using a weak reference for the delegate is what the documentation recommends. 对代表使用弱引用是文档建议的内容。 (But see this , too.) (但也要看到这一点。)

  • Protocols can be used for both reference types (classes) and value types (structs, enums). 协议可用于引用类型 (类)和值类型 (结构,枚举)。 So in the likely case that you need to make a delegate weak, you have to make it an object-only protocol. 因此,在可能需要使委托变弱的情况下,您必须使其成为仅对象协议。 The way to do that is to add AnyObject to the protocol's inheritance list. 这样做的方法是将AnyObject添加到协议的继承列表中。 (In the past you did this using the class keyword, but AnyObject is preferred now .) (在过去,您使用class关键字执行此操作,但现在首选AnyObject 。)

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

Further Study 进一步研究

Reading the following articles is what helped me to understand this much better. 阅读以下文章有助于我更好地理解这一点。 They also discuss related issues like the unowned keyword and the strong reference cycles that happen with closures. 他们还讨论了相关问题,如unowned关键字和闭包发生的强引用循环。

  • Delegate documentation 委托文件
  • Swift documentation: Automatic Reference Counting Swift文档: 自动引用计数
  • "Weak, Strong, Unowned, Oh My!" “弱,强,无主,哦,我的!” - A Guide to References in Swift - Swift中的参考指南
  • Strong, Weak, and Unowned – Sorting out ARC and Swift 强,弱和无主 - 整理ARC和Swift

Related 有关

  • How to make delegates in Swift 如何在Swift中创建委托
  • iOS: How To Make Weak Delegates In Swift iOS:如何在Swift中使弱代表
  • Swift delegation - when to use weak pointer on delegate Swift委托 - 何时在委托上使用弱指针

#5楼

Apple uses "NSObjectProtocol" instead of "class". Apple使用“NSObjectProtocol”而不是“class”。

public protocol UIScrollViewDelegate : NSObjectProtocol {...
}

This also works for me and removed the errors I was seeing when trying to implement my own delegate pattern. 这也适用于我并删除了我在尝试实现自己的委托模式时看到的错误。


#6楼

AnyObject is the official way to use a weak reference in Swift. AnyObject是在Swift中使用弱引用的官方方式。

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

From Apple: 来自Apple:

To prevent strong reference cycles, delegates should be declared as weak references. 为了防止强引用循环,应将委托声明为弱引用。 For more information about weak references, see Strong Reference Cycles Between Class Instances. 有关弱引用的详细信息,请参阅类实例之间的强引用循环。 Marking the protocol as class-only will later allow you to declare that the delegate must use a weak reference. 将协议标记为仅限类将稍后允许您声明委托必须使用弱引用。 You mark a protocol as being class-only by inheriting from AnyObject , as discussed in Class-Only Protocols. 您通过继承AnyObject将协议标记为仅仅类,如“仅类协议”中所述。

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

如何在'纯'Swift中创建弱协议引用(不带@objc)相关推荐

  1. react中纯函数_如何在纯React中创建电子邮件芯片

    react中纯函数 by Andreas Remdt 由Andreas Remdt 如何在纯React中创建电子邮件芯片 (How to create email chips in pure Reac ...

  2. swift视图容器_如何使用IBDesignable在Swift中创建漂亮的,可重复使用的渐变视图...

    swift视图容器 by Lee Dowthwaite 通过李道思韦特 如何使用IBDesignable在Swift中创建漂亮的,可重复使用的渐变视图 (How to create a beautif ...

  3. 如何在sqlite3连接中创建并调用自定义函数

    #!/user/bin/env python # @Time :2018/6/8 14:44 # @Author :PGIDYSQ #@File :CreateFunTest.py '''如何在sql ...

  4. 如何在ORACLE CLOUD中创建和访问容器集群丨内附官方文档链接

    墨墨导读:本文描述如何在Oracle Cloud中创建并访问容器服务.为了简单,所有的操作都是针对root隔离区. 创建允许容器运行的政策官方文档链接 这一步是必须的,否则可以增加容器容器. 官方文档 ...

  5. java 线程中创建线程_如何在Java 8中创建线程安全的ConcurrentHashSet?

    java 线程中创建线程 在JDK 8之前,还没有办法在Java中创建大型的线程安全的ConcurrentHashSet. java.util.concurrent包甚至没有一个名为Concurren ...

  6. 如何在Java 8中创建线程安全的ConcurrentHashSet?

    在JDK 8之前,还没有办法在Java中创建大型的线程安全的ConcurrentHashSet. java.util.concurrent包甚至没有一个名为ConcurrentHashSet的类,但是 ...

  7. 如何在React Native中创建精美的动画加载器

    by Vikrant Negi 通过Vikrant Negi 如何在React Native中创建精美的动画加载器 (How to create a beautifully animated load ...

  8. 如何在geth中创建genesis.json_Adobe XD 入门教程-如何在 Adobe XD 中创建交互式原型?...

    完成屏幕设计后,您可以将各屏幕互相连接,以便直观地了解用户如何体验您的应用程序或网站.Adobe XD 允许您创建交互式原型,直观地展示如何在屏幕或线框之间导航.您可以预览交互,验证用户体验并对设计进 ...

  9. 如何安装html启动器,如何在Spring Boot中创建自己的启动器?

    如何在Spring Boot中创建自己的启动器? 也许你有一个内部库包或一个在整个应用程序环境中常用的开源库,如果要在多个Spring Boot应用程序中使用它,为它创建一个Spring Boot启动 ...

最新文章

  1. 对比四种爬虫定位元素方法,你更爱哪个?
  2. win32: 查询滚动条相关信息的注意事项
  3. 微信小程序开发记录一,开发工具的使用
  4. [Windows编程] 监视DLL装载/卸载
  5. C#提取HTML代码中的文字(转)
  6. Mybatis Plus——[Could not set property 'id' of '***' with value]解决方案
  7. CRMEB v3.2微信小程序商城前端
  8. 解锁新的“维权方式”?车主放花圈维权!特斯拉大怒:低俗方法滋事
  9. [bzoj1026] [SCOI2009]windy数
  10. VUE axios发送cookie
  11. 作用域链涉及了什么计算机底层知识,你必须知道的Javascript知识点之深入理解作用域链的介绍...
  12. 巧技拾遗 | JavaScript 中 Array.every 和 Array.map 的巧妙结合
  13. python工资一般多少-Python开发的工资一般多少
  14. Beyong Compare过期
  15. 如何将win7电脑变身WIFI热点,让手机、笔记本共享上网?
  16. 如何屏蔽知乎网页中的热搜
  17. x265探索与研究(一):x265下载安装与配置
  18. 坪山体育中心体育馆全景不同高度展示
  19. 达梦数据库-插入单引号‘和双引号‘‘
  20. 简述信息系统安全设计要考虑的几个层面,每个层面可能存在的安全威胁及其应对措施

热门文章

  1. linux 命令-全称
  2. Windows2008R2部署SharePoint Server 2013(2)---安装篇
  3. mybatis集成 c3p0数据源
  4. 抓虫系列(三) 不要轻视web程序中常用的三个池 之数据库连接池
  5. Database2Sharp重要更新之生成Winform框架界面代码
  6. 用perl过滤文本中的IP和端口
  7. c primer plus--运算符、表达式和语句(第5章)--习题
  8. Hive分区(静态分区+动态分区)
  9. html5+css3动画学习总结
  10. HDU 5666 Segment 数论+大数