崩溃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 } }
这样我可以保存一些input:
// instead this: if let x = maybeX { z = x } // I can do this: z =? x
我的问题是,当我到达执行线( z =? x
)时,甚至在进入实现func之前崩溃,例外:
fatal error: unexpectedly found nil while unwrapping an Optional value
看来Swift试图强制unwrap x
甚至当实现接受T?
。
有任何想法吗?
这似乎是我的错误…我正在使用foo.z = ...
哪里foo
是一个无UIImageView!
从n dam的意见…
我会愉快地改变我的实现与@RMenkebuild议之后没有合并的运算符,但据我所知,这将导致一个冗余的行动,设置z为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参数,那么即使你没有在运算符内部赋值,属性设置器也会被返回。
为了解决这个问题,我做了下面的扩展,作为_ = 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为零时,这会给你另一种错误,你可以通过添加来修复
func =?<T>(lhs: T??, rhs: T?) -> () {}
运算符的这个“什么都不做”版本吸收了当传递一个可选链,在最后一个成员之前有一个零的时候得到的不可变参数版本。