ios - 自定义运算符来简化 If-Let

标签 ios swift generics

我想简化常量需要做的事情

if let firstName = firstName {
     self.name = firstName
}

执行此操作的可能的自定义通用运算符是

infix operator ?= {}
func ?= <T>(inout left: T, right: T?) {
    if let right = right {
        left = right
    }
}

将前面的示例简化为

self.name ?= firstName

这会产生一个问题,如果 firstName 的值为 nil,那么 Swift 会将该值包装在可选值中。

var name: String? = "Bob"
var firstName: String? = nil

self.name ?= firstName

print(self.name) 
/* 
     prints "nil" since it is wrapping firstName in an optional when 
     passed in.     

     E.g. Optional<nil> gets unwrapped to nil in function and assigned
*/

对自定义运算符有任何可能的修复吗?我尝试将左侧参数限制为不是可选参数,但这对于泛型的类型约束是不可能的。

最佳答案

问题(正如您已正确识别的那样)是因为左侧参数的类型为 T ,当您将可选值传递给它时 T将被推断为 Optional<Whatever> 。因为右侧参数是 T? (并且因为类型可以自由提升为可选类型),它将推断类型为 Optional<Optional<Whatever>> ,导致您观察到令人困惑的双重包装。

解决方案是添加一个重载来处理左侧参数也是可选的情况。

infix operator ?= {}
func ?= <T>(inout left: T, right: T?) {
    if let right = right {
        left = right
    }
}

// overload to deal with an optional left handed side
func ?= <T>(inout left: T?, right: T?) {
    if let right = right {
        left = right
    }
}

(请注意,在 Swift 3 中,inout 应出现在参数类型之前)

现在,如果您使用带有可选值的此运算符作为左手参数,Swift 将使用重载版本而不是原始版本,因为它始终倾向于更特定于类型的签名。这意味着右侧不会被包裹在双可选中,因为它现在与左侧参数的类型完全相同。

var name: String? = "Bob"
var firstName: String? = nil

name ?= firstName

print(name) // prints: Optional("Bob")

请注意,这与 ?? 类似。确实如此,它有两个定义来处理一侧是可选的、一侧是非可选的以及两侧都是可选的,以避免生成双重包装的选项:

@warn_unused_result
public func ??<T>(optional: T?, @autoclosure defaultValue: () throws -> T) rethrows -> T

@warn_unused_result
public func ??<T>(optional: T?, @autoclosure defaultValue: () throws -> T?) rethrows -> T?

关于ios - 自定义运算符来简化 If-Let,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37866087/

相关文章:

ios - 我如何使用 dynamicType 在 swift3 中执行 "perform(selector:)"

android - 使用 react-native 启用电话设置

ios - 从两个应用程序访问共享数据

iOS - 如何创建条纹图像?

ios - CNMutableContact 和 iOS 13 中的 note 和 imageData

C++ 的性能比 C 更好?

ios - Xamarin iOS : Simulator Works but Phone is blank

ios - 在给定时间创建 NSDate

swift - find() 使用函数式编程

xcode - 具有特定颜色的特定字母?