在我正在制作的节目中,我试图访问网页内容以显示天气。我正在努力克服可选项的概念,我想知道为什么这行代码在“?”时有效。是,但不是没有。
@IBAction func pressedSearch(sender: AnyObject) {
var urlString = "http://www.weather-forecast.com/locations/" + cityField.text.stringByReplacingOccurrencesOfString(" ", withString: "") + "/forecasts/latest"
var url = NSURL(string: urlString)
println(urlString)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) in
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding)
var contentArray = urlContent?.componentsSeparatedByString("<span class=\"phrase\">") as Array<String>
println(contentArray[1])
}
task.resume()
}
以下是“?”的代码行添加以使代码工作:
var contentArray = urlContent?.componentsSeparatedByString("<span class=\"phrase\">") as Array<String>
什么是“?”做修复错误,为什么我们要添加“?”和“!”整个swift中的一些变量而不是其他变量?
答案 0 :(得分:2)
以下是一些代码可帮助您更好地理解?
和!
(包括您告诉机器的内容):
var foo = resultOfAFunctionThatReturnsAQuestionMarkValue()
foo.accessFunction() // "<silence>..."
// this could break if foo is nil
var bar = resultOfAFunctionThatReturnsAQuestionMarkValue()
bar?.accessFunction() // "Hey, bro. This might be nil.
// If it is, just ignore the line."
// accessFunction() might not be called,
// but it won't explode.
var asdf = resultOfAFunctionThatReturnsAQuestionMarkValue()
asdf!.accessFunction() // "Yo, dude. I know for sure this is not nil.
// Don't bother checking first. It's cool."
// this could break if asdf if nil
// You just lied to the computer.
// (They will remember.)
答案 1 :(得分:1)
问题在于这一行:
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding)
...您正在Objective-C / Cocoa中调用一个 failable initializer 的方法。它可以返回nil以指示失败(例如,因为无法使用该编码对数据进行解码)。
因此,在Swift中,如果 no 失败,则此方法返回一个可选的包装字符串(因为只有在没有可选的情况下才能在Swift中使用)。
因此,您必须将视为可选项 - 因为可选的包装字符串不是一个字符串 - 它是一个可选项。因此,您打开以访问String。
答案 2 :(得分:0)
来自官方文档
返回值
通过使用编码将数据中的字节转换为Unicode字符来初始化NSString对象。返回的对象可能与原始接收器不同。如果由于某种原因初始化失败(例如,如果数据不代表编码的有效数据),则返回 nil 。
使用NSString(data:, encoding:)
并不总是返回NSString,它可以返回nil。这就是urlContent
的类型为NSString?
而不是NSString
的原因。因此,您需要在下一行中填写问号。
有关更多信息?和!,见这里:What is an optional value in Swift?
TL; DR:“?”暗示一个变量可以是nil,如果你想访问它,忽略那个nil的可能性,你需要“!”
答案 3 :(得分:0)
您的代码行是&#34;可选链接&#34;的示例。当您尝试访问可能为nil
的变量的方法或属性时,将使用它。以此为例:
class Person {
let firstName = "John"
var lastName: String? = nil
}
let person = Person()
现在假设你试图对person
的姓氏进行操作......你想要一个大写的版本,或者其他东西。您的代码可能如下所示:
let ucLastName = person.lastName.uppercaseString
但lastName
是nil
。你不能对它做任何事情,因为它不存在。如果上面的代码能够编译,那么当你运行它时它会使程序崩溃。
为了防止崩溃,编译器要求您在?
之后插入lastName
,如下所示:
let ucLastName = person.lastName?.uppercaseString
那将编译。为什么?因为插入?
会告诉编译器忽略?
之后的所有内容lastName
nil
并将nil
返回ucLastName
- {{一旦编译器确定uppercaseString
。
在您的情况下,变量lastName == nil
是可选的 - 在我的示例中类似于urlContent
。您可能没有意识到它是可选的,因为您没有将其声明为一个,但它是,因为它是由函数lastName
返回的,它返回一个可选的结果。因此,即使你没有意识到它是可选的,编译器也知道它,并通过要求你在代码中插入NSString(data: data, encoding: NSUTF8StringEncoding)
值来告诉你。
要求?
是好的,因为:
?
变量的属性或方法时发生的运行时崩溃次数nil
。您会注意到如果处理错误,将会发生运行时崩溃。如果您不需要插入nil
,请考虑会发生什么。你的程序会在运行时崩溃,你必须通过在代码中搜索出错的东西来调试它,有时候很少有关于发生了什么的线索。 ?
以及随之而来的编译器警告允许您在编译时解决问题,而不是调试运行时崩溃。