Optional value in swift? And! Examples of methods used

  • 2020-06-12 10:44:39
  • OfStack

Optional optional value

Optional is the main feature of Swift, and it is the most confusing problem for Swift beginners.

When defining a variable, specifying that the variable is optional means that the variable can have either a value of the specified type or nil.

In addition, Swift's nil is somewhat different from ES15en-ES16en. In ES17en-ES18en, only objects can be nil, while in Swift, when the base type (plastic, floating point, Boolean, etc.) has no value, it is ALSO nil instead of an initial value. A value without an initial value cannot be used, resulting in Optional. Defining a value for Optional is easy, as long as you put a question mark (?) after the type Just do it, e.g.


var str: String?

The difference between an Optional value and a non-ES29en value is that the Optional value is not initialized to nil, but the common variable is not even nil:


// Not initialized, but is 1 a Optional Type, nil
var str: String?
str // The output nil
// It's not initialized, and it's not Optional type 
var str2: String
str2  // Error in use 

About optional values! And? use

Let's start with a chestnut


class House {
 // The house has several rooms 
 var numRooms:Int = 5
}

class Person {
 //1 An individual may or may not have a house, so make the properties of the house optional 
 var house: House?
}

let xiaowang = Person()
// At this time xiaowang Don't have a house 
// If you try to call xiaowang the house Property, access house the numRooms Properties. The process is as follows: 
//1.  The first 1 Kind of way :  will house To unpack forcibly   ! . But at the moment,  house  There is no value, so the result is a direct crash. 
let numroom = xiaowang.house!.numRooms

//2.  with  if let
if let house = xiaowang.house {
 let roomCount = house.numRooms
}

//3.  with   ? 
if let numRooms = xiaowang.house?.numRooms {
 let numroom = numRooms
}

Now comes the question

How can house be followed by a question mark? Doesn't the question mark compiler know if it's going to report an error? Isn't the numRooms attribute of house a required attribute? Why use if let as an optional binding?

This involves a new piece of knowledge called a nullable chain call.

Empty chain call. When a property or method of an optional object is called, the question mark can be used directly, regardless of whether its property is optional. Each end returns 1 of the optional value.

Empty chain call

Empty chain call. When the properties and methods of an optional object are called. You can force the unpacking of the optional object first. Direct use? Optionally, the process of passing 1 straight back to the last property and method to be called, and finally returning an optional value.

Take the example above.


if let numRooms = xiaowang.house?.numRooms {
 let numroom = numRooms
}

The numRooms attribute of the optional object house is invoked. Meet the following conditions:

house is optional Calls the property numRooms of the optional object house There is no need to unpack the optional object house at this point Optionally, this feature is passed to numRooms So, return an optional value for numRooms.

Another example is chestnuts


class Room {
 // The room has a 4 A window 
 var numWindows:Int = 4
}

class House {
 // The house has several rooms 
 var room: Room?
}

class Person {
 //1 An individual may or may not have a house, so make the properties of the house optional 
 var house: House?
}

let windows = Person().house?.room?.numWindows

if let w = windows {
 //windows Is an optional value 
}
The property Room of house, an optional object, is accessed In this case, house does not have to unpack forcibly, regardless of whether Room is optional before. At this point, optional features are passed to Room, so Room also becomes optional. The numWindows attribute of the optional object Room is accessed again, at which point the optional characteristics are passed to numWindows. Returns an optional numWindows. windows is optional at this point.

Say more about calling methods on optional objects

The principle of the tuning method is one.

Let's start with the method. In swift, any method has a return value. There is no return value, just that it returns Void. Void is also a return value.
If you call a method on an optional object. The optional characteristics of the optional object are automatically passed to the method's return value.

Take a chestnut:


class Room {
 // The room has a 4 A window 
 var numWindows:Int = 4

 func closeWindow() {
 print(" Close the window ")
 }
}

class House {
 // The house has several rooms 
 var room: Room?

 func closeDoor() {
 print(" close the door ")
 }
}

class Person {
 //1 An individual may or may not have a house, so make the properties of the house optional 
 var house: House?
}

let person = Person()
// The following 1 A sentence, house  The optional features of the  closeDoor()  The return value of the  Void .   So what you're actually returning is 1 a   optional Void type 
person.house?.closeDoor()

// So, we can determine whether a method exists or not  nil
if person.house?.closeDoor() != nil {
 //closeDoor The closed method call succeeded 
} 

if person.house?.room?.closeWindow() != nil {
 //closeWindow  The method call to close the window succeeded 
}

If you don't care if the call is successful, then deciding whether it is nil is not a necessary step

So let me just conclude

When accessing properties or methods of an optional object, you can use? No. When accessing properties of an optional object from? All the following are optional. The return 1 must be an optional value. Access methods of an optional object. Determine nil to confirm that the method was invoked successfully.

Look at the chestnuts in the project


// Look at the calling properties first 
class PersonCell: UITableViewCell {

 var person: Person? {
 didSet {
  // The two places, person Is optional. access person The properties of? , and the return is 1 An optional  name
  textLabel?.text = person?.name
  detailTextLabel?.text = person?.phone
 }
 }

 override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
 super.init(style: .Subtitle, reuseIdentifier: reuseIdentifier)

 accessoryType = .DisclosureIndicator
 }

 required init?(coder aDecoder: NSCoder) {
 fatalError("init(coder:) has not been implemented")
 }
}

// Now let's look at the modulation method 
 func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
 let detailVC = DetailViewController()

 detailVC.person = persons[indexPath.row]
 detailVC.finishedCallBack = {
  self.tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .Top)
 }

// Here,  navigationController is 1 An optional attribute, then  pushViewController  Method returns 1 An optional Void . navigationController?.pushViewController(detailVC, animated: true)
 }

 // To determine whether  pushViewController  Whether successful, can do the following work 
 if navigationController?.pushViewController(detailVC, animated: true) != nil {
 // Push a success 
}

conclusion


Related articles: