从AnyObject扩展的协议和仅类协议之间有什么区别?

use*_*008 49 protocols class swift

这两个宣言

protocol SomeProtocol : AnyObject {
}
Run Code Online (Sandbox Code Playgroud)

和这个宣言

protocol SomeProtocol : class {
}
Run Code Online (Sandbox Code Playgroud)

似乎使它只有类可以符合这个协议(即协议的实例是对象的引用),并没有其他效果.

它们之间有什么区别吗?一个人应该优先于另一个吗?如果没有,为什么有两种方法可以做同样的事情?

我正在使用最新发布的Xcode 6.3.1.

kga*_*dis 15

官方Swift开发人员(Slava_Pestov)在Swift论坛上回答了此问题。这是摘要:

  • 您应该使用AnyObjectprotocol SomeProtocol: AnyObject)。

  • AnyObjectclass等价。没有区别。

  • class 最终将被弃用。


Cod*_*aFi 12

关于答案https://forums.swift.org/t/class-only-protocols-class-vs-anyobject/11507/4,不推荐这个答案.这些话现在都是一样的.

弃用

更新:在咨询权力之后,这两个定义应该是等价的,并AnyObject在完成时用作替身class.在未来,后者将消除前者,但目前,它们确实存在一些细微差别.

不同之处在于@objc声明的语义.因为AnyObject,期望符合类可能是也可能不是正确的Objective-C对象,但语言无论如何都将它们视为对待(因为有时你会失去静态调度).从中可以看出,你可以治疗AnyObject等人.协议约束作为一种请求@objc成员函数的方法,如AnyObjectSTL 中的文档中的示例所示:

import Foundation
class C {
     @objc func getCValue() -> Int { return 42 }
}

// If x has a method @objc getValue()->Int, call it and
// return the result.  Otherwise, return nil.
func getCValue1(x: AnyObject) -> Int? {
    if let f: ()->Int = x.getCValue { // <===
        return f()
    }
    return nil
}
 // A more idiomatic implementation using "optional chaining"
func getCValue2(x: AnyObject) -> Int? {
    return x.getCValue?() // <===
}
 // An implementation that assumes the required method is present
func getCValue3(x: AnyObject) -> Int { // <===
    return x.getCValue() // x.getCValue is implicitly unwrapped. // <===
}
Run Code Online (Sandbox Code Playgroud)

如果您将其更改为class-deriving协议,则相同的示例会立即失效:

import Foundation

protocol SomeClass : class {}

class C : SomeClass {
    @objc func getCValue() -> Int { return 42 }
}

// If x has a method @objc getValue()->Int, call it and
// return the result.  Otherwise, return nil.
func getCValue1(x: SomeClass) -> Int? {
    if let f: ()->Int = x.getCValue { // <=== SomeClass has no member 'getCValue'
        return f()
    }
    return nil
}

// A more idiomatic implementation using "optional chaining"
func getCValue2(x: SomeClass) -> Int? {
    return x.getCValue?() // <=== SomeClass has no member 'getCValue'
}

// An implementation that assumes the required method is present
func getCValue3(x: SomeClass) -> Int { // <===
    return x.getCValue() // <=== SomeClass has no member 'getCValue'
}
Run Code Online (Sandbox Code Playgroud)

因此,当您只关心引用语义而不关心动态成员查找或Objective-C桥接时,似乎应该使用class更保守的版本AnyObject.

  • 我仍然在努力(这可能是我的错)找到一个具体的例子,其中`protocol Protocol:AnyObject {}`不能与`protocol Protocol:class {}`互换. (2认同)
  • 那么你现在的结论是什么?如果我对 Joe Groff 的理解正确,那么 `protocol SomeProtocol : AnyObject { }` 和 `protocol SomeProtocol : class { }` 之间没有*区别,但您声称 *"... 现在,它们确实存在一些细微差别”*。请原谅我的固执,但我仍然看不到您的代码如何证明这种差异。 (2认同)

Jeb*_*ses 7

从 2021 年开始,Xcode 12.5、Big Sur 操作系统:

classApple 不推荐使用。

AnyObject代替使用。

快乐编码。

已弃用


Yuc*_*ong 5

斯威夫特编程语言指南的协议,下的类只有协议部分。它只提到了AnyObject,但没有提到class

通过将AnyObject协议添加到协议的继承列表中,可以将协议采用限制为类类型(而不是结构或枚举)。

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // class-only protocol definition goes here
}
Run Code Online (Sandbox Code Playgroud)

因此,我建议将AnyObjectover class用于新代码或新项目。除此之外,我看不出它们之间有任何明显的区别。


Dun*_*n C 1

我之前说错了。@MartinR 确实应该回答这个问题,因为他是纠正我并提供正确信息的人。

真正区别在于带有类限定符的协议只能应用于类,而不能应用于结构或枚举。

马丁,你为什么不回答,OP 可以接受你的回答?

  • 但似乎从 AnyObject 继承的协议也只能应用于类,而不能应用于结构或枚举。`协议 SomeProtocol : AnyObject { } ; struct Foo : SomeProtocol { }` 给出编译器错误“非类类型 'Foo' 无法符合类协议 'SomeProtocol'`。(我感觉实际上没有区别,但我无法证明。) (6认同)