I've found the answer to this one myself, not that I understand why however.
Given a pure Swift object that conforms to a Swift protocol:
protocol P {
var name: String { get }
}
class PImpl: P {
let name: String
init(name: String) {
self.name = name
}
}
Run the following testcases:
func unbridgableArrayOfPs() -> [P] {
let pees = [PImpl(name: "A"), PImpl(name: "B"), PImpl(name: "C")]
return pees
}
func arrayOfPs() -> [P] {
return [PImpl(name: "A"), PImpl(name: "B"), PImpl(name: "C")]
}
func testUnbridgableArrayOfPs() {
let p = unbridgableArrayOfPs() // Fails with fatal error: array cannot be bridged from Objective-C
let result = p.map{$0.name}.joinWithSeparator("")
XCTAssertEqual(result, "ABC")
}
func testArrayOfPs() {
let p = arrayOfPs() // We get our P's
let result = p.map{$0.name}.joinWithSeparator("")
XCTAssertEqual(result, "ABC")
}
It would seem that returning the array directly without creating a temporary variable allows this to succeed, whereas the unbridgableArrayOfPs() function fails.
Any thoughts?
The other options are
1. Annotate the protocol with @objc
2. Change the return type of the array to the concrete implementation's type i.e PImpl
1 Isn't going to work I believe if there are things like Swift enums in the mix
2 From a design perspective, it's nice to keep things implementation agnostic where possible.