Swift 有吗?等于零
我有: 其中Swift 有吗?等于零,swift,Swift,我有: 其中myParamKeyPath指的是字符串? 然后,当myParam应该是nil时,我有: value==nil返回false (值为?字符串?==nil返回true 是否可以检查value是否等于nil,而不必将其强制转换为字符串??比如将它与NSNull进行比较 此外,我不能直接将值类型更改为字符串?,因为它也用于代码中的其他类型 编辑: (值为?字符串?==nil返回true实际上是不相关的。 但我仍然可以打印键路径指向的值,它实际上是nil。所以我仍然不明白为什么value==
myParamKeyPath
指的是字符串?
然后,当myParam
应该是nil
时,我有:
value==nil
返回false
(值为?字符串?==nil
返回true
是否可以检查value
是否等于nil
,而不必将其强制转换为字符串?
?比如将它与NSNull
进行比较
此外,我不能直接将值
类型更改为字符串?
,因为它也用于代码中的其他类型
编辑:
(值为?字符串?==nil
返回true
实际上是不相关的。
但我仍然可以打印键路径指向的值,它实际上是nil
。所以我仍然不明白为什么value==nil
返回false
,而我希望它是true
EDIT2包含更多代码:
let value: Any? = myObject[keyPath: myParamKeyPath]
我希望得到fontAwesomeIcon=.squareO
,但是当myObject[keyPath:myParamKeyPath]
指向的值是String?
时,我得到的是checkSquareO
(稍后它对另一个值也是Bool?
)。
我一定是在什么地方遗漏了什么
编辑3个屏幕截图:
编辑4更多关于我在这里试图做什么的说明:
首先,如果你到达那里,再次感谢你的帮助
以下是关于我的项目当前设计的两张照片:
我在我的项目中使用KVO。我以前在这里使用objective-c字符串#keyPath。它工作得很好,但几乎我所有的模型都必须在@objc中转换。因此,我目前的目标是删除它并切换到新的Swift 4 keypath系统
要继续:我有一个用户类,其中包含许多设置(比屏幕截图上的设置更多),可以是几种类型(以及一些自定义类型)
另一方面,我创建了大约10个“设置编辑器视图控制器”:一个是按设置类型创建的。我想使用相同的设置编辑器VC来编辑每一个相同类型的设置
例如,如果要编辑的设置是布尔值,我希望使用“布尔编辑器VC”,并通过用户的新选择编辑所选设置。这就是我使用KVO系统的原因。如果你们有更好的解决方案,我不愿意留下。然后,它也会摆脱我的任何?==无问题。以下内容如何
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
}
}
问题是您的代码假设值为
String?
,而实际上它是String??
。我相信这是由于使用了AnyKeyPath
:
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
我想知道是否有某种方法可以调整您的代码以使用KeyPath
模式,这样,正如您所说,您的myParamKeyPath
确实明确地引用了字符串?
,例如:
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")
让foo=foo(条形:“baz”)
让keyPath=\Foo.bar
func键路径实验(对象:任意,键路径:任意键路径){
打印(对象[keyPath:keyPath])
}
func键路径实验2(对象:T,键路径:键路径){
打印(对象[keyPath:keyPath])
}
keyPath实验(对象:foo,keyPath:keyPath)//叹气:可选(可选(“baz”))
keyPath实验2(对象:foo,keyPath:keyPath)//好:可选(“baz”)
您的代码片段中没有足够的内容让我们了解如何精确地根据您的情况进行调整
正如罗布·纳皮尔(Rob Napier)所说,我想知道是否有更快捷的方法来解决这个问题。例如,当我看到这样的switch语句时,我可能倾向于使用
enum
模式。(value as?String)==nil
将返回true,如果该值不能转换为字符串,那么它可以是nil,也可以是Int,这将是true<如果代码>值==nil确实为nil,则应为true。如果value==nil
返回false,则值中有内容。我建议您放置一个断点,并检查它在调试器中实际包含的内容。Aaaaah是的,谢谢您的提示!!实际上(值为?XXX)==nil
几乎总是返回true。我正在调查…您的调试屏幕显示结果是可选(nil)
,这意味着您无疑正在查看字符串???
值。我无法足够强调类型Any?
有多混乱,以及如果它出现,您必须如何避免它并尽快转换为更具体的类型。Optional
本身就是类型Any
,而且任何类型都可以隐式提升为自身的Optional
。这意味着Any
、Any?
、Any???
、Any???
等都是可互换的,可以进行简单的推广。一旦您开始涉及Any?
,整个类型系统就会消失。什么类型是appSettings
,有没有办法避免它的值是any
?您想用appSettings
解决什么问题?我怀疑有一种更快捷的方法来解决这个问题。您需要对开关的特殊情况进行处理,这强烈表明这里存在设计问题。查看代码,我怀疑您真的希望在此处使用具有关联值的枚举,而不是将作为
强制转换。这就是我要查找的,但在我的示例中,v2==nil
在应该为真时为假。可能是因为我的AnyKeyPath
不够明确。谢谢@Rob的精彩报道。我已经在我的原始帖子中完成了我对我要做的事情的解释。
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")