Reputation: 1640
If you look at this function:
typealias JSONDictionary = [String: AnyObject]
private func allIdentifiersInJson(json: [JSONDictionary], key: String?) -> [AnyObject] {
if let identifier = key {
let identifiers = json.map{ $0[identifier] } //this returns [AnyObject?]
return identifiers as? [AnyObject] ?? [] // this crashes the compiler in Release with Optimizations
}
return []
}
How would you cast an [AnyObject?] to an [AnyObject]
In Release config with optimizations enabled, I get this error during compilation:
Bitcast requires both operands to be pointer or neither
%548 = bitcast i64 %547 to %objc_object*, !dbg !10033
LLVM ERROR: Broken function found, compilation aborted!
Upvotes: 1
Views: 135
Reputation: 11555
One way would be to use flatMap:
let l: [AnyObject?] = [1, 2, 3, 4, 5, 6, nil, 7]
let m = l.flatMap { $0 } // Returns [1, 2, 3, 4, 5, 6, 7] as [AnyObject]
(tested only in Swift 2)
Upvotes: 3
Reputation: 37043
You probably want to be using something like this instead:
private func allIdentifiersInJson(json: [JSONDictionary], key: String?) -> [AnyObject] {
if let key = key {
return json.map { $0[key] }.filter { $0 != nil } as! [AnyObject]
}
return []
}
Because we are using filter
to remove all instances of nil
, we can use the forced cast to [AnyObject]
without fear of a crash.
Or, as pointed out by @MirekE in their answer, flatMap
is even more succinct:
return json.flatMap { $0[key] }
Which only returns non-nil results, and removes the need for any casting.
Upvotes: 1
Reputation: 2782
Expanding on what is in my comment above, if you use the following, your app will crash if identifier
is not a key in the dictionary:
let identifiers = json.map { $0[ identifier ]! }
So, what you might want to do is filter that first, then perform the mapping knowing that you can force unwrap because you've already checked for that key:
let identifiers = json.filter({ $0[ identifier ] != nil }).map { $0[ identifier ]! }
But if it were me, I'd want to get rid of the force unwrap altogether for total safety, even when someone else or even yourself comes back to this code a week later and monkeys with it by taking out the filter:
let identifiers = json.map({ $0[ identifier ] ?? NSNull() }).filter { !($0 is NSNull) }
Now you are safely unwrapping with the nil coalescing operator (??
) and providing a default object (NSNull
), then filtering out those default objects.
Upvotes: 1
Reputation: 1640
This function will not crash the compiler:
private func allIdentifiersInJson(json: [JSONDictionary], key: String?) -> [AnyObject] {
if let key = key {
let identifiers = json.map{ $0[key]! } //this returns [AnyObject]
return identifiers ?? []
}
return []
}
Upvotes: 0