当我weak
在Swift中声明变量时,有时会从Xcode收到错误消息:
“弱”仅可应用于类和类绑定协议类型
我只是想知道为什么关键字weak
只能应用于类和类绑定的协议类型?背后的原因是什么?
Answers:
weak
是引用类型的限定符(与值类型相对,例如struct
s和内置值类型)。
引用类型使您可以对同一对象有多个引用。当最后一个强引用停止引用该对象时,该对象将被释放(弱引用不计算在内)。
另一方面,值类型是通过副本分配的。引用计数不适用,因此weak
修饰符对它们没有意义。
发生此错误的一个常见原因是您已经声明了自己的协议,但是却忘记继承自AnyObject
:
protocol PenguinDelegate: AnyObject {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
如果您忘记继承,上面的代码将给您错误AnyObject
。原因是weak
仅对引用类型(类)有意义。因此,您可以通过清楚地指出PenguinDelegate用于类而不是值类型,来减轻编译器的紧张感。
NSObjectProtocol
吗?对于一个,您不必处理添加weak
修饰符。
weak
是引用类型的限定符,对值类型没有意义,因为值类型在定义上不能弱。引用类型和值类型可以采用协议。因此,您应该限制它只能由引用类型实现:protocol PenguinDelegate: class { }
在这里,您要限制协议仅由NSObjectProtocol
s实现,而s也是引用类型,这就是它起作用的原因。
protocol PenguinDelegate: class
不依赖于Objective-C运行时,但仍然可以解决问题。
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
如果在协议后键入class,那么它也可以正常工作,并且看起来更适合NSObjectProtocol。
好了,以防万一别人认为你有你的代码像我的一切正确,请确认您没有误更换了:
通过=
。
这就是我所拥有的。这也给了我与上面相同的错误:
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate = PenguinDelegate?
}
但是正确的方法是:
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
你看得到差别吗?我花了一段时间才看到我有一个等号而不是冒号。另请注意,由于我已确定我的第一个错误似乎最有可能是真正的问题,因此我在同一行上确实遇到了其他错误:
-
weak
只能应用于类和类绑定协议类型
:-<
我发现在一种情况下,您甚至拥有类类型,但仍然收到此错误消息。
例如,
class MyVC: UIViewController {
var myText: UITextView = {
[weak self]
let text = UITextView()
// some codes using self
return text
}()
}
在此,UITextView
从匿名块返回一个对象,作为的初始化var myText
。我收到了相同类型的错误消息。要解决此问题,var
必须将其标记为lazy
:
class MyVC: UIViewController {
lasy var myText: UITextView = {
[weak self]
let text = UITextView()
// some codes using self
return text
}()
}
仅供参考,谁没有更新。在实施了快速提案SE-0156 https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md之后,Swift文档中的“仅类协议”部分有了https现在描述://docs.swift.org/swift-book/LanguageGuide/Protocols.html使用AnyObject代替class。因此,将来有可能不推荐使用:class。
weak
仅适用于引用类型,因此,如果您从struct
(而不是class
)进行调用,则Xcode将报告错误。
“弱”可以应用从类或类绑定协议类型继承的任何东西
NSObjectProtocol:
协议ViewControllerDelegate:NSObjectProtocol {func getInformation(value:String?)}
weak
仅与引用计数有关,并且仅对类进行引用计数