When should I use [Any]
?
Any
is an abstract type that all other types implicitly conform to. Because it could be anything – it must be guaranteed to do nothing.
For that very reason, typing a variable as Any
is nonsensical. If I define this:
let itCouldBeAnything : Any = "Actually it's a string"
It now can't do anything (without type casting):

You should always use the most descriptive type available when defining something, and because of Any
's abstract nature, there will always be a more descriptive type available – in this case, String
should've been used.
Now let’s think about arrays. As you say, Apple demonstrates that you can use an array of Any
to mix together different types.
var things = [Any]()
things.append(0)
things.append(0.0)
things.append(42)
things.append(3.14159)
things.append("hello")
things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman"))
Great. But what does this array actually represent? It’s just a collection of junk – the programming equivalent of the backseat of my car.
If we try and do something with one of the elements...

We can’t. It could be anything – so we can’t do anything with it. Sure, we can type cast the elements with a switch
or if
statement to handle the different possibilities – but all we’ll succeed in doing there is splitting our array back into distinct types. So what was the point in using [Any]
to begin with?
An array should always represent a collection of related data. There’s no point of an array if the elements share nothing in common. If the different types that the array can store have common functionality, then you should define a protocol with this common functionality:
protocol ACommonProtocol {
// define common functionality
}
We can then conform the types that the array can store to it:
extension Int : ACommonProtocol {}
extension Double : ACommonProtocol {}
extension String : ACommonProtocol {}
extension Movie : ACommonProtocol {}
Now our array can be of type [ACommonProtocol]
. This is a significant improvement from Any
, we’ve narrowed the concrete types that the elements could be down to 4 – and we can now use any common functionality that we define in the protocol on the elements without type-casting. Our elements also are now explicitly related, which actually gives the array some meaning (assuming the protocol represents a meaningful concept).
If the different types that the array can store don't have any common functionality, or cannot conform to protocols (such as tuples and functions), but are still related in some meaningful way – then another way of expressing this relationship is through using an enum
with associated values:
// obviously this enum (and possibly its cases) should have a far better names
enum IntDoubleStringOrMovie {
case int(Int)
case double(Double)
case string(String)
case movie(Movie)
}
Now our array can be of type [IntDoubleStringOrMovie]
– which has the added benefit of allowing us to use an exhaustive switch
in order to determine the element type:
for element in array {
switch element {
case let .int(int):
print(int)
case let .double(double):
print(double)
case let .string(string):
print(string)
case let .movie(movie):
print(movie)
}
}
So for this reason, you should never ever have to use [Any]
in Swift. If you ever find yourself in a situation of using [Any]
, you should be re-considering your data structure. Whether that involves splitting the array up into sub-arrays, conforming the elements to a common protocol (if they have common functionality), using an enum with associated values (if they have no common functionality) or using a different collection type altogether, is entirely up to you.
But what about interfacing with Objective-C?
Any
is sometimes necessary for bridging with Objective-C’s inferior type system – and therefore you may well find yourself using [Any]
with Objective-C APIs, which is acceptable (although with the bridging of Objective-C's lightweight generics to Swift, it should be uncommon).
The only thing I would say about this is once you’re back in your Swift logic, you should always convert an [Any]
back to a meaningful array type through type casting, or unpacking it into a more appropriate data structure. You shouldn’t sacrifice type safety in Swift just because Objective-C lacks in that regard.
But what about [AnyObject]
?
AnyObject
is pretty much as vague as Any
in pure Swift. The only thing it guarantees is that it’s a class. However, as of Swift 3, anything can be bridged to Objective-C by being boxed in a _SwiftValue
. For this reason, [AnyObject]
is just as (if not more) questionable as [Any]
.