可选任何?等于零

时间:2018-01-11 19:22:33

标签: swift

我有:

let value: Any? = myObject[keyPath: myParamKeyPath]

其中myParamKeyPath是指String?

然后,当myParam应该是nil时,我有:

value == nil返回false

(value as? String?) == nil返回true

是否可以检查value是否等于nil而不必将其首先投放到String??可能会将它与NSNull进行比较吗?

此外,我无法将value类型直接更改为String?,因为它也用于我的代码中的其他类型。

编辑:

(value as? String?) == nil返回true确实无关紧要。 但我仍然可以打印键路径指向的值,它实际上是nil。所以我仍然不明白为什么value == nil在我期待它false时返回true ...

EDIT2包含更多代码:

    let setting = appSettings.settings[indexPath.row]
    let value = appSettings[keyPath: setting.keyPath]

    let fontAwesome: FontAwesome

    switch setting.keyPath {
    case \PrinterSettings.printableImageIDs:
        fontAwesome = blablabla
    case \WeatherSettings.lockscreenImageIDs:
        fontAwesome = blablabla
    default:
        if let value = value as? FakeButtonPlacementSubSettings {
            fontAwesome = blablabla
        } else {
            fontAwesome = value != nil ? .checkSquareO : .squareO
        }
    }

我希望得到fontAwesomeIcon = .squareO,但当checkSquareO指向的值为myObject[keyPath: myParamKeyPath]时,我得到String?(对于另一个值Bool?,它会相同{1}}稍后)。 我必须在某处遗漏某些东西......

EDIT 3截图: Screenshot

编辑4更多澄清我在这里要做的事情:

首先,如果你到那儿,再次感谢你的帮助。

以下是关于我的项目当前设计的2张照片: User model Setting usecase

我在我的项目中使用KVO。我之前使用的是objective-c字符串#keyPath。它工作得很好,但我的模型几乎都必须在@objc中转换。所以我目前的目标是删除它并切换到新的Swift 4密钥路径系统。

要恢复:我有一个包含大量设置的用户类(超过屏幕截图),可以是多种类型(还有一些自定义类型)。

另一方面,我创建了大约10个“设置编辑器视图控制器”:一个按设置类型。我想使用相同的设置编辑器VC来编辑每个相同类型的设置。

例如,如果要编辑的设置是布尔值,我想使用“布尔编辑器VC”并获取用户新选择编辑的所选设置。这就是我使用KVO系统的原因。如果你们有更好的解决方案,我不愿意保留它。那么它也会摆脱我的Any? ==无问题。

2 个答案:

答案 0 :(得分:0)

以下情况如何?

struct S {
    let x: String?
}

let v1: Any? = S(x: "abc")[keyPath: \S.x]
print(v1 is String? && v1 == nil) // false

let v2: Any? = S(x: nil)[keyPath: \S.x]
print(v2 is String? && v2 == nil) // true

答案 1 :(得分:0)

问题在于您的代码假设值为String?,而实际上是String??。我认为这源于使用AnyKeyPath

struct Foo {
    let bar: String?
}

let foo = Foo(bar: "baz")

let keyPath: AnyKeyPath = \Foo.bar
print(foo[keyPath: keyPath])                        // Optional(Optional("baz"))

let keyPath2 = \Foo.bar
print(foo[keyPath: keyPath2])                       // Optional("baz")

我想知道是否有某种方法可以调整您的代码以使用KeyPath<T, String?>模式,因此,正如您所说,您的myParamKeyPath确实明确地引用了String?,。eg :

let foo = Foo(bar: "baz")

let keyPath = \Foo.bar

func keyPathExperiment(object: Any, keyPath: AnyKeyPath) {
    print(object[keyPath: keyPath])
}

func keyPathExperiment2<T>(object: T, keyPath: KeyPath<T, String?>) {
    print(object[keyPath: keyPath])
}

keyPathExperiment(object: foo, keyPath: keyPath)    // Sigh: Optional(Optional("baz"))
keyPathExperiment2(object: foo, keyPath: keyPath)   // Good: Optional("baz")

我们的代码段中没有足够的内容让我们了解这可能会如何适应您的情况。

正如Rob Napier所说,我想知道是否有可能采用Swiftier解决问题的方法。例如。当我看到像这样的switch语句时,我可能倾向于倾向于enum模式。