解包时崩溃 nil 可选



我创建了一个新运算符,该运算符仅在值不为 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 为 nil 时不调用 z 的 setter,但它是最干净/最清晰的方法吗?

您的运算符有效,但您应该使用链接的可选:foo?。z = ...

但是,当foo为nil时,这将为您提供另一种错误,您可以通过添加

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

这个"无所事事"版本的运算符吸收了您在传递在最后一个成员之前具有 nil 的可选链时获得的不可变参数版本。

相关内容

  • 没有找到相关文章

最新更新