Because [[SomeObject]] is not the same type as [[SomeProtocol]] - see @TeeJay's comment above. The how is solved like this:
protocol SomeProtocol {
}
struct SomeObject: SomeProtocol {
}
struct Test {
var arr: [[SomeProtocol]]
mutating func testFunction(objs:[[SomeObject]]) {
self.arr = []
for a in objs {
var innerArray = [SomeProtocol]()
for e in a {
innerArray.append(e)
}
self.arr.append(innerArray)
}
}
}
Or, as @MartinR pointed out, you could use map.
If I try to short-circuit the inner loop with
self.arr = []
for a in objs {
self.arr.append(a)
}
I get the error "Cannot convert value of type 'Array<SomeObject>' to expected argument type [SomeProtocol]", which, on one level, is entirely correct - they are not the same - it's the elements, not the collection, which conform to the protocol. Array assignment doesn't dig down to the final element types for protocol conformance, unless you do it explicitly.
This is not entirely surprising - you wouldn't expect the following to work:
struct SomeOther1 {
var a : SomeProtocol
}
struct SomeOther2 {
var a : SomeObject
}
let x = SomeOther2(a: SomeObject())
let y: SomeOther1 = x // ERROR
whilst this should (and does) work:
let x = SomeOther2(a: SomeObject())
let y = SomeOther1(a: x.a)
Since Arrays are Structs that use generics, we can try the same using generics:
struct SomeOther<T> {
var a: T
}
let z = SomeOther<SomeObject>(a: SomeObject()) // OK, of course
let w = SomeOther<SomeProtocol>(a: SomeObject()) // OK, as expected
let v: SomeOther<SomeProtocol> = z // Doesn't work - types are not the same.
SomeObjectisSomeProtocolbut[[SomeObject]]is not[[SomeProtocol]]. Probably you need to cast each element. This was the same in .net 3.5, and it has been "resolved" in .net 4.0.