Reputation: 4270
In Swift I declared a function that differs from Array.count
only in that if array == nil
the function returns 0
. This is related to my UITableViewDataSource
, but that's not important here. The problem is, if I declare the function as:
class func countOfItemsInArray(array: [AnyObject]?) -> Int
and then try to pass it an array of structs, it declares that the structs in the array do not conform to AnyObject
. I understand why that is (I think), but is there a way to make this work with classes and structs, or should I just give in to copy and paste?
Upvotes: 1
Views: 150
Reputation: 40955
Generics are probably better suited to this problem than relying on covariance of [AnyObject]
. A version of countElements
that worked on an optional array and returned 0 in case of nil
could go like this:
func countElements<T>(array: [T]?) -> Int {
return array?.count ?? 0
}
When you call countElements
with any kind of array, the placeholder T
is replaced with the type of the element contained in the array.
Note, this version overloads the existing countElements
with a version that takes an optional. If you call it with a non-optional or any other kind of collection, the Swift version would be called, if you pass in an optional array, this one will be called. It’s debatable whether this is a good practice (I think it’s fine) or a bad one (some may disapprove :).
A version that works on any collection type would be:
func countElements<C: CollectionType>(col: C?) -> C.Index.Distance {
return col.map { countElements($0) } ?? 0
}
Upvotes: 3
Reputation: 3258
If you use Any
instead of AnyObject
you can pass any type, so also structs:
class func countOfItemsInArray(array: [Any]?) -> Int
This is kind of weird.
I used this function:
func countOfItemsInArray(array: [Any]?) -> Int {
return array != nil ? array!.count : 0
}
Declared two of your Assignment
structs and put them in an array:
let structOne = Assignment(name: "1", dueDate: NSDate(), subject: "1")
let structTwo = Assignment(name: "2", dueDate: NSDate(), subject: "2")
let myArray: [Assignment] = [structOne, structTwo]
But here's the interesting part.
When calling println(countOfItemsInArray(myArray))
it gives the error:
<stdin>:27:33: error: 'Assignment' is not identical to 'Any'
println(countOfItemsInArray(myArray))
^
<stdin>:17:26: note: in initialization of parameter 'array'
func countOfItemsInArray(array: [Any]?) -> Int {
^
So I tested if myArray
is of type [Any]
:
println(myArray is [Any])
to which swift says:
<stdin>:25:17: error: 'Any' is not a subtype of 'Assignment'
println(myArray is [Any])
^
But when I change the type annotation of myArray
to [Any]
it works:
let myArray: [Any] = [structOne, structTwo]
And when simply handing the literal to the function it works, too:
countOfItemsInArray([structOne, structTwo])
The whole code example can be seen here.
Upvotes: 0