Swift编程语言指南中有如下示例:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { println("\(name) is being deinitialized") }
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
var tenant: Person?
deinit { println("Apartment #\(number) is being deinitialized") }
}
var john: Person?
var number73: Apartment?
john = Person(name: "John Appleseed")
number73 = Apartment(number: 73)
//From Apple's “The Swift Programming Language” guide (https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html)
然后,在给这个人分配公寓时,他们使用感叹号来“打开实例”:
john!.apartment = number73
“展开实例”是什么意思?为什么有必要?它与仅仅做以下事情有什么不同:
john.apartment = number73
我对Swift语言很不熟悉。我只是想把基本的东西记下来。
更新:
我遗漏了一个很大的谜团(答案中没有直接说明——至少在写这篇文章的时候没有),那就是当你做以下事情的时候:
var john: Person?
这并不意味着“约翰是人的类型,它可能是nil”,因为我最初的想法。我只是误解了《人与人》是完全不同的类型。一旦我明白了,所有其他的?,!疯狂,以及下面这些精彩的回答,让我觉得更有道理。
The entire story begins with a feature of swift called optional vars.
These are the vars which may have a value or may not have a value. In general swift doesn't allow us to use a variable which isn't initialised, as this may lead to crashes or unexpected reasons and also server a placeholder for backdoors.
Thus in order to declare a variable whose value isn't initially determined we use a '?'.
When such a variable is declared, to use it as a part of some expression one has to unwrap them before use, unwrapping is an operation through which value of a variable is discovered this applies to objects. Without unwrapping if you try to use them you will have compile time error.
To unwrap a variable which is an optional var, exclamation mark "!" is used.
有时候你知道这样的可选变量会被系统或者你自己的程序赋值,但是稍后,比如UI outlet,在这种情况下,我们不会用问号"?"来声明可选变量,而是用"!"
因此,系统知道这个用“!”声明的变量现在是可选的,没有值,但将在其生命周期的后期接收一个值。
因此,感叹号有两种不同的用法,
1. 声明一个变量,该变量将是可选的,并且以后一定会接收值
2. 在表达式中使用可选变量之前,将其展开。
以上描述避免了太多的技术问题,我希望。
John是一个可选的Person,这意味着它可以保存值或为nil。
john.apartment = number73
如果John不是可选选项,则使用。由于john从不为nil,我们可以确定它不会在nil值时调用apartment。而
john!.apartment = number73
向编译器承诺John不是nil,然后打开可选选项以获取John的值并访问John的公寓属性。如果你知道john不是nil就用这个。如果你在可选的nil上调用这个,你会得到一个运行时错误。
文档中包含了一个很好的示例,其中convertedNumber是可选的。
if convertedNumber {
println("\(possibleNumber) has an integer value of \(convertedNumber!)")
} else {
println("\(possibleNumber) could not be converted to an integer")
}