HTML tutorial
CSS3 tutorial
Bootstrap tutorial
JavaScript tutorial
JQuery tutorial
AngularJS tutorial
React tutorial
NodeJS tutorial
PHP tutorial
Python tutorial
Python3 tutorial
Django tutorial
Linux tutorial
Docker tutorial
Ruby tutorial
Java tutorial
C tutorial
C ++ tutorial
Perl tutorial
JSP tutorial
Lua tutorial
Scala tutorial
Go tutorial
ASP.NET tutorial
C # tutorial
Optional chain (Optional Chaining) is a is a way to request and calls the property, the process approach and sub-script calls for the target request or may be nil.
Optional chain returns two values:
If the target has a value, the call succeeds, the return value
If the target is nil, the call will return nil
Multiple requests or calls can be linked into a chain, if any node is nil failure will cause the entire chain.
By appending properties, methods, or optional value index script put a question mark (?), You can define an optional chain.
Optional chain '?' | Exclamation point (!) To force expansion methods, properties, subscript script optional chain |
? An optional value placed on the later calling methods, properties, subscript script | ! Optional value placed on the later calling methods, properties, subscript script to expand mandatory values |
When the optional output is nil more friendly error messages | When the optional expansion to nil forced execution error |
class Person { var residence: Residence? } class Residence { var numberOfRooms = 1 } let john = Person() //将导致运行时错误 let roomCount = john.residence!.numberOfRooms
The above program execution output is:
fatal error: unexpectedly found nil while unwrapping an Optional valueWant to use an exclamation point (!) To force parsing of this person residence property numberOfRooms property value, it will throw a runtime error, because then there is no value can be used for residence resolved.
class Person { var residence: Residence? } class Residence { var numberOfRooms = 1 } let john = Person() // 链接可选residence?属性,如果residence存在则取回numberOfRooms的值 if let roomCount = john.residence?.numberOfRooms { print("John 的房间号为 \(roomCount)。") } else { print("不能查看房间号") }
The above program execution output is:
不能查看房间号
Because these attempts numberOfRooms operation may fail, optional chain will return Int? Type value, or called "Optional Int". When the residence was empty when (the example), select Int will be empty, so there will not be the case of access numberOfRooms.
It should be noted that even non-optional numberOfRooms Int (Int?) When this is also true. As long as the request is optional chain by means of a final numberOfRooms always return Int? Instead Int.
You can use an optional chain to multi-call properties, methods, and index script. This allows you to use complex models between them to get more underlying properties, and check whether you can obtain such underlying property.
Model defines four classes, including multi-optional chain:
class Person { var residence: Residence? } // 定义了一个变量 rooms,它被初始化为一个Room[]类型的空数组 class Residence { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { return rooms[i] } func printNumberOfRooms() { print("房间号为 \(numberOfRooms)") } var address: Address? } // Room 定义一个name属性和一个设定room名的初始化器 class Room { let name: String init(name: String) { self.name = name } } // 模型中的最终类叫做Address class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } }
Method to invoke the alternative settings you can use an optional chain and check the method call was successful. Even if this method does not return a value, you can still use an optional chain to achieve this purpose.
class Person { var residence: Residence? } // 定义了一个变量 rooms,它被初始化为一个Room[]类型的空数组 class Residence { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { return rooms[i] } func printNumberOfRooms() { print("房间号为 \(numberOfRooms)") } var address: Address? } // Room 定义一个name属性和一个设定room名的初始化器 class Room { let name: String init(name: String) { self.name = name } } // 模型中的最终类叫做Address class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } } let john = Person() if ((john.residence?.printNumberOfRooms()) != nil) { print("输出房间号") } else { print("无法输出房间号") }
The above program execution output is:
无法输出房间号
Use if statements to check whether a successful call printNumberOfRooms method: If the method call succeeds through an optional chain, printNumberOfRooms implicit return value will be the Void, if not successful, it returns nil.
You can use an optional chain to try to get the value from the standard script and examine the next call subscript script is successful, however, you can not set an optional chain index script.
class Person { var residence: Residence? } // 定义了一个变量 rooms,它被初始化为一个Room[]类型的空数组 class Residence { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { return rooms[i] } func printNumberOfRooms() { print("房间号为 \(numberOfRooms)") } var address: Address? } // Room 定义一个name属性和一个设定room名的初始化器 class Room { let name: String init(name: String) { self.name = name } } // 模型中的最终类叫做Address class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } } let john = Person() if let firstRoomName = john.residence?[0].name { print("第一个房间名 \(firstRoomName).") } else { print("无法检索到房间") }
The above program execution output is:
无法检索到房间
The next standard script calls the optional chain directly behind circname.print question mark, the next standard script parentheses front because circname.print optional chain trying to get the optional value.
Examples of instances to create a Residence john.residence, and one or more instances of his rooms Room array, then you can use the optional chain to get rooms in the array instance by Residence subscript script:
class Person { var residence: Residence? } // 定义了一个变量 rooms,它被初始化为一个Room[]类型的空数组 class Residence { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { return rooms[i] } func printNumberOfRooms() { print("房间号为 \(numberOfRooms)") } var address: Address? } // Room 定义一个name属性和一个设定room名的初始化器 class Room { let name: String init(name: String) { self.name = name } } // 模型中的最终类叫做Address class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } } let john = Person() let johnsHouse = Residence() johnsHouse.rooms.append(Room(name: "客厅")) johnsHouse.rooms.append(Room(name: "厨房")) john.residence = johnsHouse if let firstRoomName = john.residence?[0].name { print("第一个房间名为\(firstRoomName)") } else { print("无法检索到房间") }
The above program execution output is:
第一个房间名为客厅
With the optional link call, we can use the index to be read or written to an optional value, and determines the subscript call was successful.
class Person { var residence: Residence? } // 定义了一个变量 rooms,它被初始化为一个Room[]类型的空数组 class Residence { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { return rooms[i] } func printNumberOfRooms() { print("房间号为 \(numberOfRooms)") } var address: Address? } // Room 定义一个name属性和一个设定room名的初始化器 class Room { let name: String init(name: String) { self.name = name } } // 模型中的最终类叫做Address class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } } let john = Person() let johnsHouse = Residence() johnsHouse.rooms.append(Room(name: "客厅")) johnsHouse.rooms.append(Room(name: "厨房")) john.residence = johnsHouse if let firstRoomName = john.residence?[0].name { print("第一个房间名为\(firstRoomName)") } else { print("无法检索到房间") }
The above program execution output is:
第一个房间名为客厅
If the index may return null value type, such as Swift in the Dictionary of the key index. You can close the next target in brackets after the question mark to put a link to the subject under empty Return Value:
var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]] testScores["Dave"]?[0] = 91 testScores["Bev"]?[0]++ testScores["Brian"]?[0] = 72 // the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81]
The above example defines a testScores array contains two key-value pairs, the type String key is mapped to an integer array.
This sample calls with an optional link to "Dave" is set to the first element of the array 91, the first element +1 "Bev" array, and then try to "Brian" The first element of the array is set to 72 .
The first two calls are successful, because the two key presence. But the key "Brian" in the dictionary does not exist, so the third call failed.
You can chain together multiple layers optionally may be digging within the model properties further down the methods and index script. However, an optional multi-chain can add optional value ratio has returned more layers.
If you try to get through the optional Int value chain, regardless of how many link layer always returns Int ?. Similarly, if you try to get through the optional chain Int? Value, regardless of how many link layer always returns Int ?.
The following example attempts to get john's residence properties in the street address of the property. As used herein, the two optional chain to contact residence and address attributes, both of them are optional type:
class Person { var residence: Residence? } // 定义了一个变量 rooms,它被初始化为一个Room[]类型的空数组 class Residence { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { return rooms[i] } func printNumberOfRooms() { print("房间号为 \(numberOfRooms)") } var address: Address? } // Room 定义一个name属性和一个设定room名的初始化器 class Room { let name: String init(name: String) { self.name = name } } // 模型中的最终类叫做Address class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } } let john = Person() if let johnsStreet = john.residence?.address?.street { print("John 的地址为 \(johnsStreet).") } else { print("不能检索地址") }
The above program execution output is:
不能检索地址
If you set an example to the Address as a value john.residence.address and set a value for the actual street address of the property, you can chain multiple layers to get this optional attribute values.
class Person { var residence: Residence? } class Residence { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { get{ return rooms[i] } set { rooms[i] = newValue } } func printNumberOfRooms() { print("房间号为 \(numberOfRooms)") } var address: Address? } class Room { let name: String init(name: String) { self.name = name } } class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } } let john = Person() john.residence?[0] = Room(name: "浴室") let johnsHouse = Residence() johnsHouse.rooms.append(Room(name: "客厅")) johnsHouse.rooms.append(Room(name: "厨房")) john.residence = johnsHouse if let firstRoomName = john.residence?[0].name { print("第一个房间是\(firstRoomName)") } else { print("无法检索房间") }
The above example output is:
第一个房间是客厅
We can also call the method returns a null value by an optional link, and you can continue on the alternative settings link.
class Person { var residence: Residence? } // 定义了一个变量 rooms,它被初始化为一个Room[]类型的空数组 class Residence { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { return rooms[i] } func printNumberOfRooms() { print("房间号为 \(numberOfRooms)") } var address: Address? } // Room 定义一个name属性和一个设定room名的初始化器 class Room { let name: String init(name: String) { self.name = name } } // 模型中的最终类叫做Address class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } } let john = Person() if john.residence?.printNumberOfRooms() != nil { print("指定了房间号)") } else { print("未指定房间号") }
The above program execution output is:
未指定房间号