Swift可选项:语言问题,还是做错了什么?

时间:2014-09-02 06:50:01

标签: ios swift

我正在做我认为非常简单的任务。如果密钥存在,我正试图从字典中获取值。我正在为字典中的几个键执行此操作,然后创建一个对象(如果它们都存在)(基本上解码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...
}

这似乎是基本的替代,但我可能会遗漏一些语言的细微差别。任何人都可以对此有所了解吗?

2 个答案:

答案 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
}