关于在 Swift 中使用通用类型扩展 Optional 的问题

Issue about extending Optional with Generic Type in Swift

我试图为安全解包做一个扩展,我正在使用它的两个版本,一个长代码形式,第二个短代码!但没想到它们不起作用!就我所看到的代码而言,我只是把所有事情都弄对了!我缺少什么来修复这两个版本?

struct ContentView: View {
    
    let test: String? = "Hello, World!"
    
    var body: some View {
        Text(test.safeUnwrapV1(defaultValue: "Empty!"))
        Text(test.safeUnwrapV2(defaultValue: "Empty!"))
    }
    
}


extension Optional {    
    func safeUnwrapV1<T>(defaultValue: T) -> T {
        let wrappedValue: T? = (self as? T?) ?? nil
        if let unwrappedValue: T = wrappedValue { return unwrappedValue }
        else { return defaultValue }
    }
    
    func safeUnwrapV2<T>(defaultValue: T) -> T {
        return (self as? T) ?? defaultValue
    }
    
}

像这样制作你的扩展程序。

extension Optional {
    
    func safeUnwrapV1<T>(defaultValue: T) -> Wrapped {
        
        guard let value = self else {
            return defaultValue as! Wrapped
        }
        return value
    }
}

编辑: 正如@Rudedog 建议无需在此处定义泛型

extension Optional {
    func safeUnwrapV1(defaultValue: Wrapped) -> Wrapped {
        
        guard let value = self else {
            return defaultValue
        }
        return value
    }
}

无需定义您自己的泛型类型参数。 Optional 已经是泛型,其泛型类型参数称为 Wrapped。所以你只需要将默认值的类型声明为 Wrapped.

extension Optional {
    func defaultValue(_ value: Wrapped) -> Wrapped {
        self ?? value
    }
}

struct ContentView: View {

    let test: String? = "Hello, World!"

    var body: some View {
        Text(test.defaultValue("Empty!"))
    }
}
extension Optional {
    func safeUnwrap(_ defaultValue: Wrapped) -> Wrapped {
        switch self {
            case let value?: return value
            case nil: return defaultValue
        }
    }
}

甚至

extension Optional {
  func safeUnwrap(_ defaultValue: Wrapped) -> Wrapped {
    self ?? defaultValue
  }
}

但正如所指出的,这比仅使用 ?? 运算符更冗长且不那么惯用。

我会将 Optional 通用 Wrapped 类型限制为 LosslessStringConvertible:


extension LosslessStringConvertible {
    var string: String { .init(self) }
}

extension Optional where Wrapped: LosslessStringConvertible {
    var string: String { self?.string ?? "" }
    func string(default value: Wrapped) -> String {
        self?.string ?? value.string
    }
}

用法:

var double1 = Double("2.7")
var double2 = Double("a")

print(double1.string(default: 0))
print(double2.string(default: 0))

这将打印:

2.7
0