簡體   English   中英

打開時崩潰nil可選

[英]Crash on unwrapping nil optional

我創建了一個新的運算符,只有當值不為nil時才將值與目標關聯,否則不執行任何操作。 基本上它是合成糖, 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
    }
}

這樣我可以節省一些打字:

// instead this:
if let x = maybeX {
    z = x
}

// I can do this:
z =? x

我的問題是,當我到達執行線( z =? x )時,我甚至在進入實現函數之前崩潰,但異常:

fatal error: unexpectedly found nil while unwrapping an Optional value

似乎Swift試圖強制解包x即使實現接受T?

有任何想法嗎?

這似乎是我的錯誤......我正在使用foo.z = ...其中foo是一個零UIImageView! ...來自筆尖的致命視圖......

我很樂意在@RMenke建議后使用nil合並運算符更改我的實現,但據我所知,這將導致在x為nil時將z設置為z的冗余操作...例如:

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發表了重要評論:

如果運算符(或函數)接受inout參數,則即使您未在運算符內分配新值,也會在返回時調用屬性setter

為了解決這個問題,我將以下擴展作為_ = foo.map...方法的更清晰版本:

extension Optional {
    public func use<U>(@noescape f: (Wrapped) throws -> U) rethrows {
        _ = try self.map(f)
    }
}

//then:
x.use{ z = $0 }

它可能更好,因為當x為零時它不會調用z的setter,但它是最干凈/最清晰的方式嗎?

您的運營商有效,但您應該使用鏈式選項:foo?.z = ...

但是,當foo為nil時,這會給你另一種錯誤,你可以通過添加來解決

func =?<T>(lhs: T??, rhs: T?) -> ()
{}

操作符的“無操作”版本吸收了在傳遞最后一個成員之前具有nil的可選鏈時獲得的不可變參數版本。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM