Swift 1.2 cast [AnyObject?] to [AnyObject] - swift

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!

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)

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.

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.

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 []
}

Related

Get elements and count of Array of unknown type

Let's say we have an Array, assigned to a variable with the type Any
let something: Any = ["one", "two", "three"]
Let's also assume we don't know if it's an array or something entirely else. And we also don't know what kind of Array.Element we are dealing with exactly.
Now we want to find out if it's an array.
let isArray = something is Array // compiler error
let isArray = (something as? [Any?] != nil) // does not work (array is [String] and not [Any?])
Is there any elegant solution to tickle the following information out of the swift type system:
Is the given object an Array
What's the count of the array
Give me the elements of the array
(bridging to NSArray is not a solution for me, because my array could also be of type [Any?] and contain nil-values)
I love #stefreak's question and his solution. Bearing in mind #dfri's excellent answer about Swift's runtime introspection, however, we can simplify and generalise #stefreak's "type tagging" approach to some extent:
protocol AnySequenceType {
var anyElements: [Any?] { get }
}
extension AnySequenceType where Self : SequenceType {
var anyElements: [Any?] {
return map{
$0 is NilLiteralConvertible ? Mirror(reflecting: $0).children.first?.value : $0
}
}
}
extension Array : AnySequenceType {}
extension Set : AnySequenceType {}
// ... Dictionary, etc.
Use:
let things: Any = [1, 2]
let maybies: Any = [1, nil] as [Int?]
(things as? AnySequenceType)?.anyElements // [{Some 1}, {Some 2}]
(maybies as? AnySequenceType)?.anyElements // [{Some 1}, nil]
See Swift Evolution mailing list discussion on the possibility of allowing protocol extensions along the lines of:
extension<T> Sequence where Element == T?
In current practice, however, the more common and somewhat anticlimactic solution would be to:
things as? AnyObject as? [AnyObject] // [1, 2]
// ... which at present (Swift 2.2) passes through `NSArray`, i.e. as if we:
import Foundation
things as? NSArray // [1, 2]
// ... which is also why this fails for `mabyies`
maybies as? NSArray // nil
At any rate, what all this drives home for me is that once you loose type information there is no going back. Even if you reflect on the Mirror you still end up with a dynamicType which you must switch through to an expected type so you can cast the value and use it as such... all at runtime, all forever outside the compile time checks and sanity.
As an alternative to #milos and OP:s protocol conformance check, I'll add a method using runtime introspection of something (foo and bar in examples below).
/* returns an array if argument is an array, otherwise, nil */
func getAsCleanArray(something: Any) -> [Any]? {
let mirr = Mirror(reflecting: something)
var somethingAsArray : [Any] = []
guard let disp = mirr.displayStyle where disp == .Collection else {
return nil // not array
}
/* OK, is array: add element into a mutable that
the compiler actually treats as an array */
for (_, val) in Mirror(reflecting: something).children {
somethingAsArray.append(val)
}
return somethingAsArray
}
Example usage:
/* example usage */
let foo: Any = ["one", 2, "three"]
let bar: [Any?] = ["one", 2, "three", nil, "five"]
if let foobar = getAsCleanArray(foo) {
print("Count: \(foobar.count)\n--------")
foobar.forEach { print($0) }
} /* Count: 3
--------
one
2
three */
if let foobar = getAsCleanArray(bar) {
print("Count: \(foobar.count)\n-------------")
foobar.forEach { print($0) }
} /* Count: 5
-------------
Optional("one")
Optional(2)
Optional("three")
nil
Optional("five") */
The only solution I came up with is the following, but I don't know if it's the most elegant one :)
protocol AnyOptional {
var anyOptionalValue: Optional<Any> { get }
}
extension Optional: AnyOptional {
var anyOptionalValue: Optional<Any> {
return self
}
}
protocol AnyArray {
var count: Int { get }
var allElementsAsOptional: [Any?] { get }
}
extension Array: AnyArray {
var allElementsAsOptional: [Any?] {
return self.map {
if let optional = $0 as? AnyOptional {
return optional.anyOptionalValue
}
return $0 as Any?
}
}
}
Now you can just say
if let array = something as? AnyArray {
print(array.count)
print(array.allElementsAsOptional)
}
This works for me on a playground:
// Generate fake data of random stuff
let array: [Any?] = ["one", "two", "three", nil, 1]
// Cast to Any to simulate unknown object received
let something: Any = array as Any
// Use if let to see if we can cast that object into an array
if let newArray = something as? [Any?] {
// You now know that newArray is your received object cast as an
// array and can get the count or the elements
} else {
// Your object is not an array, handle however you need.
}
I found that casting to AnyObject works for an array of objects. Still working on a solution for value types.
let something: Any = ["one", "two", "three"]
if let aThing = something as? [Any] {
print(aThing.dynamicType) // doesn't enter
}
if let aThing = something as? AnyObject {
if let theThing = aThing as? [AnyObject] {
print(theThing.dynamicType) // Array<AnyObject>
}
}

Swift Dictionary default value

A pattern I've gotten used to with Python's defaultdicts is a dictionary that returns a default value if the value for a given key has not been explicitly set. Trying to do this in Swift is a little verbose.
var dict = Dictionary<String, Array<Int>>()
let key = "foo"
var value: Array<Int>! = dict[key]
if value == nil {
value = Array<Int>()
dict[key] = value
}
I realize I can make a class that does this, but then the actual Dictionary has to be accessed through a property to use any of the other normal Dictionary methods
class DefaultDictionary<A: Hashable, B> {
let defaultFunc: () -> B
var dict = Dictionary<A, B>()
init(defaultFunc: () -> B) {
self.defaultFunc = defaultFunc
}
subscript(key: A) -> B {
get {
var value: B! = dict[key]
if value == nil {
value = defaultFunc()
dict[key] = value
}
return value
}
set {
dict[key] = newValue
}
}
}
Is there a better pattern for this?
This changed in Swift 4, and there's now a way to read a key's value or provide a default value if the key isn't present. For example:
let person = ["name": "Taylor", "city": "Nashville"]
let name = person["name", default: "Anonymous"]
This is particularly useful when modifying dictionary values, because you can write code like this:
var favoriteTVShows = ["Red Dwarf", "Blackadder", "Fawlty Towers", "Red Dwarf"]
var favoriteCounts = [String: Int]()
for show in favoriteTVShows {
favoriteCounts[show, default: 0] += 1
}
I covered this change and others in my article What's new in Swift 4.
Using Swift 2 you can achieve something similar to python's version with an extension of Dictionary:
// Values which can provide a default instance
protocol Initializable {
init()
}
extension Dictionary where Value: Initializable {
// using key as external name to make it unambiguous from the standard subscript
subscript(key key: Key) -> Value {
mutating get { return self[key, or: Value()] }
set { self[key] = newValue }
}
}
// this can also be used in Swift 1.x
extension Dictionary {
subscript(key: Key, or def: Value) -> Value {
mutating get {
return self[key] ?? {
// assign default value if self[key] is nil
self[key] = def
return def
}()
}
set { self[key] = newValue }
}
}
The closure after the ?? is used for classes since they don't propagate their value mutation (only "pointer mutation"; reference types).
The dictionaries have to be mutable (var) in order to use those subscripts:
// Make Int Initializable. Int() == 0
extension Int: Initializable {}
var dict = [Int: Int]()
dict[1, or: 0]++
dict[key: 2]++
// if Value is not Initializable
var dict = [Int: Double]()
dict[1, or: 0.0]
Unless I'm misunderstanding defaultdict in Python, I don't see how nil coalescing wouldn't work for you. Let's say you had a dictionary of type [Int:Int], and you wanted it to return 0 by default. With nil coalescing it looks like this:
let dict = [1:10, 2:8, 3:64]
let valueForKey = dict[4] ?? 0
You mentioned in a comment that that wouldn't work because it wouldn't update the dictionary. I don't understand the problem, though: why would you need to update the dictionary if you knew that every instance of nil would be replaced by your default? Maybe I'm missing something here but it seems like defaults and nil coalescing are (in practice) the same.
You can change the syntax a little, if it makes things more clear:
extension Dictionary {
subscript(key: Key, or r: Value) -> Value {
get { return self[key] ?? r }
set { self[key] = newValue }
}
}
In this case, the example above could be written like this:
let dict = [1:10, 2:8, 3:64]
let valueForKey = dict[4, or: 0]
In this case, mutating methods can work on the keys, like this:
var dict = [2: 8, 3: 64, 1: 10]
dict[2, or: 0]++
dict // [2: 9, 3: 64, 1: 10]
dict[4, or: 0]++
dict // [2: 9, 3: 64, 1: 10, 4: 1]
This extension is similar to the default subscript in Swift 4, with the difference that it will actually store the default value in the dictionary.
(It's also similar to QByte's answer, with the difference that it uses an autoclosure to prevent accessing the default when not needed).
extension Dictionary {
subscript(key: Key, setDefault defaultValue: #autoclosure () -> Value) -> Value {
mutating get {
return self[key] ?? {
let value = defaultValue()
self[key] = value
return value
}()
}
}
}
Note that no setter is defined for the subscript as the standard default subscript already fulfills this purpose.
Example:
var items = [String: ComplexItem]()
let item1 = items["milk", setDefault: ComplexItem()]
let item2 = items["milk", setDefault: ComplexItem()]
Here the ComplexItem is only created once because the dictionary retained it after the first access.

Swift - matching class dynamically

I am trying to write an extension method on Dictionary with the following signature:
func firstNonNilObjectForKey(keys: [Key], ofClass aClass: Any.Type = String.self) -> Value?
This is meant to help me deal with JSON dictionaries, where I often need the first non-null value, but sometimes the JSON includes null itself as value, which is converted to NSNull in Cocoa.
The usage would be something like:
let dict: [String:AnyObject] = [...]
let myValue = dict.firstNonNilObjectForKey([ "key1", "key2" ]) as? String
The issue is implementational - how to match the class:
if let value = self[key] {
if value is aClass { ... } <--- error: aClass is not a type
if let castedValue = value as? aClass { ... } <--- error: ditto
let type = value.dynamicType
if type == aClass { ... } <--- no error, but doesn't handle subclasses!
// Cannot use value.isKindOfClass() since value may be Any
}
I have thought of an alternative:
func firstNonNilObjectForKey<ReturnValueType>(keys: [Key]) -> ReturnValueType?
which allows to be implemented as
if let value = self[key] as? ReturnValueType { ... }
But:
- Here I cannot set the default type (I mostly need String.Type).
- I'm not really sure how to invoke this:
let value = dict.firstNonNilObjectForKey([ "key1", "key2" ]) as? String <--- error: Cannot invoke 'firstNonNilObjectForKey' with an argument list of type '([String])'
let value = dict.firstNonNilObjectForKey<String>([ ... ]) <--- error: Cannot explicitly specialize a generic function
I hope this isn't a duplicate, but most similar questions here are simply handling a situation where you are matching against a known class.
I'm not sure I got the requirements exactly, but can something like this work for you?
extension Dictionary {
func firstNonNilObjectForKey(keys: [Key]) -> String? {
return self.firstNonNilObjectForKey(keys, ofClass: String.self)
}
func firstNonNilObjectForKey<T>(keys: [Key], ofClass aClass: T.Type) -> T? {
for k in keys {
if let v = self[k] as? T {
return v
}
}
return nil
}
}
let dict = ["key1": 2, "key2": "Foo"]
let aString = dict.firstNonNilObjectForKey(["key1", "key2"]) // "Foo"
let anInt = dict.firstNonNilObjectForKey(["key1", "key2"], ofClass: Int.self) // 2
The main gotcha here is that I'm using overloading as opposed to default parameters, which don't seem to get along well with the swift type checker.

Map with Optional Unwrapping in Swift

Say I had the below api :
func paths() -> [String?] {
return ["test", nil, "Two"]
}
And I was using this in a method where I needed [String], hence I had to unwrap it using the simple map function. I'm currently doing :
func cleanPaths() -> [String] {
return paths.map({$0 as! String})
}
Here, the force-cast will cause an error. So technically I need to unwrap the Strings in the paths array. I'm having some trouble doing this and seem to be getting silly errors. Can someone help me out here?
compactMap() can do this for you in one step:
let paths:[String?] = ["test", nil, "Two"]
let nonOptionals = paths.compactMap{$0}
nonOptionals will now be a String array containing ["test", "Two"].
Previously flatMap() was the proper solution, but has been deprecated for this purpose in Swift 4.1
You should filter first, and map next:
return paths.filter { $0 != .None }.map { $0 as! String }
but using flatMap as suggested by #BradLarson is a just better
Perhaps what you want to is a filter followed by a map:
func cleanPaths() -> [String] {
return paths()
.filter {$0 != nil}
.map {$0 as String!}
}
let x = cleanPaths()
println(x) // ["test", "two"]
let name = obj.value
name.map { name in print(name)}

Swift: shortcut unwrapping of array of optionals

Assume we have an array of optionals defined:
var arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
I can force unwrap it in a short way: var arrayForCrash = arrayOfOptionals.map { $0! }
But that will make app to crash, is there any other short way(without explicitly unwrapping) how I can unwrap an array of optional?
This solution will get you a new array with all values unwrapped and all nil's filtered away.
Swift 4.1:
let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.compactMap { $0 }
Swift 2.0:
let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.flatMap { $0 }
Swift 1.0:
let arrayOfOptionals: [String?] = ["Seems", "like", "an", nil, "of", "optionals"]
let arrayWithNoOptionals = arrayOfOptionals.filter { $0 != nil }.map { $0! }
Since it is an array of optionals, it is possible some of the entries are nil. Instead of force unwrapping with !, use the nil coalescing operator to turns nils into empty strings.
let arrayOfOptionals: [String?] = ["This", "array", nil, "has", "some", "nils", nil]
let array:[String] = arrayOfOptionals.map{ $0 ?? "" }
// array is now ["This", "array", "", "has", "some", "nils", ""]
Although you can use flatMap { $0 } to remove nils, flatMap is actually a much more powerful function, and has an overloaded version which does something completely different (e.g. flatten [[Int]] to [Int]). If you're not careful, you may accidentally invoke the wrong function.
I would recommend using an extension on SequenceType to remove nils. If you use removeNils(), you'll be able to essentially do the following:
[1, nil, 2].removeNils() == [1, 2]
It works by making Optional conform to an OptionalType protocol which allows extending SequenceTypes that contain Optional values.
For more information see the original answer I posted.
I took #Cenny's answer and decided to make an operator out of it:
prefix operator <!> {}
prefix func <!> <T>(array: [T?]) -> [T] {
return array.filter{ $0 != nil }.map{ $0! }
}
I'm using it to parse an array of JSON objects and filter the ones that failed:
static func parse(j: JSONArray) -> [Agency]? {
return <!>j.map { self.parse($0) }
}
Update for Swift 2+:
Use flatMap operator and it'll only return non-nil objects
Swift 4
Easy to read and safe approach to filter nils of any sequence
protocol OptionalProtocol {
associatedtype Wrapped
var optional: Wrapped? { get }
}
extension Optional: OptionalProtocol {
var optional: Wrapped? {
return self
}
}
extension Sequence where Element: OptionalProtocol {
var removingOptionals: [Element.Wrapped] {
return self.compactMap { $0.optional }
}
}
Usage
let array: [Int?] = [1, 2, nil, 3, 4, nil]
print(array.removingOptionals) // prints [1, 2, 3, 4], has type [Int]
The more interesting, how to unwrap an optional array of optional values. It is important to deal when we are working with JSON, because JSON can potentially contain null value for an array of something.
Example:
{ "list": null }
// or
{ "list": [null, "hello"] }
To fill a Swift struct we may have a model:
struct MyStruct: Codable {
var list: [String?]?
}
And to avoid working with String?? as a first item we could:
var myStruct = try! JSONDecoder.init().decode(MyStruct.self, from: json.data(using: .utf8)!)
let firstItem: String? = s1.list?.compactMap { $0 }.first
With compactMap { $0 } we can avoid
let i2: String?? = s1.list?.first
compactMap { $0 } is an equivalent of filter { $0 != nil }. map { $0! }
How about:
import Foundation
var test: [String!] = ["this","is","a",nil,"test"]
for string in test {
if string != nil {
print(string)
}
}
Output is thisisatest.
In your case use [String!], if I understood you correctly.