2
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?

rmaddy
  • 314,917
  • 42
  • 532
  • 579
Qasa iNto
  • 31
  • 3

2 Answers2

5

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.

Community
  • 1
  • 1
Hamish
  • 78,605
  • 19
  • 187
  • 280
  • Thanx!!! Your explanation and tips are so great for me(a new guy learning Swift)! Have a nice day – Qasa iNto Mar 23 '17 at 03:20
  • Happy to help, and welcome to Stack Overflow @QasaiNto :) If you feel your question has been answered, you can [accept an answer](http://stackoverflow.com/help/someone-answers). – Hamish Mar 23 '17 at 10:23
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.

Community
  • 1
  • 1
Mr. Xcoder
  • 4,719
  • 5
  • 26
  • 44
  • Suggestions are welcome and if you need clarifications about the answer, please let me know! – Mr. Xcoder Mar 22 '17 at 14:23
  • 1
    `[AnyObject]` is a value type therefore it *is not* an `AnyObject`, which represents only class types. However, when `Foundation` is imported, a Swift array can be bridged to `NSArray` which is an `AnyObject`. That's the important part here. – Sulthan Mar 22 '17 at 14:38
  • Ok, I will edit the answer with the information You've provided @Sulthan. Good to know! – Mr. Xcoder Mar 22 '17 at 16:33