快速可选的通用类型和嵌套的可选展开

时间:2019-06-05 17:52:50

标签: ios swift generics optional key-value-observing

我有这段代码

class MyObject<T> {

    func start(_ value: T?) {
        if let value = value {
            doSomething(value)
        }
    }

    func doSomething(_ value: T) {
        print(value)
    }
}

MyObject<String>().start("some")
// prints "some"

MyObject<String?>().start(nil)
// doesn't print anything

我需要为传递到-doSomething:的每个有效值调用-start:。并且当T == String?时,nil是有效值。

我是否需要在-start的扩展名中写上MyObject类型的两个版本的T?以及如何做到?

4 个答案:

答案 0 :(得分:2)

您可以使您的start函数采用非可选的T,而总是调用doSomething而不是尝试先对其进行拆包。仅当start(nil)本身是可选类型时,这才允许您调用T

class MyObject<T> {

    func start(_ value: T) {
        doSomething(value)
    }

    func doSomething(_ value: T) {
        print(value)
    }
}

MyObject<String>().start("some")
// prints "some"

MyObject<String?>().start(nil)
// prints "nil"

如果您想将参数保留为start作为可选参数,那么您的原始代码将可以正常使用,但是您需要在第二个示例中更改传递值的方式。

由于TString?,因此您方法中的参数的类型为String??,并且传递nil String??的方式与通过String?传递参数的方式不同。恰好包含nil

如果您将其称为:

MyObject<String?>().start(.some(nil))

let string: String? = nil
MyObject<String?>().start(string)

然后它将显示“ nil”

答案 1 :(得分:0)

由于let value = value在第二个输入中失败,因此您需要单独处理这种情况。

func start(_ value: T?) {
    if let value = value {
        doSomething(value)
    }
    else
    {
        print("nil input")
    }
}

答案 2 :(得分:0)

如果值是nil,则当展开时,该值将不会输入if语句中。相反,您可以执行以下操作:

class MyObject<T> {

    func start(_ value: T?) {
        if let value = value {
            doSomething(value)
        } else {
            print("nil")
        }
    }

    func doSomething(_ value: T) {
        print(value)
    }
}

答案 3 :(得分:0)

Swift中的可选只是一个通用枚举,有两种情况:

enum Optional<T> {
    case some(T)
    case none
}

例如String?Optional<String>是同一件事。

如果您声明MyObject<String?>基本上是在创建此MyObject<Optional<String>>,那么您的具体start方法将是

func start(_ value: Optional<Optional<String>>) { ... }

这意味着,如果您像start(nil)那样调用它,则整个对象当然为nil,而if let将失败。 但是,您可以通过这种方式调用该函数

MyObject<String?>().start(Optional.some(Optional.none))
MyObject<String?>().start(.some(.none)) // -> shorter version with type inference

基本上,现在存在外部可选对象,并且可展开,但内部可选对象为nil

但是我仍然不明白为什么你需要做类似的事情