什么是 '!'和 '?' Swift 中使用的标记

What are '!' and '?' marks used for in Swift

当我从Objective-C转为Swift编程时,我遇到了'!'(感叹号)和'?'(问号)通常必须紧跟在 propertymethod 调用等之后。这些标记有什么用,如果我们不使用它们会怎样?

我在网上搜索了详尽的答案,但没有找到。所以我决定把我的答案放在这里,以防有人为此寻找明确的答案。

我还在下面的回答中包含了一个 link 与我的问题类似的问题,您可以在其中找到有关如何以及在何处使用这些标记(即“!”和“?”)的进一步解释。 ').我的问题和我的回答比 link.

中的类似问题更基本

这些标记使用的术语是 Optional Chaining。它们一般用于区分大小写,例如,a property 是否是,a method call returns nil.

Apple's language guide for Optional Chaining中解释的一个例子很好地说明了它们的用途:

First, two classes called Person and Residence are defined:

class Person {
    var residence: Residence?
}

class Residence {
    var numberOfRooms = 1
} Residence instances have a single `Int` property called `numberOfRooms`, with a default value of **1**. `Person` instances

have an optional residence property of type Residence?.

If you create a new Person instance, its residence property is default initialized to nil, by virtue of being optional. In the code below, john has a residence property value of nil:

let john = Person()

If you try to access the numberOfRooms property of this person’s residence, by placing an exclamation mark after residence to force the unwrapping of its value, you trigger a runtime error, because there is no residence value to unwrap:

let roomCount = john.residence!.numberOfRooms
// this triggers a runtime error

The code above succeeds when john.residence has a non-nil value and will set roomCount to an Int value containing the appropriate number of rooms. However, this code always triggers a runtime error when residence is nil, as illustrated above.

Optional chaining provides an alternative way to access the value of numberOfRooms. To use optional chaining, use a question mark in place of the exclamation mark:

if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).")
} else {
    print("Unable to retrieve the number of rooms.")
}
// Prints "Unable to retrieve the number of rooms."

This tells Swift to “chain” on the optional residence property and to retrieve the value of numberOfRooms if residence exists.

Because the attempt to access numberOfRooms has the potential to fail, the optional chaining attempt returns a value of type Int?, or “optional Int”. When residence is nil, as in the example above, this optional Int will also be nil, to reflect the fact that it was not possible to access numberOfRooms. The optional Int is accessed through optional binding to unwrap the integer and assign the nonoptional value to the roomCount variable.

Note that this is true even though numberOfRooms is a nonoptional Int. The fact that it is queried through an optional chain means that the call to numberOfRooms will always return an Int? instead of an Int.

You can assign a Residence instance to john.residence, so that it no longer has a nil value:

john.residence = Residence()

除了上面对可选链的一般概述之外,您还可以在 Whosebug 中查看此answer

希望这能让您对可选链有一些看法。

简单来说,添加一个

!

意味着你 100% 保证给出一个值....如果你添加一个“!”并且不给出一个值应用程序将崩溃说 returned 一个值为 nil(或类似的东西)....

?

意味着您可能 return 一个值...如果您能提供帮助,这是更好的做事方式...