In fact, the empty chain call does not have its name so strange, in short, is for Optional
the optional type (using the question mark ? suffix) and the forced expansion type (using an exclamation point ! suffix) method of use. In the ordinary writing code is only about the clear which values are nullable, which values are definitely present, but did not delve into the advantages of an empty call, there are things to be aware of when using. At least when I write a lot of sample code in front of me, I mostly define it according to my own idea. This section is a detailed description of the air conditioning, as for the chain, is a multi-layered call, presumably school.classroom.student.name
this is the method of invocation.
A nullable chain call is a procedure that can request and invoke properties, methods, and subscripts, and its nullability is reflected in the current possibility that the request and invocation are currently empty nil
. If the nullable target has a value, the call succeeds, and if the selected target is null, the call will return null nil
. Multiple successive calls can be linked together to form a chain of calls, and if any of the nodes are empty nil
, the entire call will fail.
Swift's nullable chaining calls and messages in objective-c are somewhat like, but Swift can be used in any type and be able to check whether the call was successful. An air-conditioning equivalent of Objective-c if (message == nil) { } else { }
, but only in the objective-c can be used in objects or variables, far from the powerful function of Swift.
Use a nullable chained tone to force the expansion
The following sentences read a bit of a mouthful, more understanding is good: optional value
?
You can define a nullable chain by placing a question mark after the nullable value of the property, method, or subscript that you want to invoke. This is much like placing an exclamation mark after a nullable value !
to force the value to be expanded. The main difference between them is that when a nullable value is empty, a nullable chain is simply a call failure, but a forced unveiling will run the error.
To put it simply, when we call a property or method, we want it to be non-empty and have a value, but we're not sure if we have a value, we're going to use a nullable chain. For example, to get the network data, and then show, we certainly want to get the data, but sometimes because of the network, the background of the problem, the data is empty, if you use the empty chain to deal with, it will be simpler.
It should be emphasized that the return result of a nullable chain call has the same type as the original return result, but is packaged as a nullable type value. For example, when a nullable chained call succeeds, the int
result of a type returns the int?
type.
The following lines of sample code show some differences between nullable chained calls and forced expansion:
//Household Information class person {varResidence:residence?}//House information, how many rooms are there altogether class Residence {varNumberofrooms =1 //default to only one room}//Create a new person instanceLet Personone = person ()//Because the Residence property is empty, so what if? Into! Forced to untie, will error. In addition, the code complement here is the band? Of Print(personone.residence?). Numberofrooms)//output: nil//Initialize the Residence propertyPersonone.residence = Residence ()//At this time residence already has the initial value, but the gallbladder code complements the time still uses?, at this time if will? Switch , and does not cause an error because it is mandatory for an already defined non-null valuePrint(personone.residence!. Numberofrooms)//output: 1Print(personone.residence?). Numberofrooms)//output: Optional (1), indicates a nullable
In fact, the most common scenario of a nullable chain call is the if
judgment of the statement, when the nullable chain call returns Yes when the operation A is executed, nil
not nil
when the action B is executed, as follows:
// 可空链式调用用于 if 语句判断iflet person = personOne.residence?.numberOfRooms {// 此时不为空 personOne.residence?.numberOfRooms = 1else {// 此时为空 personOne.residence?.numberOfRooms = nil}
Defining model classes with nullable chained calls
Multi-layered properties, methods, and subscripts can be called by using a nullable chain call. This allows the various sub-properties to be accessed down through various models. You can also determine whether a property, method, or subscript of a child property can be accessed based on whether it is null or not.
The following sample code defines four model classes, including multi-layer nullable chain calls. At the same time, the following knowledge points will be based on these 4 classes as a description:
//Household Informationclassperson {//House information, probably no house, so optional more suitablevarResidence:residence?}//House InformationclassResidence {//Room arrayvarRooms = [guest] ()//How many rooms are there altogethervarNumberofrooms:int {returnRooms.count}//House addressvarAddress:address?//Subscript method, select the first roomSubscript (Index:int)--------{get {returnRooms[index]//value} set {Rooms[index] = newvalue//Set Value}}//number of printed roomsFunc printnumberofrooms () {print ("Number of rooms: \ (rooms.count)")}}//Room informationclassThe hostel {//Room name LetNameStringInit (roomname name:String) {self.name = name}}//Address informationclassAddress {varBuildingname:String?//Building namevarBuildingnumber:String?//Building numbervarBuildingstreet:String?//Name of the street where the building is located//method, gets the unique identifier of the building, because it may be empty, so the returned string type is optionalFunc Buildingidentifier ()String? {if LetName = Buildingname {returnName}Else if LetNumber = Buildingnumber {returnNumber}Else{returnNil}}}
Accessing properties via a nullable chained call
Is the one we usually call the property, the method of the set, first create an instance, and then go to invoke. In fact, many times instances, attributes, etc. are nullable or forced to expand, the system will help us to identify, we need to understand why the completion of the situation, sometimes we need to manually decide whether optional or mandatory deployment.
Here is the code example, and the main points of attention are written in the comments:
//Create an instance of a householderLet John = Person ()ifLet Roomcount = John.residence?. numberofrooms {//Nullable chain call succeeds, this will not be performed because of the john.residence?. Numberofrooms is nil at this time .}Else{//Nullable chained call failed, will execute code here}//Set property values via a nullable chain callJohn.residence = Residence ()//Instantiate attribute John.residence firstJohn.residence?. Address = Address ()//Instantiate address//At this time, address already exists in order to modify its property valuesJohn.residence?. Address?. Buildingname ="Beijing"Print (john.residence?. Address?. Buildingidentifier ())//output: Optional ("Beijing")Print (john.residence!. Address!. Buildingidentifier ()!)//output: Beijing/*************** The above code must be each property is mandatory expansion, any one can be empty, will output Optional ("Beijing") ***************/
Calling a method with a nullable chain call
You can invoke a method with a nullable chained call and determine whether the call succeeds. Even if this method does not return a value. In fact, there is no way to return a value implicitly to the return Void
type. This means that a method that does not return a value also returns ()
or an empty tuple.
If you invoke a method that does not return a value on a nullable value by using a nullable chained call, the returned type will be an optional null type Void?
, not a Void
. The resulting return value is nullable because of an empty, nullable chain call nil
.
The following line of sample code, combined with the data type defined above, shows the difference between a nullable return value that can return an empty tuple:
// 不在可空链式调用上调用没有返回值的方法,默认是 Void 类型的返回,返回一个空的元组let residence = Residence()print(residence.printNumberOfRooms()) // 输出:number of rooms : 0 ()// 在可空链式调用上调用没有返回值的方法,返回的是一个可选的空类型 Void? ,因为只有可选类型才能为 nillet tom = Person()print(tom.residence?.printNumberOfRooms()) // 输出: nil
Similarly, it is possible to determine whether a value is successfully assigned to a property through a nullable chain call. The first thing you need to know is that you can't assign a value to a nil
property:
let jack = Person()let jackResidence = Residence()jack.residence? = jackResidence // 这句话并没有给 jack.residence? 赋值// 此时 jack.residence? == nilifnil{print("赋值成功"else {print("赋值失败")}// 输出: 赋值失败
As a comparison, compare the following code with the above differences:
let jack = Person()let jackResidence = Residence()jack.residence = jackResidence // 这句话给 jack.residence 了内存地址// 此时 jack.residence 已经被实例了ifnil{print("赋值成功"else {print("赋值失败")}// 输出: 赋值成功
Access subscript via a nullable chain transfer
With a nullable chain call, you can use the subscript to read or write to a null value, and to determine whether the subscript is successfully invoked. Note: You should place the question mark in front of the subscript square brackets instead of following it when access is nullable by a nullable chain call. A question mark that can be called with an empty chain is usually followed directly by a controllable expression. The question mark follows which expression indicates which expression is controllable.
In fact, access to subscript and access properties, methods are not different, can be used for if
statement judgment, can not give a value nil
of the property assignment:
//Access subscriptLet Rose = person ()ifLet Firstroomname = Rose.residence?. Rooms[0].name {Print("Because of rose.residence?" is a nullable value, and the value is nil at this time, so this sentence is not printed ")//Do not execute}Else{Print("be printed.")//Execute}//Assign a value to a property with a value of nilRose.residence?[0] = the Roomname:"Living ")//Assignment failed, at this time rose.residence? [0] = = NilRose.residence = Residence ()//Create an instanceRose.residence?. Rooms.Append(Roomname:"Firstroom"))//Add value//Try to access the subscript againifLet Firstroomnameagain = Rose.residence?. Rooms[0].name {Print("Because of rose.residence?" is a nullable value, and the value is nil at this time, so this sentence is not printed ")//Execute}Else{Print("be printed.")//Do not execute}
If the subscript returns a nullable type value, such as a subscript in Swift Dictionary
key
. You can link the nullable return value of the subscript by placing a question mark after the closing parenthesis of the subscript:
var testscrore = [ "John" : [88 , 91 , 78 ], "Jack" : [99 , 112 , 130 ]]testscrore[ "John" ]? [0 ] = 140 testscrore[ "Jack" ]? [0 ] = 33 testscrore[ " Hehe "]? [0 ] = 44 //This sentence does not execute, Removing the question mark will cause an error print (testscrore) //output: ["Jack": [33, 1 "John": [[+] []]
Multi-layer Links
You can use the nullable chaining of multiple properties to access properties, methods, and subscripts down. However, the multi-layer nullable chain call does not add the nullability of the return value, that is:
- If the value of the access is not nullable, a nullable value is returned through a nullable chain call.
- If the access value is already nullable, it will not become more empty through a nullable chain call.
So:
- Accessing a value through a nullable chain call
Int
will return Int?
, no matter how many times a nullable chained call is made.
- Similarly, access to a value through a nullable chained call
Int?
does not become more empty.
Link to a function that returns nullable
The above example shows how to obtain a controllable property value through a nullable chain call. It is also possible to invoke a method that returns a nullable value through a nullable chain call, and you can continue to link to null values:
// 对返回值可空的方法可以继续往下链接let liLei = Person()// 注意,在方法的圆括号后面加问号并不是指方法可空,而是指方法的返回值可空。iflet beginWithPrefix = liLei.residence?.address?.buildingIdentifier()?.hasPrefix("China"else { }
It's a bit of a bluff, it's just a matter of saying things that we've always used but don't care too much, so it's pretty easy to learn.
I am very lazy, have been learning what is not to be done. These two days to find an animation to see, the storm, the whole animation around Shakespeare's Hamlet, the storm two revenge drama unfolded, obviously so tall on the book I did not read, but the animation itself is quite good, characters are very characteristic. Like to see the animation can be mended.