Swift, as I am sure you are aware, is quite a strict, safe and strongly-typed language. However, because the language needs to maintain Objective-C compatibility it has some rather curious features, and the behaviour of
AnyObject is one of them!
AnyObject and relaxed type-safety
AnyObject is a protocol that can represent an instance of any class type. It also has a more general counterpart,
Any, which can represent any type at all (including structs and enums).
As you might expect, the following code will not compile:
It fails with the error ‘AnyObject’ does not have a member named ‘saySomething()’.
When provided with an instance of AnyObject you have to cast to the required type in order to execute its methods or access properties:
This all makes sense so far, but here is where things get a little curious. If you import Foundation and mark the class with the
@objc attribute, you no longer have to cast from
Cat in order to invoke the
This is pretty odd behaviour! And as you can imagine, it is also unsafe. It is quite possible to write code that compiles, yet fails at runtime:
Whilst this behaviour is understandable to people who came to Swift via Objective-C, I can guarantee it will confuse people who are new to iOS development!
AnyObject and sneaky type conversions
If you try to create a ‘mixed’ array containing strings and numbers you will encounter difficulties:
AnyObject can represent any class instance, but Swift’s string and numeric types are all structs (i.e. value types).
However, as soon as you import Foundation, the compiler errors go away:
How on earth does that work? From inspecting the contents of the array you can see that the compiler has automatically converted those literal values into a
Take care when using
AnyObject, you can do some pretty strange things with that types. In fact, take care when using Swift with Objective-C at all! ;-)
Regards, Colin E.