问题
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
PersonandResidenceare 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` instanceshave an optional
residenceproperty of typeResidence?.If you create a new
Personinstance, itsresidenceproperty is default initialized tonil, by virtue of being optional. In the code below,johnhas aresidenceproperty value ofnil:let john = Person()If you try to access the
numberOfRoomsproperty of this person’sresidence, by placing an exclamation mark afterresidenceto force the unwrapping of its value, you trigger a runtime error, because there is noresidencevalue to unwrap:let roomCount = john.residence!.numberOfRooms // this triggers a runtime errorThe code above succeeds when
john.residencehas a non-nil value and will setroomCountto anIntvalue containing the appropriate number of rooms. However, this code always triggers a runtime error whenresidenceisnil, 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
residenceproperty and to retrieve the value ofnumberOfRoomsifresidenceexists.Because the attempt to access
numberOfRoomshas the potential to fail, the optional chaining attempt returns a value of typeInt?, or “optional Int”. Whenresidenceisnil, as in the example above, this optionalIntwill also benil, to reflect the fact that it was not possible to accessnumberOfRooms. The optionalIntis accessed through optional binding to unwrap the integer and assign the nonoptional value to theroomCountvariable.Note that this is true even though
numberOfRoomsis a nonoptionalInt. The fact that it is queried through an optional chain means that the call tonumberOfRoomswill always return anInt?instead of anInt.You can assign a
Residenceinstance tojohn.residence, so that it no longer has anilvalue: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