如何在'纯'Swift中创建弱协议引用(不带@objc)
本文翻译自: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 usedunowned
) and always usevar
(notlet
) so that the optional can be set tonil
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 theweak
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 theclass
keyword, butAnyObject
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)相关推荐
- react中纯函数_如何在纯React中创建电子邮件芯片
react中纯函数 by Andreas Remdt 由Andreas Remdt 如何在纯React中创建电子邮件芯片 (How to create email chips in pure Reac ...
- swift视图容器_如何使用IBDesignable在Swift中创建漂亮的,可重复使用的渐变视图...
swift视图容器 by Lee Dowthwaite 通过李道思韦特 如何使用IBDesignable在Swift中创建漂亮的,可重复使用的渐变视图 (How to create a beautif ...
- 如何在sqlite3连接中创建并调用自定义函数
#!/user/bin/env python # @Time :2018/6/8 14:44 # @Author :PGIDYSQ #@File :CreateFunTest.py '''如何在sql ...
- 如何在ORACLE CLOUD中创建和访问容器集群丨内附官方文档链接
墨墨导读:本文描述如何在Oracle Cloud中创建并访问容器服务.为了简单,所有的操作都是针对root隔离区. 创建允许容器运行的政策官方文档链接 这一步是必须的,否则可以增加容器容器. 官方文档 ...
- java 线程中创建线程_如何在Java 8中创建线程安全的ConcurrentHashSet?
java 线程中创建线程 在JDK 8之前,还没有办法在Java中创建大型的线程安全的ConcurrentHashSet. java.util.concurrent包甚至没有一个名为Concurren ...
- 如何在Java 8中创建线程安全的ConcurrentHashSet?
在JDK 8之前,还没有办法在Java中创建大型的线程安全的ConcurrentHashSet. java.util.concurrent包甚至没有一个名为ConcurrentHashSet的类,但是 ...
- 如何在React Native中创建精美的动画加载器
by Vikrant Negi 通过Vikrant Negi 如何在React Native中创建精美的动画加载器 (How to create a beautifully animated load ...
- 如何在geth中创建genesis.json_Adobe XD 入门教程-如何在 Adobe XD 中创建交互式原型?...
完成屏幕设计后,您可以将各屏幕互相连接,以便直观地了解用户如何体验您的应用程序或网站.Adobe XD 允许您创建交互式原型,直观地展示如何在屏幕或线框之间导航.您可以预览交互,验证用户体验并对设计进 ...
- 如何安装html启动器,如何在Spring Boot中创建自己的启动器?
如何在Spring Boot中创建自己的启动器? 也许你有一个内部库包或一个在整个应用程序环境中常用的开源库,如果要在多个Spring Boot应用程序中使用它,为它创建一个Spring Boot启动 ...
最新文章
- 对比四种爬虫定位元素方法,你更爱哪个?
- win32: 查询滚动条相关信息的注意事项
- 微信小程序开发记录一,开发工具的使用
- [Windows编程] 监视DLL装载/卸载
- C#提取HTML代码中的文字(转)
- Mybatis Plus——[Could not set property 'id' of '***' with value]解决方案
- CRMEB v3.2微信小程序商城前端
- 解锁新的“维权方式”?车主放花圈维权!特斯拉大怒:低俗方法滋事
- [bzoj1026] [SCOI2009]windy数
- VUE axios发送cookie
- 作用域链涉及了什么计算机底层知识,你必须知道的Javascript知识点之深入理解作用域链的介绍...
- 巧技拾遗 | JavaScript 中 Array.every 和 Array.map 的巧妙结合
- python工资一般多少-Python开发的工资一般多少
- Beyong Compare过期
- 如何将win7电脑变身WIFI热点,让手机、笔记本共享上网?
- 如何屏蔽知乎网页中的热搜
- x265探索与研究(一):x265下载安装与配置
- 坪山体育中心体育馆全景不同高度展示
- 达梦数据库-插入单引号‘和双引号‘‘
- 简述信息系统安全设计要考虑的几个层面,每个层面可能存在的安全威胁及其应对措施