快速协议错误: “弱”不能应用于非类类型

协议和类约束协议有什么区别,我们应该在 Swift 中使用哪一个?

protocol A : class { ... }


protocol A { ... }

当协议没有定义为 : class时,试图添加 weak委托时,我们得到一个错误:

protocol A { ... }


weak var delegate: A

给出了错误:

“弱”不能应用于非类类型

或者

“弱”不能应用于非类绑定的“ A”; 请考虑添加具有类绑定的协议一致性

40544 次浏览

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.

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

protocol TopNewsTableDelegate : AnyObject {
func topNewsTableDidLoadedStories()
}

Or you can type like this

@objc protocol A { ... }

then you can make a weak delegate reference

protocol CustomProtocolName : NSObjectProtocol {
// ...
}

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'