81

Both this declaration

protocol SomeProtocol : AnyObject {
}

and this declaration

protocol SomeProtocol : class {
}

seem to make it so that only classes can conform to this protocol (i.e. that the instances of the protocol are references to objects), and have no other effects.

Is there any difference between them? Should one be preferred over the other? If not, why is there two ways to do the same thing?

I am using the latest released Xcode 6.3.1.

user102008
  • 30,736
  • 10
  • 83
  • 104

7 Answers7

60

This was answered by an official Swift developer (Slava_Pestov) on the Swift forums. Here is the summary:

  • You should use AnyObject (protocol SomeProtocol: AnyObject).

  • AnyObject and class are equivalent. There is no difference.

  • class will eventually be deprecated.

kgaidis
  • 14,259
  • 4
  • 79
  • 93
23

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.

Vyacheslav
  • 26,359
  • 19
  • 112
  • 194
CodaFi
  • 43,043
  • 8
  • 107
  • 153
  • 1
    First of all, thanks for your answer. (Perhaps one shouldn't use "AnyClass" because that is already a type alias for AnyObject.Type.) The difference between `AnyObject` and, let's say, `MyClassProtocol`, defined as `protocol MyClassProtocol : class {}` is now clear. What I am still missing is the difference between `protocol MyObjectProtocol : AnyObject {}` and `protocol MyClassProtocol : class {}`. – Martin R Oct 01 '15 at 20:42
  • 2
    I am still struggling (and that may be my fault) to find a concrete example where `protocol Protocol : AnyObject {}` is not interchangeable with `protocol Protocol : class {}`. – Martin R Oct 01 '15 at 20:55
  • 2
    So what is your conclusion now? If I understand Joe Groff correctly, there is *no* difference between `protocol SomeProtocol : AnyObject { }` and `protocol SomeProtocol : class { }` at all, but you are claiming that *"... for now, they do present a few minor differences"*. Please pardon my obstinateness, but I still cannot see how your code demonstrates that difference. – Martin R Oct 02 '15 at 15:19
  • @MartinR Hi, I happened to stumble upon this post after having tried to play around this myself. I understand the use of `: class`, but I am also curious to know about the difference mentioned above in your comments. Have you since found any concrete differences between the aforementioned (i.e, _„... for now, they do present a few minor differences"_) successfully? Excuse my obstinateness, likewise. Thanks. – Unheilig Oct 24 '15 at 07:27
  • @Unheilig: CodaFi said that there are minor differences, so I assume that your question is addressed to him, not to me? – I do not know more that what I said in the comments. – Martin R Oct 24 '15 at 08:07
  • @MartinR It appeared to me that they were unanswered, so I thought of asking you, in hopes that you might have since found out somehow. :-) Thanks for response, nonetheless. CodaFi, would you mind sharing with us your discovery regarding the subtle differences between the two? – Unheilig Oct 24 '15 at 08:56
  • 1
    @Unheilig All that I have is up there, and will soon be obsolete if Joe Groff is to be believed. For now, `class` is more conservative - I suspect because of its incomplete implementation. It will not be in future. – CodaFi Nov 04 '15 at 19:53
11

In the Swift programming language guide for protocols, under the Class-Only Protocols section. It only mentioned AnyObject, but not class.

You can limit protocol adoption to class types (and not structures or enumerations) by adding the AnyObject protocol to a protocol’s inheritance list.

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol {
    // class-only protocol definition goes here
}

For that reason, I will suggest using AnyObject over class for new code or new project. Other than that, I don't see any obvious difference between them.

Yuchen
  • 30,852
  • 26
  • 164
  • 234
6

From 2021, Xcode 12.5, Big Sur OS:

Usage of class is deprecated by apple.

Use AnyObject instead.

Happy Coding.

Deprecated

Jeba Moses
  • 809
  • 8
  • 25
4

AnyObject is a protocol to which all classes implicitly conform (source). So I would say there is no difference: you can use either to require class constraint.

József Vesza
  • 4,775
  • 3
  • 27
  • 42
3

If you open the help (alt-click) in Xcode 9 for class in a line such as protocol P: class {}, you will get typealias AnyObject.

Thus, the code compiled (in Swift 4) will be the same whether you constrain the protocol to class or AnyObject.

That said, there is also the question of style and future options — a future Swift version might want to treat class and AnyObject differently in some subtle way, even if that is not the case right now.

(Edit: This has finally happened in Swift 5.4/Xcode 12.5.)

idrougge
  • 633
  • 5
  • 12
  • Worth noting that since XCode 12.5 if you're extending classes that are annotated with @objc then you may see `Redundant constraint 'Self' : 'AnyObject'` and need to either remove the AnyObject reference or replace it with NSObjectProtocol – NikoRoberts Jun 05 '21 at 11:22
1

I misspoke before. @MartinR should really answer this, since he's the one who corrected me and provided the correct information.

The real difference is that a protocol with the class qualifier can only be applied to a class, not a struct or enum.

Martin, why don't you answer and the OP can accept your answer?

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • 6
    But it seems that a protocol inheriting from AnyObject can also be applied to a class only, not a struct or enum. `protocol SomeProtocol : AnyObject { } ; struct Foo : SomeProtocol { }` gives the compiler error `non-class type 'Foo' cannot conform to class protocol 'SomeProtocol'`. (I have the feeling that there is actually no difference, but I cannot prove it.) – Martin R May 12 '15 at 05:17
  • 1
    I guess that makes sense, since AnyObject is also only class objects. You'd have to use `protocol SomeProtocol: Any` if you want a struct or enum to conform to that protocol. Makes me wonder what the point of the class qualifier is. I (wrongly) assumed it restricted the protocol to the class, not instances of the class, but the docs clearly state otherwise. – Duncan C May 12 '15 at 10:27
  • _The real difference is that a protocol with the class qualifier can only be applied to a class, not a struct or enum_ ? No, that's not a difference, exactly the same holds true for `AnyObject` as only objects can conform to that, neither enums nor structs can be used where `AnyObject` is expected. The real difference is that `AnyObject` can be a Swift class or an Obj-C object (or something else, that would conform to that protocol), but only Swift classes can conform to `class`. – Mecki Jun 02 '17 at 10:16