是否有可能仅执行一项分配(例如:一个非可选的属性),如果右手边不是nil?我正在寻找一个单行形式:
if let unwrapped = funcThatReturnsOptional() { object.nonOptionalProperty = unwrapped }
amrnrhlw1#
与您的代码具有相同效果的单个表达式是
funcThatReturnsOptional().map { object.nonOptionalProperty = $0 }
但你的代码可读性肯定更好。这里使用了Optional的map()方法,并且只有当函数不返回nil时才会执行闭包。
Optional
map()
nil
hwazgwia2#
有很多种方法都不是很难操作使用??:
object.nonOptionalProperty = funcThatReturnsOptional() ?? object.nonOptionalProperty
使用函数:
func setNotNil<T>(inout variable:T, _ value:T?) { if value != nil { variable = value! } } setNotNil(&object.nonOptionalProperty, funcThatReturnsOptional())
使用运算符:
infix operator <-?? { associativity right precedence 90 assignment } func <-??<T>(inout variable:T, value:T?) { if value != nil { variable = value! } } object.nonOptionalProperty <-?? funcThatReturnsOptional()
使用扩展:
extension Equatable { mutating func setNotNil(value:Self?) { if value != nil { self = value! } } } object.nonOptionalProperty.setNotNil(funcThatReturnsOptional())
pxyaymoc3#
好的,实际上有一种方法可以通过引入一个新的运算符?=来实现这一点:
?=
infix operator ?= : AssignmentPrecedence func ?= <T: Any> (left: inout T, right: T?) { if let right = right { left = right } }
通过使用上面定义的?=,如果可选的内部有一个值,实际上可以将可选的分配给非可选的。
ijnw1ujt4#
来自@Sajjon的答案可以通过使用if let来避免反射来改进。
if let
precedencegroup OptionalAssignment { associativity: right } infix operator ?= : OptionalAssignment public func ?= <T>(variable: inout T, value: T?) { if let value = value { variable = value } }
qhhrdooz5#
@ch1llb4y和@ tyler-sheffer提供的解决方案都不起作用,因为泛型丢失了关于可选值的信息。但这可以使用下面的unwrap方法修复。
unwrap
precedencegroup OptionalAssignment { associativity: right } infix operator ?= : OptionalAssignment public func ?= <T>(variable: inout T, value: T?) { if let unwrapped = unwrap(any: value) ?? nil { variable = unwrapped } } public func unwrap<T: Any>(any: T) -> T? { let mirror = Mirror(reflecting: any) guard mirror.displayStyle == .optional else { return any } guard let child = mirror.children.first else { return nil } return unwrap(any: child.value) as? T }
我还没有想出一个解决方案,不必在unwrap(any: value) ?? nil中写入?? nil。
unwrap(any: value) ?? nil
?? nil
pw9qyyiw6#
我更喜欢用这样的闭包来完成它:
let unwrapped = { funcThatReturnsOptional() ?? object.nonOptionalProperty }()
这样,你也可以在处理多个可选属性时使用it guard语句:
guard let unwrapped = { funcThatReturnsOptional() ?? object.OptionalProperty }() else { return }
fumotvh37#
由于Swift是关于协议的,而POP,涉及协议的解决方案必然会发生。这里有一个古怪的协议,允许您将可选值分配给非可选属性:
protocol OptionalShortcut { } extension OptionalShortcut { subscript<T>(_ keyPath: WritableKeyPath<Self,T>) -> T? { get { self[keyPath: keyPath] } set { if let newValue = newValue { self[keyPath: keyPath] = newValue } } } }
只要让你的class/struct/enum/actor符合上面的协议,你就可以像这样写赋值:
object[\.nonOptionalProperty] = funcThatReturnsOptional()
我个人不喜欢下标和键路径语法(方括号很难看,除非它们涉及集合),但为了完整起见,我想给予解决方案。
7条答案
按热度按时间amrnrhlw1#
与您的代码具有相同效果的单个表达式是
但你的代码可读性肯定更好。
这里使用了
Optional
的map()
方法,并且只有当函数不返回nil
时才会执行闭包。hwazgwia2#
有很多种方法都不是很难操作
使用??:
使用函数:
使用运算符:
使用扩展:
pxyaymoc3#
好的,实际上有一种方法可以通过引入一个新的运算符
?=
来实现这一点:通过使用上面定义的
?=
,如果可选的内部有一个值,实际上可以将可选的分配给非可选的。ijnw1ujt4#
来自@Sajjon的答案可以通过使用
if let
来避免反射来改进。qhhrdooz5#
@ch1llb4y和@ tyler-sheffer提供的解决方案都不起作用,因为泛型丢失了关于可选值的信息。但这可以使用下面的
unwrap
方法修复。我还没有想出一个解决方案,不必在
unwrap(any: value) ?? nil
中写入?? nil
。pw9qyyiw6#
我更喜欢用这样的闭包来完成它:
这样,你也可以在处理多个可选属性时使用it guard语句:
fumotvh37#
由于Swift是关于协议的,而POP,涉及协议的解决方案必然会发生。
这里有一个古怪的协议,允许您将可选值分配给非可选属性:
只要让你的class/struct/enum/actor符合上面的协议,你就可以像这样写赋值:
我个人不喜欢下标和键路径语法(方括号很难看,除非它们涉及集合),但为了完整起见,我想给予解决方案。