iOS development language Swift entry---optional chain

Source: Internet
Author: User

iOS development Language Swift starter Series-optional chain optional chain (Optional Chaining)

is a procedure that can request and invoke properties, methods, and subscript scripts, and its optional representation is that the target of a request or call may currently be empty (nil). If the optional target has a value, the call succeeds, and conversely, if the selected target is empty (nil), the call returns Null (NIL). Multiple requests or calls can be chained together to form a chain, if any one of the nodes is empty (nil) will cause the entire chain to fail.
Attention:
The optional chain and the message in Objective-c are somewhat similar, but Swift can be used in any type, and failure or not can be detected.
Optional chain alternative to forced parsing
You can define an optional chain by placing a question mark after the optional value (optional value) (non-null) of the property, method, or subscript script that you want to invoke. This is much like placing an exclamation mark behind an optional value to force the value inside its packet to be removed. The main difference is that an optional chain fails immediately when an optional value is empty, whereas a general force resolution throws a run-time error.
To reflect that an optional chain can call null (nil), the returned result is an optional value, regardless of whether the returned value of the property, method, subscript script, and so on that you call is an optional value. You can use this return value to detect if your optional chain is successful, the return value succeeds, and nil returns to fail.
The return result of the invocation of the optional chain has the same type as the original return result, but the original return result is packaged as an optional value, and when the optional chain call succeeds, a property that should return int will return int?.
The following sections of code explain the differences between optional chains and forced parsing.
First, define two classes of person and residence.

class Person {    var residence: Residence?}class Residence {    var1}

The Residence has an int type of numberofrooms with a value of 1.  The person has an optional residence property whose type is residence?. If you create a new person instance whose Residence property is defined as selectable, this property will be initialized to NULL by default:

let john = Person()

If you want to use an exclamation mark (! Forcing a parse to get the value of this person's Residence property Numberofrooms property will raise a run-time error because there is no residence value to parse.

let roomCount = john.residence!.numberOfRooms//将导致运行时错误

When John.residence is not nil, it runs through, and the Roomcount is set to a reasonable value of type int.  However, as mentioned above, when residence is empty, this code will cause a run-time error. The optional chain provides another way to get numberofrooms. Use the optional chain to replace the original with a question mark! The location:

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

This tells Swift to link optional residence?  The Residence property that retrieves the value of numberofrooms if it exists. Because this attempt to get Numberofrooms is likely to fail, the optional chain returns an int? The type value, or "optional int".  When residence is empty (the previous example), selecting int will be empty, so you will not be able to access numberofrooms first. Note that even though the numberofrooms is optional int (int?). This is also true. As long as the request through an optional chain means that the last numberofrooms always returns an int?  instead of Int. You can define a residence instance for John.residence so that it is no longer empty:

john.residence = Residence()

John.residence now has an actual instance instead of nil. If you want to use the same optional chain as before to get numberofroooms, it will return an int that contains the default value of 1. :

if let roomCount = john.residence?.numberOfRooms {    println("John‘s residence has \(roomCount) room(s)."else {    println("Unable to retrieve the number of rooms.")}// 打印 "John‘s residence has 1 room(s)"。

Define a model class for an optional chain you can use the optional chain to call properties, methods, and subscript scripts in multiple layers.  This allows you to take advantage of the complex model between them to get more underlying properties and to check if such underlying properties can be successfully obtained. The following code defines four model classes that will be used later, including multi-layer optional chains.  These classes are extended by the person and residence model above by adding a single and an address class. The person class definition is the same as before.

class Person {    var residence: Residence?}

The Residence analogy is more complicated than before. This time, it defines a variable rooms, which is initialized to an empty array of type room[]:

class Residence {    var rooms = Room[]()    varnumberOfRooms: Int {    return rooms.count    }    subscript(i: Int) -> Room {        return rooms[i]    }    func printNumberOfRooms() {        println("The number of rooms is \(numberOfRooms)")    }    varaddress: Address?}

Because residence stores an array of instances of the instance, its Numberofrooms property value is not a fixed stored value but is calculated.  The Numberofrooms property value is determined by the Count property of the returned rooms array. To enable quick access to the rooms array, Residence defines a read-only subscript script that can be successfully invoked by inserting an array of element corners.  If the corner label is present, the subscript script returns the element.  Residence also provides a printnumberofrooms way to simply print the number of rooms. Finally, Residence defines an optional attribute called address. )。 The properties of the Address class are defined later. The class for the rooms array is a simple class that has only one name property and one initializer for the set name.

class Room {    name: String    init(name: String) { self.namename }}

The final class in this model is called address. It has three types is string? Optional properties. The previous two optional properties Buildingname and Buildingnumber as part of the address, are two ways to define a building. Third Property Street, the name of the street used to name the address:

class  Address {var  buildingname: string ?    var  buildingnumber: string ?    var  Street: string ? Func buildingidentifier (), string ? {if  buildingname {return  buildingn  AME} else  if  buildingnumber {return  buildingnumber} else  {return  Nil}}}  

The Address class also provides a Buildingidentifier method whose return value type is string?.  This method checks the properties of Buildingname and Buildingnumber, returns if the Buildingname has a value, or returns NULL if the Buildingname has a value, or if no property has a value. Calling properties with an optional chain as described in "optional chain substitution forced resolution" above, you can take advantage of the optional chain's optional values to get the property and check if the property is successful.  However, you cannot use an optional chain to assign a value to a property. Use the class defined above to create a person instance and try again after going to its Numberofrooms property:

let john = Person()iflet roomCount = john.residence?.numberOfRooms {    println("John‘s residence has \(roomCount) room(s)."else {    println("Unable to retrieve the number of rooms.")}// 打印 "Unable to retrieve the number of rooms。

Since john.residence is empty, this optional chain fails as before, but there is no run-time error. You can use an optional chain call method to invoke the optional value method and check whether the method invocation succeeded.  Even if the method does not have a return value, you can still use an optional chain to accomplish this. The Residence Printnumberofrooms method prints the current value of the numberofrooms. Here's how: empty, so this optional chain fails as before, but there is no run-time error.

func printNumberOfRooms(){    ofis \(numberOfRooms)”)}

This method has no return value.  However, functions and methods that do not return a value type have an implicit return value of type void (see function without return values). If you call this method with an optional chain, the return value type of this method will be void? , not void, because the return value is always an optional type (optional type) when the method is called through an optional chain. Even if the method itself does not have a return value defined, you can use the IF statement to check if the Printnumberofrooms method can be successfully invoked: if the method succeeds through an optional chain call, the implicit return value of printnumberofrooms will be void, if not successful, will return nil:

if john.residence?.printNumberOfRooms() {    println("It was possible to print the number of rooms."else {    println("It was not possible to print the number of rooms.")}// 打印 "It was not possible to print the number of rooms."。

Use an optional chain to invoke subscript scripts you can use an optional chain to try to get values from the subscript script and check if the call to the subscript script succeeds, however, you cannot set the subscript script with an optional chain. Note: When you use an optional chain to get the subscript script, you should place the question mark in front of the subscript script brackets instead of behind.  The question mark of an optional chain is usually followed directly by the expression statement. The following example uses the subscript script defined in the residence class to get the name of the first room in the john.residence array. Because John.residence is nil now, the call to the subscript script has failed.

if let firstRoomName = john.residence?[0].name {    println("The first room name is \(firstRoomName)."else {    println("Unable to retrieve the first room name.")}// 打印 "Unable to retrieve the first room name."。

The question mark of the optional chain in the subscript script call is followed by the john.residence, preceded by the subscript script parenthesis, because John.residence is an optional chain that is trying to obtain an alternative value. If you create a residence instance to john.residence and have one or more instances of the instance in his rooms array, you can use the optional chain to get an instance of the rooms array through the residence subscript script:

let johnsHouse = Residence()johnsHouse.rooms"Living Room")johnsHouse.rooms"Kitchen")john.residence = johnsHouseif let firstRoomName = john.residence?[0].name {    println("The first room name is \(firstRoomName).")} else {    println("Unable to retrieve the first room name.""The first room name is Living Room."。
Connecting multi-layer Links

You can connect multiple layers of optional chains together to dig into the lower-level attribute methods and subscript scripts within the model. However, multilayer optional chains can no longer add more layers than the optional values that have been returned. That is, if the type you are trying to obtain is not an optional type, it will become an optional type because of the optional chain used.  If the type you are trying to obtain is already an optional type, it will not improve the optional chain because it is optional. So: If you try to get an int value through an optional chain, no matter how many layers of links are used, the int is always returned. Similarly, what if you try to get int through an optional chain?  Value, regardless of how many layer links are used to return the always int?. The following example attempts to get the address's Street property in John's Residence property. The two-layer optional chain is used to contact the residence and Address properties, both of which are optional types:

if let johnsStreet = john.residence?.address?.street {    println("John‘s street name is \(johnsStreet)."else {    println("Unable to retrieve the address.")}// 打印 "Unable to retrieve the address.”。

The value of John.residence now contains a residence instance, but John.residence.address is nil now, so john.residence?. Address?.  The street call failed. From the above example, you try to get the street property value. The type of this property is string?. Therefore, although the optional type attribute is used before the two-layer optional chain, john.residence?. Address?.  The return value type of street is also string?. If you set an instance for address as the value of the john.residence.address and set an actual value for the address's Street property, you can get this attribute value through a multilayer optional chain.

let johnsAddress = Address()johnsAddress.buildingName"The Larches"johnsAddress.street"Laurel Street"john.residence!.address = johnsAddress
if let johnsStreet = john.residence?.address?.street {    println("John‘s street name is \(johnsStreet)."else {    println("Unable to retrieve the address.")}// 打印 "John‘s street name is Laurel Street."。

It's worth noting that, "! "Symbol is used when assigning an address instance to john.residence.address. The John.residence property is an optional type, so you need to use it before it gets the Address property!  Parse to get the actual value of it. An example of a method that links an optional return value explains how an optional chain can be used to obtain an optional Type property value.  You can also call a method that returns an optional type value through an optional chain and link the return value of the method as needed. The following example invokes the Buildingidentifier method in the address class through an optional chain. The return value type of this method is string?. As mentioned above, the final return value type of this method after an optional chain call is still string? :

if let buildingIdentifier = john.residence?.address?.buildingIdentifier() {    println("John‘s building identifier is \(buildingIdentifier).""John‘s building identifier is The Larches."。

If you want to further perform an optional chain on the return value of the method, place the optional chain question mark after the method bracket:

if let upper = john.residence?.address?.buildingIdentifier()?.uppercaseString {    println("John‘s uppercase building identifier is \(upper).""John‘s uppercase building identifier is THE LARCHES."。

Note: In the example above, you put the optional chain question mark after the parentheses because the optional value you want to link is the return value of the Buildingidentifier method, not the Buildingidentifier method itself.

iOS development language Swift entry---optional chain

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.