Ios Swift选项:语言问题,还是做错了什么?
我正在做我认为非常简单的事情。如果键存在,我试图从字典中获取一个值。我对字典中的几个键执行此操作,然后创建一个对象(如果它们都存在的话)(基本上是解码JSON对象)。我对这门语言还不熟悉,但在我看来,这门语言应该有用,但却不能:Ios Swift选项:语言问题,还是做错了什么?,ios,swift,Ios,Swift,我正在做我认为非常简单的事情。如果键存在,我试图从字典中获取一个值。我对字典中的几个键执行此操作,然后创建一个对象(如果它们都存在的话)(基本上是解码JSON对象)。我对这门语言还不熟悉,但在我看来,这门语言应该有用,但却不能: class func fromDict(d: [String : AnyObject]!) -> Todo? { let title = d["title"]? as? String // etc... } 它给了我一个错误:后缀的操作数?应具有
class func fromDict(d: [String : AnyObject]!) -> Todo? {
let title = d["title"]? as? String
// etc...
}
它给了我一个错误:后缀的操作数?应具有可选类型;类型为(字符串,任意对象)
但是,如果我这样做,它会起作用:
class func fromDict(d: [String : AnyObject]!) -> Todo? {
let maybeTitle = d["title"]?
let title = maybeTitle as? String
// etc...
}
这似乎是基本的替代,但我可能遗漏了语言的一些细微差别。有人能解释一下吗?推荐的模式是
if let maybeTitle = d["title"] as? String {
// do something with maybeTitle
}
else {
// abort object creation
}
这可能真的是一个细微差别的问题。格式数组[下标]?
不明确,因为它可能意味着整个字典(
)是可选的,而您可能指的是结果(字符串
)。在上面的模式中,您利用了这样一个事实,即字典
被设计为假设访问某些键会导致可选类型
经过实验,并注意到之后的?
与一样不明确,更重要的是,我的解决方案如下:
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) d[“title”]?
中的?
用法不正确。如果您试图展开d[“title”]
,请使用
但要小心,因为如果title
不是字典中的有效键,则会崩溃。(?
用于可选链接,就像您试图对可选变量调用方法或访问属性一样。在这种情况下,如果可选变量为nil
,则访问将不起任何作用)。您似乎没有试图打开d[“title”]
,因此请关闭?
。字典访问总是返回可选值,因为键可能不存在
2) 如果要解决此问题:
let maybeTitle = d["title"] as? String
错误消息更改为:错误:“(字符串,任意对象)”不能转换为“字符串”
这里的问题是字符串
不是对象。您需要强制转换到NSString
let maybeTitle = d["title"] as? NSString
这将导致maybeTitle
成为NSString?
。如果d[“title”]
不存在,或者如果类型确实是NSNumber
而不是NSString
,则可选值将为nil
,但应用程序不会崩溃
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
成为字符串,您可以执行以下操作:
if var title:String = d["title"] as? NSString {
title += " by Poe"
}
如果您的词典也有NSNumber
s:
if var age:Int = d["age"] as? NSNumber {
age += 1
}
因为NSString和String之间有自动转换;您正在将NSString保存为字符串而不强制转换。如果需要字符串,那么使用NSString只会让人感到困惑。遗憾的是,我们不得不使用NSString
,但在处理来自Cocoa和Cocoa touch调用的词典时,这是事实。如果字典是[String:Any]
的话,生活就会简单得多。因为每个NSObject都有一个可选的NSString,所以没有必要使用As而不是As
,As?
允许应用程序在字典没有我们期望的类型的情况下生存。当值实际为NSNumber
时,强制转换为NSString
将导致崩溃。如果字典来自外部源,那么假设您知道值的类型是什么是很危险的。请在操场上尝试此代码。然后将23更改为字符串<代码>变量d:[字符串:AnyObject]!=[“name”:“Fred”,“age”:23]如果让age:String=d[“age”]as?NSString{println(“age是一个字符串”)}如果让age:Int=d[“age”]as?NSNumber{println(“age是一个Int”)}
d[“title”]
是可选的,您在可选错误后使用?
。这个操作符的一个用例是object?.property
,因此它只会计算object.property
,当object
不是nil
时,它会返回nil
,我也这么认为,但这会在操场上抛出一个错误,就像@vacawama提到的那样。字典中的NSString
作为值显示为(String,AnyType)
的一种类型,不能在同一行中转换为String?
。。。你的maybeTitle将不再是maybe,否则它将不会在进入if括号之前被正确设置。如果字典的类型是[String:AnyObject]代码>就像OP的字典一样。这对我来说在操场上不起作用。如果让三个=字典[“三”]作为NSObject?
如果字典是[String:AnyObject]代码>。是的,这是类似的解决方案。