Swift variable value
What's the difference between these two ads? Which one is better? Why?
... error = some NSError ...
1.
var newUserInfo: [NSObject: NSObject] = [:]
if let tempUserInfo = error.userInfo as? [NSObject: NSObject] {
newUserInfo = tempUserInfo
}
2.
var newUserInfo: [NSObject: NSObject]
if let tempUserInfo = error.userInfo as? [NSObject: NSObject] {
newUserInfo = tempUserInfo
} else {
newUserInfo = [:]
}
source to share
As of Swift 1.2, you can use let
deferred assignment so that you can use your if / else version:
let newUserInfo: [NSObject: NSObject]
if let tempUserInfo = error.userInfo as? [NSObject: NSObject] {
newUserInfo = tempUserInfo
} else {
newUserInfo = [:]
}
However, option 1 will not work as there is a path that newUserInfo
cannot be set.
(note that as of 1.2b1 this does not work with globals, only member and local variables if you try this in a playground)
Alternatively, you can use the nil-coalescing operator to do this in one go, e.g .:
let newUserInfo = (error.userInfo as? [NSObject:NSObject]) ?? [:]
edit: Swift 1.2 adds deferred assignment let
, now includes 2s option let
, but also changed the priority of as?
vs ??
, requiring parens.
Pre-1.2 answer if you have similar code that you need to port:
None of them are particularly appealing if you ask me. In both cases, you need to declare newUserInfo
using var
, because you are not declaring or assigning it in one go.
I would suggest:
let newUserInfo = error.userInfo as? [NSObject:NSObject] ?? [:]
source to share
- In
newUserInfo
1.assigned twice if branch is executedif
. 2.better in terms of performance - In 1. it is clear that it is
newUserInfo
initialized as an empty array. 2.makes the code less readable because you need to look at the code to see if the default is - If
newUserInfo
it is possible to install in multiple locations (for example if it can be initialized in multiple operationsif
) then you should duplicate the branchelse
in 2., so 1. looks better
So: not in the solution. 1 code is more readable, but no solution. 2 is slightly more effective.
Apart from using @AirspeedVelocity's solution (which is better than yours, no offense :)), I prefer to use optional , setting newUserInfo
to nil to indicate no value - after all, what are these options, right? But of course it depends on your specific needs.
source to share
My preferred template for this:
struct TryUnrap<T> {
typealias Tryee = () -> T?
typealias Catchee = () -> T
private var tryee: Tryee
init(tryee: Tryee) {
self.tryee = tryee
}
func catch(catchee: Catchee) -> T {
if let result = tryee() {
return result
}
return catchee()
}
}
let error: NSError? = NSError()
let newUserInfo = TryUnrap {
error?.userInfo as? [NSObject : NSObject]
}.catch {
[:]
}
println("newUserInfo = \(newUserInfo)")
I prefer the above because I think it is best for me. Also see Answer 4 Error Handling in Swift-Language for general error handling using the same pattern.
source to share