What's the difference between a protocol extended from AnyObject and a class-only protocol?

前端 未结 6 1931
一整个雨季
一整个雨季 2020-12-02 14:30

Both this declaration

protocol SomeProtocol : AnyObject {
}

and this declaration

protocol SomeProtocol : class {
}
<         


        
6条回答
  •  情歌与酒
    2020-12-02 14:51

    Regarding the answer https://forums.swift.org/t/class-only-protocols-class-vs-anyobject/11507/4, this answer is deprecated. These words are the same now.

    DEPRECATED

    Update: After consulting with the powers that be, the two definitions are supposed to be equivalent, with AnyObject being used as a stand-in while class was being finished. In the future the latter will obviate the former but, for now, they do present a few minor differences.

    The difference lies in the semantics of @objc declarations. With AnyObject, the expectation is that conforming classes may or may not be proper Objective-C objects, but the language treats them as such anyway (in that you lose static dispatch sometimes). The takeaway from this is that you can treat an AnyObject et al. protocol constraint as a way to ask for @objc member functions as shown in the example in documentation for AnyObject in the STL:

    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. // <===
    }
    

    The same example falls over immediately if you change that to a class-deriving protocol:

    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'
    }
    

    So it seems class is a more conservative version of AnyObject that should be used when you only care about reference semantics and not about dynamic member lookups or Objective-C bridging.

提交回复
热议问题