为什么关键字"weak"只能应用于类和类绑定协议类型

Tho*_*hor 65 variables weak-references swift

当我weak在Swift中声明变量时,我有时会收到来自Xcode的错误消息:

'weak'可能只适用于类和类绑定协议类型

我只是想知道为什么关键字weak只能应用于类和类绑定协议类型?它背后的原因是什么?

Jak*_*Jak 124

此错误的一个常见原因是您已声明自己的协议,但忘记继承NSObjectProtocol:

protocol PenguinDelegate: NSObjectProtocol {
    func userDidTapThePenguin()
}

class MyViewController: UIViewController {
    weak var delegate: PenguinDelegate?
}
Run Code Online (Sandbox Code Playgroud)

如果您忘记继承,上面的代码会给您错误NSObjectProtocol.原因是weak只对引用类型(类)有意义.因此,通过明确声明PenguinDelegate是针对类而不是值类型,使编译器不那么紧张.

  • 是的,它的工作原理.但你不知道为什么.`weak`是引用类型的限定符,对于值类型没有意义,因为值类型根据定义不能很弱.引用类型*和*值类型可以采用协议.所以你应该通过引用类型来限制它****protocol PenguinDelegate:class {}`在这里,你只是通过`NSObjectProtocol'来约束协议,它也是引用类型,这就是为什么有用. (12认同)
  • 使用`protocol PenguinDelegate:class`,它不依赖于Objective-C运行时但仍能解决问题. (4认同)
  • @Apostolos弱引用仅在类中有效.通过继承NSObjectProtocol,您可以向编译器保证协议将仅用于类(而不是用于枚举等). (3认同)

Aar*_*112 60

protocol PenguinDelegate: class {
    func userDidTapThePenguin()
}

class MyViewController: UIViewController {
    weak var delegate: PenguinDelegate?
}
Run Code Online (Sandbox Code Playgroud)

如果您在协议之后键入类,它也可以正常工作,对于NSObjectProtocol来说似乎更合适.


das*_*ght 58

weak是引用类型的限定符(与值类型相反,例如structs和内置值类型).

引用类型允许您对同一对象进行多次引用.当最后一个强引用停止引用它时,对象将被释放(弱引用不计数).

另一方面,值类型由副本分配.引用计数不适用,因此weak修饰符对它们没有意义.


小智 12

好吧,以防万一其他人认为你的代码中的所有内容都像我一样正确,请检查你是否错误地将其替换:为了=.

这就是我所拥有的.它也给了我同样的错误:

protocol PenguinDelegate: class {
    func userDidTapThePenguin()
}

class MyViewController: UIViewController {
    weak var delegate = PenguinDelegate?
}
Run Code Online (Sandbox Code Playgroud)

但正确的方法是:

protocol PenguinDelegate: class {
    func userDidTapThePenguin()
}

class MyViewController: UIViewController {
    weak var delegate: PenguinDelegate?
}
Run Code Online (Sandbox Code Playgroud)

你看得到差别吗?我花了一段时间才看到我有一个等号而不是冒号.还要注意我确实在同一行中得到了其他错误,因为我已经确定我的第一个错误似乎最有可能是真正的问题:

- weak可能只适用于类和类绑定协议类型

: - <


Dav*_*.ca 5

我发现在一种情况下,您甚至有类类型,但仍然收到此错误消息。

例如,

class MyVC: UIViewController {
   var myText: UITextView = {
      [weak self]
      let text = UITextView()
      // some codes using self
      return text
   }()
}
Run Code Online (Sandbox Code Playgroud)

这里一个UITextView对象作为 的初始化从匿名块返回var myText。我收到了相同类型的错误消息。要解决此问题,var必须将其标记为lazy

class MyVC: UIViewController {
   lasy var myText: UITextView = {
      [weak self]
      let text = UITextView()
      // some codes using self
      return text
   }()
}
Run Code Online (Sandbox Code Playgroud)