How can this [AnyObject] return as AnyObject?

2019-05-26 05:15发布

问题:

import Cocoa

class Brain{
    var internalProgram = [AnyObject]()
    var program:AnyObject{
        get{
            return (internalProgram as AnyObject)
        }
    }
}

var savedProgram: AnyObject?
let brain = Brain()
func save(){
    savedProgram = brain.program
}

How can this internalProgram:[AnyObject] return as AnyObject without Xcode giving a warning or an error? I know that program's type is set as AnyObject already but I mean how can this work and wasn't it supposed to be [AnyObject]? So why no any warning or error issue?

回答1:

So why no any warning or error issue?

There would have been if you hadn't of said as AnyObject:

class Brain {
    var internalProgram = [AnyObject]()
    var program: AnyObject {
        get {
            // compiler error:
            // Return expression of type '[AnyObject]' does not conform to 'AnyObject'
            return internalProgram
        }
    }
}

The compiler is telling us that [AnyObject] doesn't conform to AnyObject – which is perfectly true. A Swift Array is a struct, not a class, therefore cannot directly be typed as an AnyObject.

However, you then say as AnyObject. By doing so, you're bridging the Swift Array to NSArray (when Foundation is imported) – which is a class. Therefore it can be typed as an AnyObject. You can see the full list of Foundation types which can be bridged to here.

Furthermore it's worth noting that in Swift 3, everything can be bridged to AnyObject due to the introduction of the opaque _SwiftValue type, which can wrap an arbitrary Swift value in an Obj-C compatible box (including Array when Foundation isn't imported).

Because anything can now be an AnyObject, it's pretty much as weak a type as Any. On top of this, it also lets you call any known @objc method on it, completely disregarding type safety and is almost guaranteed to cause you problems with _SwiftValue boxing. For those reasons, you should avoid using AnyObject wherever you can. There is nearly always a stronger type available for you to use.



回答2:

According to Apple's documentation, AnyObject can be used when:

  • you need the flexibility of an untyped object
  • you use bridged Objective-C methods and properties that return an untyped result

It basically can be used as a type for any instance of any class, no matter what that is. Therefore, [AnyObject], converted to NSArray, is still an object, which AnyObject can hold, because its type does not matter, since AnyObject can hold any class type, such as NSArray.


Explanation:

[AnyObject] is an array of Objects, so it's a value type. However, when Foundation is imported, the array can automatically be converted to the Objective-C bridged type NSArray which is AnyObject.