Any or AnyObject in Swift

Any and AnyObject. Not the same.

Sometimes you want to work with types that are not necessarily the standard set of literals given to us by Swift.

Image for post
Image for post
Photo by Jadon Kelly on Unsplash

Difficulty: Beginner | Easy | Normal | Challenging

Prerequisites:

  • Be able to produce a “Hello, World!” iOS application (guide HERE)
  • Protocols in Swift (guide HERE) would be useful, as would knowledge of Equality (guide HERE)
  • String Interpolation is used later in this article (guide HERE)

Terminology

Any: An instance of any type, including function types

AnyObject: an instance of any class type

Concrete: A type that can be instantiated

Instance: An example or single occurrence of something

Method: a group of statements that together can perform a function

NSNumber: Objective-C type for storing numbers

NSString: Objective-C type for storing Strings

Properties: fields of classes

Protocol: A blueprint on methods, properties and requirements to suit a piece of functionality

Reference: A pointer to a variable or object

String: A collection of Characters

Struct: An object defined in Swift, using pass by value semantics

Type: A representation of the type of data that can be processed, for example Integer or String

Type Casting: A way to either check the type of an instance, or treat the instance as a different superclass or subclass

Value Type: Where a value is stored as the actual value of the item

AnyObject

AnyObject gives flexibility. That is, we can use AnyObject as a concrete type. More than that, AnyObject is (and we can quote here)

“The protocol to which all classes implicitly conform”

https://developer.apple.com/documentation/swift/anyobject

This means we can make Classes conform to the AnyObject Protocol — because they are Objects and Class types.

This means that we have no real problem making an Array of AnyObject and place within the Array a series of Classes.

class Person {
var name: String
init (name: String) {
self.name = name
}
}
class Animal {
var name: String
init (name: String) {
self.name = name
}
}

We then set up Instances of these types

let jamie = Person(name: "Jamie")
let dave = Animal(name: "Dave")

which can then be placed in an Array:

let anyObjects: [AnyObject] = [jamie, dave]

with the advantage of doing so that we can place both a Person and an Animal into the same Array(although a better choice would usually be to make both conform to a Protocol, and create an Array of that Protocol)

Any

Any allows us to store, well different (that is, Any) types

let anyThings: [Any] = [1, 2, "3", false]

The issue is that when you cast to Any, you cannot access the Methods and Properties that can be used on the specific type.

Telling the difference between Any and AnyObject

Any arrays can be traversed, and is used to identify the type

for obj in anyThinks {
if obj is String {
print ("\(obj) is a String")
}
if obj is Int {
print ("\(obj) is an Integer")
}
if obj is Bool {
print ("\(obj) is a Boolean")
}
}

This is because Any pretty much means any and the elements held in the array keep their own type.

The unusual case

But what if we Cast value types to AnyObject?

let anyObjectArray: [AnyObject] = [1 as AnyObject]

The Integer is still a value type (it is actually a Struct) yet we can cast it an even (wait for it)

let anyObjectArray: [AnyObject] = [1 as AnyObject]
print (anyObjectArray) // 1

So…what type is this? We can use as again.

for obj in anyObjectArray {
if obj is Int {
print ("\(obj) is an Integer")
}
}

and…it’s an Integer? How are we storing a value type as AnyObject? Are we seeing something that’s impossible?

Just because something is one type, does not mean that it isn’t another type

We can simply find out the type of our object

print (type(of: obj))

which is placed in our traversal of the array

for obj in anyObjectArray {
if obj is Int {
print ("\(obj) is an Integer")
print (type(of: obj))
}
}

we find out the truth:

“_NSCFNumber”

As part of the interoperability of Swift, the compiler has switched the type for use seamlessly to the Objective-C equivalent!

This bridged type which is NSNumber and is actually a Class, which means that it can happily be stored in our array of AnyObject (which is because NSNumber is of course a Class)

You can experiment and see the same is true for String and NSString in the same situation

Apple’s recommendation

Through the Swift documentation, Any and AnyObject should only be used when you need the capabilities provided by those types. Usually it is better to specifically use a declared type for your code.

Conclusion:

As another tool in our arsenal, we can use Any and AnyObject to store data Types. However, we need to be aware that there are limitations, and Apple themselves recommend that we use specific types for your code — unless there isn’t another option.

As ever, it is in the hands of the programmer to make the correct choice for their particular code and their particular problem.

The Twitter contact:

Any questions? You can get in touch with me here

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store