Swift protocol error: 'weak' cannot be applied to non-class type

SwiftProtocols

Swift Problem Overview


What's the difference between Protocols and class-bound Protocols, and which one we should use in Swift?

protocol A : class { ... }

protocol A { ... }

We get an error when attempting to add a weak delegate when the Protocol is not defined as : class:

protocol A { ... }

weak var delegate: A

Gives the error:

> 'weak' cannot be applied to non-class type

or

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

Swift Solutions


Solution 1 - Swift

Swift >= 4:

protocol A : AnyObject { ... {

Swift < 4:

protocol A : class { ... }

defines a "class-only protocol": Only class types (and not structures or enumerations) can adopt this protocol.

Weak references are only defined for reference types. Classes are reference types, structures and enumerations are value types. (Closures are reference types as well, but closures cannot adopt a protocol, so they are irrelevant in this context.)

Therefore, if the object conforming to the protocol needs to be stored in a weak property then the protocol must be a class-only protocol.

Here is another example which requires a class-only protocol:

protocol A { 
    var name : String { get set }
}

func foo(a : A) {
    a.name = "bar" // error: cannot assign to property: 'a' is a 'let' constant
}

This does not compile because for instances of structures and enumerations, a.name = "bar" is a mutation of a. If you define the protocol as

protocol A : class { 
    var name : String { get set }
}

then the compiler knows that a is an instance of a class type to that a is a reference to the object storage, and a.name = "bar" modifies the referenced object, but not a.

So generally, you would define a class-only protocol if you need the types adopting the protocol to be reference types and not value types.

Solution 2 - Swift

If you are using Swift 4 or later, use AnyObject:

protocol A : AnyObject { ... }

Using class as before gives the warning and fix-it:

> Using 'class' keyword to define a class-constrained protocol is deprecated; use 'AnyObject' instead
> > Replace 'class' with 'AnyObject'

Solution 3 - Swift

You can make the protocol derive from any class type like NSObject or AnyObject:

protocol TopNewsTableDelegate : AnyObject {
    func topNewsTableDidLoadedStories()
}

Solution 4 - Swift

protocol CustomProtocolName : NSObjectProtocol {
  // ...
}

Solution 5 - Swift

Or you can type like this

@objc protocol A { ... }

then you can make a weak delegate reference

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionboogView Question on Stackoverflow
Solution 1 - SwiftMartin RView Answer on Stackoverflow
Solution 2 - SwiftRogerView Answer on Stackoverflow
Solution 3 - SwiftSachindra PandeyView Answer on Stackoverflow
Solution 4 - SwiftRavindra Kumar SonkarView Answer on Stackoverflow
Solution 5 - SwiftMedhat MebedView Answer on Stackoverflow