问题
I made a new operator which associate a value to a target only if the value is not nil, otherwise does nothing.
Basically it's a synthetic sugar for if let foo = foo { faa = foo }:
infix operator =? {}
func =?<T>(inout lhs: T, rhs: T?) {
if let rhs = rhs {
lhs = rhs
}
}
func =?<T>(inout lhs: T?, rhs: T?) {
if let rhs = rhs {
lhs = rhs
}
}
That way I can save some typing:
// instead this:
if let x = maybeX {
z = x
}
// I can do this:
z =? x
My issue is that when I get to the line of execution (z =? x) I crash even before entering the implementation func with the exception:
fatal error: unexpectedly found nil while unwrapping an Optional value
It appears Swift tries to force unwrap x even when the implementation accepts T?.
Any ideas?
回答1:
This appeared to be my mistake... I was using foo.z = ... where foo was a nil UIImageView!... damm views from nib...
I would happily change my implementation with a nil coalescing operator following @RMenke suggestion but as far as I know this will cause a redundant action of setting z to z when x is nil... e.g.:
var z = someFoo()
var x: Int? = nil
z = x ?? z
// will this re-write z's reference to z again or simply do nothing?
@MartinR made an important comment:
if an operator (or function) takes an inout-parameter, then the property setter will be called on return even if you don't assign a new value inside the operator
Trying to solve the issue, I made the following extension as a cleaner version of the _ = foo.map... approach:
extension Optional {
public func use<U>(@noescape f: (Wrapped) throws -> U) rethrows {
_ = try self.map(f)
}
}
//then:
x.use{ z = $0 }
It's probably better since it does not call z's setter when x is nil, but is it the cleanest/clearest way?
回答2:
Your operator works but you should have used chained optionals: foo?.z = ...
However, this will give you another kind of error when foo is nil which you can fix by adding
func =?<T>(lhs: T??, rhs: T?) -> ()
{}
This "do-nothing" version of the operator absorbs the unmutable parameter version that you get when passing an optional chain that has a nil before the last member.
来源:https://stackoverflow.com/questions/34838661/crash-on-unwrapping-nil-optional