为什么关键字"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 是引用类型的限定符(相对于值类型,例如 structs 和内置值类型)。

引用类型允许您对同一个对象有多个引用。当最后一个强引用停止引用对象时,对象将被释放(弱引用不算在内)。

另一方面,值类型是通过复制分配的。引用计数不适用,因此 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 会报告错误。

  1. weak 不适用于值类型。
  2. 弱来图仅供class.

"weak" 可以应用继承自 class 或 class 绑定协议类型的任何内容

  1. Class 协议: 协议 ViewControllerDelegate : class { func getInformationk(value: String?) }
  2. NSObjectProtocol:

    协议 ViewControllerDelegate : NSObjectProtocol { func getInformation(value: String?) }