Crash on unwrapping nil optional

丶灬走出姿态 提交于 2019-12-10 18:53:19

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!