我创建了一个新的运算符,只有当值不为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
即使实现接受x
,Swift也会尝试强制解包T?
。
有什么想法吗?
答案 0 :(得分:0)
这似乎是我的错误......我正在使用foo.z = ...
,其中foo
是nil UIImageView!
...来自nib的那些... ...
我很乐意在@RMenke建议后使用nil合并运算符更改我的实现,但据我所知,当x为nil时,这将导致将z设置为z的冗余操作... 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发表了重要评论:
如果操作符(或函数)接受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,但它是最干净/最清晰的方式吗?
答案 1 :(得分:-1)
您的运算符有效,但您应该使用链式选项:foo?.z = ...
但是,当foo为nil时,这会给你另一种错误,你可以通过添加
来解决func =?<T>(lhs: T??, rhs: T?) -> ()
{}
这&#34;什么都不做&#34;运算符的版本吸收了在传递最后一个成员之前具有nil的可选链时获得的不可变参数版本。