The concept of Any and AnyObject is a compromise in Swift, and confuses developers. In the "Swift Programming Language "from Apple, it is described as:

AnyObject can represent an instance of any class type.

Any can represent an instance of any type, even including the function type.

Check and see AnyObject first. Objective-C developers are well aware of type id. The compiler will not check the actual type of id, so it can express the concept of any type of object. Cocoa framework uses quite a lot of id in parameters and return values. Right now, Swift is primarily used in app development with Cocoa. Since we need to use APIs from Cocoa, AnyObject is a replacement for id, which means an instance of a class type.

But there is a conspicuous gap between id and AnyObject. Swift compiler will not check whether method exists or not when called on an AnyObject. And all return of AnyObject instance would be an Optional value. This makes sense in Objective-C, but a little troublesome in Swift. When using an object in Swift, we should always do a type casting before using an AnyObject.

Say that we have an API returning id in Objective-C, it now returns AnyObject? (because id could be a nil as well, so we need an Optional value here). Although we know calling a specified method on it SHOULD be no problem, we often cast it first instead:

func someMethod() -> AnyObject? {
    // ...

    // result is an `AnyObject?` value, which is equivalent to `id`.
    return result
}

let anyObject: AnyObject? = SomeClass.someMethod()
if let someInstance = anyObject as? SomeRealClass {
    // ...
    // Now, `someInstance` is `SomeRealClass` type. Use it directly.

    someInstance.funcOfSomeRealClass()
}

In fact, AnyObject is an empty protocol under the hood:

protocol AnyObject {
}

Distinct from other protocols, all class types conform to this protocol implicitly. This is why AnyObject can only represent class type. In Swift, Array and Dictionary are struct, instead of the class type in many other languages. The struct cannot be described into AnyObject, and this is why Any comes in. Besides of class, Any can be utilized in all other types too, including struct and enum.

To help understand it better, we can have a test on Any and AnyObject. Write this in an iOS's playground. Please take notice of the first line:

import UIKit

let swiftInt: Int = 1
let swiftString: String = "miao"

var array: [AnyObject] = []
array.append(swiftInt)
array.append(swiftString)

(You can also do the same thing in a Mac playground, in which the first line would be import AppKit instead.)

import UIKit means we like to take Cocoa in this file. We declared an Int and a String here, which are both struct and can only be represented by Any, but not by AnyObject. But surprisingly, the code gets compiled and can run correctly. However, if we print out the elements in array, we can find the types of these elements are changed to NSNumber and NSString, which are not original Swift types as declared. Yes, the secret is import UIKit. When importing UIKit, you imported Foundation as well, in which NSNumber and NSString are also included. These types and Swift corresponding types can be converted seamless. Here we declared AnyObject is the type that should be stored in the array. So Int and String are converted automatically to their "variant" in Cocoa.

If we remove the import UIKit line, we will have an error saying types are not correct as expected. And if we change the array from [AnyObject] to [Any], everything will work again, and the types are exactly the ones we declared:

let swiftInt: Int = 1
let swiftString: String = "miao"

var array: [Any] = []
array.append(swiftInt)
array.append(swiftString)
array

Using Swift original types without converting to Cocoa types benefits the performance. And it will be a wise choice to use Swift types as often as possible when writing your code in Swift.

It can hardly make you happy if you insist on using a lot of Any or AnyObject. As stated in the beginning of this article, it is just a compromise in Swift. If Any or AnyObject exists in your code here and there, it might mean a bad smell in your code. Try to avoid depending and using them in your code, you will be benefited from pointing out the real type of your objects at the time.