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”,因为我最初的想法。我只是误解了《人与人》是完全不同的类型。一旦我明白了,所有其他的?,!疯狂,以及下面这些精彩的回答,让我觉得更有道理。


当前回答

如果john是一个可选的变量(这样声明)

var john: Person?

那么john可能没有值(在ObjC中为nil值)

感叹号基本上告诉编译器“我知道这有一个值,你不需要测试它”。如果你不想使用它,你可以有条件地测试它:

if let otherPerson = john {
    otherPerson.apartment = number73
}

只有当john有值时,这个内部才有价值。

其他回答

博士TL;

感叹号在Swift语言中是什么意思?

感叹号实际上是在说:“我知道这是可选的 肯定有一个值;请使用它。”这被称为可选值的强制展开:

例子

let possibleString: String? = "An optional string."
print(possibleString!) // requires an exclamation mark to access its value
// prints "An optional string."

let assumedString: String! = "An implicitly unwrapped optional string."
print(assumedString)  // no exclamation mark is needed to access its value
// prints "An implicitly unwrapped optional string."

来源:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html / / apple_ref / doc / uid / TP40014097-CH5-XID_399

!意味着您正在强制打开对象!遵循。更多信息可以在苹果文档中找到,可以在这里找到:https://developer.apple.com/library/ios/documentation/swift/conceptual/Swift_Programming_Language/TheBasics.html

因为谷歌员工:

john!.department

...告诉编译器:

我知道约翰可有可无 把它当成有价值的东西来使用 如果没有,就崩溃

在生产中,使用保护let或if let来处理无值和无效硬崩溃的情况。

总之(!): 在你声明了一个变量并且你确定这个变量有一个值之后。

let assumedString: String! = "Some message..."
let implicitString: String = assumedString

否则你必须在每次传递值之后都这样做…

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // requires an exclamation mark

如果你来自c语言家族,你会想“指向X类型对象的指针,它可能是内存地址0 (NULL)”,如果你来自动态类型语言,你会想“对象可能是X类型,但可能是未定义的类型”。这两种说法实际上都不正确,尽管迂回地说,第一个说法很接近。

你应该把它想象成一个物体:

struct Optional<T> {
   var isNil:Boolean
   var realObject:T
}

When you're testing your optional value with foo == nil it's really returning foo.isNil, and when you say foo! it's returning foo.realObject with an assertion that foo.isNil == false. It's important to note this because if foo actually is nil when you do foo!, that's a runtime error, so typically you'd want to use a conditional let instead unless you are very sure that the value will not be nil. This kind of trickery means that the language can be strongly typed without forcing you to test if values are nil everywhere.

实际上,它并不是这样做的,因为工作是由编译器完成的。在高层次上有一个类型Foo?它与Foo是分开的,这可以防止接受类型Foo的函数函数接收到nil值,但在低级别上,可选值不是一个true对象,因为它没有属性或方法;实际上,它很可能是一个指针,在强制展开时,通过适当的测试,它可能是NULL(0)。

还有一种情况,你会看到感叹号是在一种类型上,比如:

func foo(bar: String!) {
    print(bar)
}

这大致相当于接受一个强制展开的可选选项,即:

func foo(bar: String?) {
    print(bar!)
}

你可以使用它来创建一个方法,该方法在技术上接受一个可选值,但如果它为nil,则会出现运行时错误。在当前版本的Swift中,这显然绕过了is-not-nil断言,所以你会有一个低级错误。通常不是个好主意,但在从另一种语言转换代码时可能很有用。