问题
When I changed from Objective-C
to Swift
programming, I have come across '!
' (exclamation mark) and '?
' (question mark) that often have to be put right after a property
, a method
call etc. What are these marks used for, and what happens if we did not use them?
I searched for a thorough answer on the web but could not find any. So I decided to put here my answer in case for anyone is in search of a clear answer for that.
I also included in my answer below a link to a question that is similar to mine, where you can find further explanation on how and where you can use these marks (i.e. '!' and '?'). My question asks and my answer explains at a more basic level than the similar question in the link.
回答1:
The terminology used for these marks is Optional Chaining
. They are generally used for distinguishing the cases, for example, whether a property
is, a method call
returns nil
.
An example explained in Apple's language guide for Optional Chaining is a good one to show the purpose of their use:
First, two classes called
Person
andResidence
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 typeResidence
?.If you create a new
Person
instance, itsresidence
property is default initialized tonil
, by virtue of being optional. In the code below,john
has aresidence
property value ofnil
:let john = Person()
If you try to access the
numberOfRooms
property of this person’sresidence
, by placing an exclamation mark afterresidence
to force the unwrapping of its value, you trigger a runtime error, because there is noresidence
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 setroomCount
to anInt
value containing the appropriate number of rooms. However, this code always triggers a runtime error whenresidence
isnil
, 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 ofnumberOfRooms
ifresidence
exists.Because the attempt to access
numberOfRooms
has the potential to fail, the optional chaining attempt returns a value of typeInt?
, or “optional Int”. Whenresidence
isnil
, as in the example above, this optionalInt
will also benil
, to reflect the fact that it was not possible to accessnumberOfRooms
. The optionalInt
is accessed through optional binding to unwrap the integer and assign the nonoptional value to theroomCount
variable.Note that this is true even though
numberOfRooms
is a nonoptionalInt
. The fact that it is queried through an optional chain means that the call tonumberOfRooms
will always return anInt?
instead of anInt
.You can assign a
Residence
instance tojohn.residence
, so that it no longer has anil
value:john.residence = Residence()
Besides the general overview of Optional Chaining above, you can look at this answer in StackOverflow.
Hope this gives you some perspective on Optional Chaining.
回答2:
In simpler terms adding a
!
means you are 100% guaranteed to give a value....if you add a "!" and don't give a value the app will crash saying returned a value that is nil (or something like that).....
?
means you might return a value...this is the better way of doing things if you can help it...
来源:https://stackoverflow.com/questions/37342844/what-are-and-marks-used-for-in-swift