我正在做我认为非常简单的任务。如果密钥存在,我正试图从字典中获取值。我正在为字典中的几个键执行此操作,然后创建一个对象(如果它们都存在)(基本上解码JSON对象)。我是这门语言的新手,但在我看来,它似乎应该有用,但却没有:
class func fromDict(d: [String : AnyObject]!) -> Todo? {
let title = d["title"]? as? String
// etc...
}
它给了我错误:Operand of postfix ? should have optional type; type is (String, AnyObject)
但是,如果我这样做,它可以工作:
class func fromDict(d: [String : AnyObject]!) -> Todo? {
let maybeTitle = d["title"]?
let title = maybeTitle as? String
// etc...
}
这似乎是基本的替代,但我可能会遗漏一些语言的细微差别。任何人都可以对此有所了解吗?
答案 0 :(得分:3)
推荐的模式是
if let maybeTitle = d["title"] as? String {
// do something with maybeTitle
}
else {
// abort object creation
}
这可能是一个细微差别的问题。表单array[subscript]?
含糊不清,因为它可能意味着整个字典(<String:AnyObject>
)是可选的,而您可能意味着结果(String
)。在上面的模式中,您利用了Dictionary
旨在假设以可选类型访问某些键结果的事实。
经过实验,并注意到?
之后的as
同样含糊不清,更多,这是我的解决方案:
var dictionary = ["one":"1", "two":"2"]
// or var dictionary = ["one":1, "two":2]
var message = ""
if let three = dictionary["three"] as Any? {
message = "\(three)"
}
else {
message = "No three available."
}
message // "No three available."
这适用于所有非对象Swift对象,包括Swift字符串,数字等。感谢Viktor提醒我 String
不是Swift中的对象。 +
如果你知道值的类型,可以用Any?
替换String?
答案 1 :(得分:2)
这里有一些事情发生。
1)?
中的d["title"]?
使用不正确。如果您尝试解包d["title"]
,请使用!
,但要小心,因为如果title
不是您词典中的有效密钥,则会崩溃。 (?
用于可选链接,就像您尝试在可选变量上调用方法或访问属性一样。在这种情况下,如果可选,访问将无效是nil
)。您似乎没有尝试解开d["title"]
,因此请不要使用?
。字典访问始终返回可选值,因为密钥可能不存在。
2)如果你要解决这个问题:
let maybeTitle = d["title"] as? String
错误消息更改为:错误:&#39;(String,AnyObject)&#39;不能转换为&#39; String&#39;
这里的问题是String
不是对象。您需要转换为NSString
。
let maybeTitle = d["title"] as? NSString
这会导致maybeTitle
成为NSString?
。如果d["title"]
不存在或类型确实是NSNumber
而不是NSString
,那么可选项的值为nil
,但应用赢了&#39 ;崩溃。
3)你的陈述:
let title = maybeTitle as? String
不会根据需要解包可选变量。正确的形式是:
if let title = maybeTitle as? String {
// title is unwrapped and now has type String
}
所以把它们放在一起:
if let title = d["title"] as? NSString {
// If we get here we know "title" is a valid key in the dictionary, and
// we got the type right. title has now been unwrapped and is ready to use
}
title
将具有类型NSString
,它存储在字典中,因为它包含对象。您可以使用NSString
完成String
所做的大部分工作,但如果您需要title
成为String
,则可以执行此操作:
if var title:String = d["title"] as? NSString {
title += " by Poe"
}
如果您的词典也有NSNumber
:
if var age:Int = d["age"] as? NSNumber {
age += 1
}