What’s the difference between any and Any?
You’re more of a video kind of person? I’ve got you covered! Here’s a video with the same content than this article 🍿
If you use Swift, you might have come across code that used the keyword any
, either with a lowercase a
or with an uppercase A
.
And you might have been a bit confused by what the difference could be between the two of them.
As it turns out, they both serve a similar purpose, which is to represent types that will only be determined at runtime.
But they do it in two very different ways!
Let’s first focus on any
.
This is a typical use case for any
.
A protocol
is defined and then a class
that stores a property that conforms to this protocol
.
What’s important to notice here is that the compiler will not know at compile time what’s the actual type that’s stored in the property.
All that it will know is that the actual type is guaranteed to conform to the protocol NetworkServicing
and so that it’s okay to call the method .fetchUserName()
declared in the protocol.
However, since the actual type isn’t known at compile time, the compiler will need to generate extra code to account for the fact that it doesn’t know in advance the size of the actual instance or the address in memory of the method that we’re calling.
This extra code has a cost in performance, and that’s why Swift introduced the keyword any
to make that cost more obvious!
For now, using this keyword in this example is still optional, but in the next major version of Swift it should become mandatory.
Now let’s focus on Any
!
Any
represents a special type, that will accept any possible value.
So if you declare an array of Any
, you are then allowed to store inside of it a String
, an Int
, a struct
, and even a closure
!
However, this time the compiler will not know anything about the actual types being stored.
And so the only way to use the values will be through run time casting operations.
As you can imagine, this is less than ideal…
Actually, using Any
in your code is almost always guaranteed to be a bad practice that must be avoided, because it’s almost always possible to rewrite the code without using Any
.
However, you might have noticed that a good number of APIs from Apple actually use Any
, typically to store arbitrary data in a Dictionary
called userInfo
.
The reason behind this design choice is that these APIs have actually been written in Objective-C, and passing untyped values used to be quite common in that language, because it originally didn’t offer any kind of support for generics.
So that’s it, now you know the difference between any
and Any
!
That’s all for this article, here’s the code if you want to experiment with it:
// using `any`
protocol NetworkServicing {
func fetchUserName() async -> String
}
class ViewModel {
var userName: String?
private var service: any NetworkServicing
init(service: any NetworkServicing) {
self.service = service
}
func fetchData() {
Task {
userName = await service.fetchUserName()
}
}
}
// using `Any`
let canContainAnything: [Any] = [
"Hello",
42,
URL(string: "https://swift.org")!,
{ (arg: Int) in print(arg) },
]
if let string = canContainAnything.first as? String {
print("It contains the string \(string)")
}
var userInfo: [AnyHashable : Any]?