Reputation: 41480
In Swift Programming Language, it says "An array stores multiple values of the same type in an ordered list." But I have found that you can store multiple types of values in the array. Is the description incorrect?
e.g.
var test = ["a", "b", true, "hi", 1]
Upvotes: 17
Views: 35382
Reputation: 1086
Worked and Tested on Swift 5
You can explicitly state the data type to any. The Any type represents values of any type.
Type Casting
var test = ["a", "b", true, "hi", 1] as [Any]
Type explicit
var test: [Any] = ["a", "b", true, "hi", 1]
Upvotes: 0
Reputation: 634
Instead you can also use a struct in your class:
struct Something {
let a: String
let b: String?
let boolValue: Bool
let value: Int
init(a: String, b: String? = nil, boolValue: Bool, value: Int) {
self.a = a
self.b = b
self.boolValue = boolValue
self.value = value
}
}
Upvotes: 2
Reputation: 601
In Swift 3 you can use :
var testArray = ["a",true,3,"b"] as [Any]
Upvotes: 2
Reputation: 46598
From REPL
xcrun swift
1> import Foundation
2> var test = ["a", "b", true, "hi", 1]
test: __NSArrayI = @"5 objects" {
[0] = "a"
[1] = "b"
[2] =
[3] = "hi"
[4] = (long)1
}
3>
you can see test
is NSArray
, which is kind of AnyObject[]
or NSObject[]
What happening is that Foundation
provides the ability to convert number and boolean into NSNumber
. Compiler will perform the conversion whenever required to make code compile.
So they now have common type of NSObject
and therefore inferred as NSArray
Your code doesn't compile in REPL without import Foundation
.
var test = ["a", "b", true, "hi", 1]
<REPL>:1:12: error: cannot convert the expression's type 'Array' to type 'ArrayLiteralConvertible'
var test:Array = ["a", "b", true, "hi", 1]
<REPL>:4:18: error: cannot convert the expression's type 'Array' to type 'ExtendedGraphemeClusterLiteralConvertible'
but you can do this
var test : Any[] = ["a", "b", true, "hi", 1]
Because they have a common type, which is Any
.
Note: AnyObject[]
won't work without import Foundation
.
var test:AnyObject[] = ["a", "b", true, "hi", 1]
<REPL>:2:24: error: type 'Bool' does not conform to protocol 'AnyObject'
Upvotes: 22
Reputation: 369
To initialize an Array with arbitrary types, just use
var arbitraryArray = [Any]()
.
Upvotes: 9
Reputation: 36389
AnyObject
is a type and you can create an array that holds those, which (as the class name implies) means it can hold any type of object. NSArrays aren't type-bound and when you create an array with mixed types, it will generate an NSArray
instead of an Array
. I wouldn't rely on this, however, since it could change in the future (AnyObject[] is automatically bridged with NSArray).
You can try this in a playground (note: dynamicType
returns "(Metatype)" and I wasn't sure how to pull out the actually type so I relied on the compiler error):
var x = [ 1, 2, "a" ]
x.dynamicType.description() // -> __NSArrayI
var y = [ 1, 2 ]
y.dynamicType.description() // -> Error: Array<Int>.Type does not have a member named 'description'.
var z: AnyObject[] = [ 1, 2, "a" ]
z.dynamicType.description() // -> Error: Array<AnyObject>.Type does not have a member named 'description'.
Upvotes: 2
Reputation: 70145
The description is correct, an Array stores multiple values of the same type. The key is that one value has multiple types. That is, for example, a String
has types of String
and Any
; an instance of a class Ellipse : Shape
has types of Ellipse
, Shape
, AnyObject
and Any
.
14> class Foo {}
15> class Bar : Foo {}
16> var ar1 : Array<Any> = [1, "abc", Foo(), Bar()]
ar1: Any[] = size=4 {
[0] = <read memory from 0x7fa68a4e67b0 failed (0 of 8 bytes read)>
[1] = { ... }
[2] = {}
[3] = { ... }
}
17> ar1[0]
$R5: Int = <read memory from 0x7fa68a51e3c0 failed (0 of 8 bytes read)>
18> ar1[1]
$R6: String = { ... }
19> ar1[2]
$R7: Foo = {}
20> ar1[3]
$R8: Bar = {
lldb_expr_14.Foo = {}
}
21> ar1[0] as Int
$R9: Int = 1
Upvotes: 1