为什么关键字"weak"只能应用于class和class绑定的协议类型
Why can the keyword "weak" only be applied to class and class-bound protocol types
当我在 Swift 中将变量声明为 weak
时,我有时会收到来自 Xcode 的错误消息:
'weak' may only be applied to class and class-bound protocol types
或
'weak' must not be applied to non-class-bound 'SomeProtocol'; consider adding a protocol conformance that has a class bound
我想知道为什么关键字weak
只能应用于class和class绑定的协议类型?这个要求背后的原因是什么?
weak
用于 ARC(自动引用计数)。这意味着不添加引用计数。所以它只适用于 Class
。在 Swift 中,您将获得可选的安全值。
weak
是引用类型的限定符(相对于值类型,例如 struct
s 和内置值类型)。
引用类型允许您对同一个对象有多个引用。当最后一个强引用停止引用对象时,对象将被释放(弱引用不算在内)。
另一方面,值类型是通过复制分配的。引用计数不适用,因此 weak
修饰符对它们没有意义。
此错误的一个常见原因是您已声明自己的协议,但忘记继承自 AnyObject
:
protocol PenguinDelegate: AnyObject {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
如果您忘记从 AnyObject
继承,上面的代码会给您错误。原因是 weak
只对引用类型有意义 (类)。因此,通过明确声明 PenguinDelegate 适用于 类 而不是值类型,可以让编译器不那么紧张。
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
如果您在协议后键入 class,它也可以正常工作,而且似乎更适合 NSObjectProtocol。
我发现在一种情况下,您甚至有 class 类型,但您仍然收到此错误消息。
例如,
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
}()
}
万一其他人认为您的代码中的所有内容都像我一样正确,请检查您没有错误地将 :
替换为 =
。
这是我的。它也给了我与上面相同的错误:
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
may only be applied to class and class-bound protocol types
:-<
我试图捕获闭包的 String 和 Array-typed 属性。我收到这些错误:
'weak' may only be applied to class and class-bound protocol types, not '[String]'
'weak' may only be applied to class and class-bound protocol types, not 'String'
我在操场上玩了一会儿,结果发现,对于这些类型来说,捕获自我就足够了。
我在 swift 中使用 objective C class 作为 scrolView。我创建了那个滚动视图的 IBOutlet。在编译代码时开始显示此错误。
因此,要解决此类问题,请在桥接 header
中导入 class
import "YourClass.h"
我正在使用 Xcode 9.2 和 swift 3.2
仅供参考,谁没有更新。
在 swift 提议 SE-0156 https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md was implemented, there is in the Swift docs "Class-Only Protocols section" https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID281 现在描述为 使用 AnyObject 而不是 class。
因此,: class 将来可能会被弃用。
weak
仅适用于引用类型,因此如果您从 struct
(而不是 class
)调用,Xcode 会报告错误。
- weak 不适用于值类型。
- 弱来图仅供class.
"weak" 可以应用继承自 class 或 class 绑定协议类型的任何内容
- Class 协议:
协议 ViewControllerDelegate : class {
func getInformationk(value: String?) }
NSObjectProtocol:
协议 ViewControllerDelegate : NSObjectProtocol {
func getInformation(value: String?) }
当我在 Swift 中将变量声明为 weak
时,我有时会收到来自 Xcode 的错误消息:
'weak' may only be applied to class and class-bound protocol types
或
'weak' must not be applied to non-class-bound 'SomeProtocol'; consider adding a protocol conformance that has a class bound
我想知道为什么关键字weak
只能应用于class和class绑定的协议类型?这个要求背后的原因是什么?
weak
用于 ARC(自动引用计数)。这意味着不添加引用计数。所以它只适用于 Class
。在 Swift 中,您将获得可选的安全值。
weak
是引用类型的限定符(相对于值类型,例如 struct
s 和内置值类型)。
引用类型允许您对同一个对象有多个引用。当最后一个强引用停止引用对象时,对象将被释放(弱引用不算在内)。
另一方面,值类型是通过复制分配的。引用计数不适用,因此 weak
修饰符对它们没有意义。
此错误的一个常见原因是您已声明自己的协议,但忘记继承自 AnyObject
:
protocol PenguinDelegate: AnyObject {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
如果您忘记从 AnyObject
继承,上面的代码会给您错误。原因是 weak
只对引用类型有意义 (类)。因此,通过明确声明 PenguinDelegate 适用于 类 而不是值类型,可以让编译器不那么紧张。
protocol PenguinDelegate: class {
func userDidTapThePenguin()
}
class MyViewController: UIViewController {
weak var delegate: PenguinDelegate?
}
如果您在协议后键入 class,它也可以正常工作,而且似乎更适合 NSObjectProtocol。
我发现在一种情况下,您甚至有 class 类型,但您仍然收到此错误消息。
例如,
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
}()
}
万一其他人认为您的代码中的所有内容都像我一样正确,请检查您没有错误地将 :
替换为 =
。
这是我的。它也给了我与上面相同的错误:
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
may only be applied to class and class-bound protocol types
:-<
我试图捕获闭包的 String 和 Array-typed 属性。我收到这些错误:
'weak' may only be applied to class and class-bound protocol types, not '[String]'
'weak' may only be applied to class and class-bound protocol types, not 'String'
我在操场上玩了一会儿,结果发现,对于这些类型来说,捕获自我就足够了。
因此,要解决此类问题,请在桥接 header
中导入 classimport "YourClass.h"
我正在使用 Xcode 9.2 和 swift 3.2
仅供参考,谁没有更新。 在 swift 提议 SE-0156 https://github.com/apple/swift-evolution/blob/master/proposals/0156-subclass-existentials.md was implemented, there is in the Swift docs "Class-Only Protocols section" https://docs.swift.org/swift-book/LanguageGuide/Protocols.html#ID281 现在描述为 使用 AnyObject 而不是 class。 因此,: class 将来可能会被弃用。
weak
仅适用于引用类型,因此如果您从 struct
(而不是 class
)调用,Xcode 会报告错误。
- weak 不适用于值类型。
- 弱来图仅供class.
"weak" 可以应用继承自 class 或 class 绑定协议类型的任何内容
- Class 协议: 协议 ViewControllerDelegate : class { func getInformationk(value: String?) }
NSObjectProtocol:
协议 ViewControllerDelegate : NSObjectProtocol { func getInformation(value: String?) }