Why can the keyword "weak" only be applied to class and class-bound protocol types

42,124

Solution 1

weak is a qualifier for reference types (as opposed to value types, such as structs and built-in value types).

Reference types let you have multiple references to the same object. The object gets deallocated when the last strong reference stops referencing it (weak references do not count).

Value types, on the other hand, are assigned by copy. Reference counting does not apply, so weak modifier does not make sense with them.

Solution 2

One common reason for this error is that you have declared you own protocol, but forgot to inherit from AnyObject:

protocol PenguinDelegate: AnyObject {
    func userDidTapThePenguin()
}

class MyViewController: UIViewController {
    weak var delegate: PenguinDelegate?
}

The code above will give you the error if you forget to inherit from AnyObject. The reason being that weak only makes sense for reference types (classes). So you make the compiler less nervous by clearly stating that the PenguinDelegate is intended for classes, and not value types.

Solution 3

protocol PenguinDelegate: class {
    func userDidTapThePenguin()
}

class MyViewController: UIViewController {
    weak var delegate: PenguinDelegate?
}

If you type class after your protocol it works as well and seems more appropriate that for NSObjectProtocol.

Solution 4

Well just in case anyone else thinks that you have everything correct in your code like me, check that you did not mistakenly replaced the : by an =.

Here is what I had. It was also giving me the same error as above:

protocol PenguinDelegate: class {
    func userDidTapThePenguin()
}

class MyViewController: UIViewController {
    weak var delegate = PenguinDelegate?
}

But the correct way is:

protocol PenguinDelegate: class {
    func userDidTapThePenguin()
}

class MyViewController: UIViewController {
    weak var delegate: PenguinDelegate?
}

Do you see the difference? It took me a while to see that I had an equal sign instead of a colon. Also note that I did get other errors for the same line for I had decided my first error seem like the most likely to be the real problem :

-weak may only be applied to class and class-bound protocol types

:-<

Solution 5

I find out in one case where you even have class type but still you get this error message.

For example,

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

Here an UITextView object is returned from an anonymous block as initialization of var myText. I got the same type of error message. To resolve the issue, the var has to be marked as lazy:

class MyVC: UIViewController {
   lasy var myText: UITextView = {
      [weak self]
      let text = UITextView()
      // some codes using self
      return text
   }()
}
Share:
42,124

Related videos on Youtube

Thor
Author by

Thor

Updated on February 23, 2022

Comments

  • Thor
    Thor over 2 years

    When I'm declaring variables as weak in Swift, I sometimes get the error message from Xcode:

    'weak' may only be applied to class and class-bound protocol types

    or

    'weak' must not be applied to non-class-bound 'SomeProtocol'; consider adding a protocol conformance that has a class bound

    I'm wondering why the keyword weak can only applied to class and class-bound protocol types? What is the reason behind this requirement?

    • dan
      dan almost 8 years
      weak is only relevant to reference counting and only classes are reference counted
  • Apostolos Apostolidis
    Apostolos Apostolidis about 7 years
    what is the advantage of inheriting from NSObjectProtocol? My own delegates don't do that and I haven't encountered any problem in my uses
  • Vince O'Sullivan
    Vince O'Sullivan about 7 years
    @Apostolos Weak references are only valid in classes. By inheriting from NSObjectProtocol your are guaranteeing to the compiler that the protocol will only be used for classes (and not for enums, etc.).
  • yesthisisjoe
    yesthisisjoe almost 7 years
    @VinceO'Sullivan What's the advantage of guaranteeing that to the compiler? Isn't is easier to just not inherit from NSObjectProtocol? For one you don't have to deal with adding the weak modifier.
  • Martin
    Martin almost 7 years
    Yep, it works. But you don't know why. weak is a qualifier for reference types, it makes no sense with value types because value types cannot be weak by definition. A protocol can be adopted by reference types and value types. So you should constrain it to be implemented only by reference types: protocol PenguinDelegate: class { } Here, you are constraining the protocol to be implemented only by NSObjectProtocols, whose are reference types too, that's the reason why it works.
  • Feuermurmel
    Feuermurmel over 6 years
    Use protocol PenguinDelegate: class which does not depend on an Objective-C runtime but still solves the problem.
  • stuckj
    stuckj about 6 years
    I feel like the combination of this and the answer from @dasblinkenlight would fully answer this question. dasblinkenlight explained why the error message is showing and this explains how to achieve what you were likely trying to do as a developer.
  • Dieter Meemken
    Dieter Meemken over 4 years
    Can you explain a bit more?
  • Kuvonchbek Yakubov
    Kuvonchbek Yakubov about 2 years
    well, if closures are reference types, then why XCode shows an error 'weak' may only be applied to class and class-bound protocol types, not '() -> Void'?