How do you use Any
in Swift? What’s the difference between Any
and AnyObject
? And when and why should you use them? We’ll answer those questions in this tutorial.
Here’s what we’ll get into:
Any
is and why it’s quite usefulAnyObject
and Any
AnyObject
actually comes fromReady? Let’s go.
The Swift Programming Language provides two nonspecific types called Any
and AnyObject
. They’re nonspecific, because they really can be anything…
Let’s make a quick comparison. Consider that a constant called age
has value 42
and is of type Int
, like this:
let age:Int = 42
This type Int
is specific – we’re very clear here about the fact that age
is an integer number.
Now let’s check out a nonspecific type that uses Any
. The following code defines a values
array of type [Any]
:
let values:[Any] = ["Apple", 99, "Zaphod", -1]
What’s going on here? It doesn’t make sense at first glance – how can the values
array contain multiple different types, such as Int
and String
? That’s because the type of the values
array is nonspecific, it is [Any]
or array-of-Any
.
Making matters more mind-boggling, the individual items in values
still use their own specific types. Here, check this out:
[sandbox]
let values:[Any] = [“Apple”, 99, “Zaphod”, -1]
for value in values
{
switch value {
case is String:
print(“\(value) is a string!”)
case is Int:
print(“\(value) is an integer!”)
default:
print(“I don’t know this value!”)
}
}
[/sandbox]
In the above code, we’re using a for loop to iterate over the items in the values
array. For every item we’re executing a switch block. This switch block matches the type of value
with one of three cases, using the type checking is
keyword. In essence, we’re checking the type of each of the items in array
, and writing some text based on this type.
But why aren’t the types Any
? After all, the type of the values
array is [Any]
, so its items must have type Any
. Right? Well… yes and no. Here’s how:
values
is [Any]
– it’s nonspecificInt
and String
Why would you use Any
with this approach? Let’s find out…
If you’re unfamiliar with type casting, now’s a good time to read up on that. Type casting, Any
and AnyObject
are closely related, because you’ll almost always want to type cast a variable or constant with type Any
or AnyObject
to a specific value type (such as in the above example).
The previous example begs the question: why would you want to use Any
in the first place? (We’ll get to AnyObject
later.)
Before we answer that question, consider that Swift has a few programming features that make dealing with types more flexible. For example:
Consider that programming is often nothing more than taking some input, processing it, and providing that as output. You’re writing code that downloads tweets from an API, manipulates that data, and shows it to a user in a UI.
It then makes sense for the Swift programming language to provide tools and features that make dealing with data easier. Optionals, generics, protocols, type casting, Any
and AnyObject
– all of those “tools” help you process data more effectively. And they (usually) make your code clearer, more expressive, and easier to extend and maintain.
Any
and AnyObject
are particularly useful for values that have mixed, nonspecific types. Consider, for example the following dictionary:
let tweet:[String: Any] = [
"text": "Lorem ipsum dolor amet hoodie bicycle rights, 8-bit mixtape",
"likes": 42,
"retweets": ["@reinder42", "@aplusk", "@beeblebrox"]
]
See how this dictionary mixes values of different types? The first value is a string, the second an integer, and the third an array of strings.
What if you want to get to specific values in the tweet
dictionary? Here’s how you do that:
if let likes = tweet["likes"] {
print("This tweet has \(likes) likes!")
}
In the above code, the constant likes
has type Int
. The code uses optional binding to get the value by its key. If needed, you can also make the type cast explicit, like this:
if let likes = tweet["like"] as? Int { ...
Thanks to Any
we can combine these different tweet
values in one dictionary. We don’t need a custom class or type for the tweet, or use multiple values and dictionaries. And that’s super useful!
So far we’ve only looked at Any
. How is Any
different from its close cousin, AnyObject
?
Here’s what the official Swift documentation says:
Any
can represent an instance of any type at all, including function typesAnyObject
can represent an instance of any class typeSimple enough, right? You use Any
for anything and AnyObject
for classes. But… there’s more!
First, it’s important to understand the difference between value types and reference types. In short, a value type is copied when you pass it around in your code, and a reference type is not. Classes are reference types, and passing those around in your code merely creates a reference to the original object.
This has a clear consequence:
Second, it’s crucial to understand the role of Objective-C, Swift’s predecessor, in Any
vs. AnyObject
. In Objective-C you can use the polymorphic, untyped id
pointer to refer to any kind of object. Much like Any
and AnyObject
in Swift.
In Objective-C, all objects are reference types†. They’re accessed via pointers, and Objective-C doesn’t have the concept of a value type. This is an important point!
One of the great features of Swift is its interoperability with Objective-C. You can use Objective-C code in Swift projects and vice-versa. And you can use SDKs written in Objective-C in your Swift projects. Neat!
This interoperability relies on bridging Swift types and Objective-C types, among other things. The Objective-C type NSString
, for example, is bridged to the Swift type String
. As a result, you can (almost) seamlessly work with strings between the two languages.
In Swift 2 and earlier, importing to Swift from Objective-C had a problem. Before Swift 3, Objective-C’s id
type was imported as AnyObject
. Any value of type id
that’s passed from Objective-C to Swift had the AnyObject
type in Swift.
Remember that AnyObject
can only works with classes? This implies that AnyObject
is a reference type. Objective-C doesn’t have value types, and id
is a reference type, because it uses pointers. And that has a huge disadvantage: you can’t benefit from Swift’s value types when interoperating with Objective-C’s id
.
Simply said, importing Objective-C’s id
into Swift as AnyObject
means you can’t benefit from value types in Swift. And that’s where Any
comes in.
Since Swift 3, Objective-C’s id
is now imported as Any
in Swift. This change is more complex than what’s described here – because it affected bridged and unbridged value types, generics, and collections with AnyHashable
.
But where does that leave the difference between Any
and AnyObject
? You hopefully felt this coming! Here we go:
Any
is used for both value and reference types, such as structs, Int
, String
, etc. and can also be used for classes, functions and closuresAnyObject
is used for reference types, i.e. classesWhen should you choose one or the other? It’s a good practice to use AnyObject
when working with classes, and Any
when working with value types.
As we’ve seen in the previous examples, an array with integers and strings should use Any
because they’re value types. You can use Any
with classes, but it’s better to use AnyObject
.
In any case, don’t use Any
when you don’t want to provide a value’s type. It’s important to only use Any
and AnyObject
when you explicitly need the behavior and functionality they provide. Otherwise you’re just creating needless ambiguity in your code!
Note: Some blogs, articles and forums still mention Objective-C’s id
as being imported as AnyObject
in Swift. This is outdated information.
† With the exception of NSString
, NSNumber
, etc. because they define object equality as something different than pointer equality.
Swift’s Any
type proves useful when you want to work with nonspecific types, for example in arrays and dictionaries.
In this tutorial, we’ve discussed the difference between Any
and AnyObject
and why that’s relevant for iOS developers today. And we’ve seen how type casting can be used to effectively work with Any
.
Want to learn more? Check out these resources: