Swift4 基础部分: Optional Chaining(可选链)

本文是学习《The Swift Programming Language》整理的相关随笔,基本的语法不作介绍,主要介绍Swift中的一些特性或者与OC差异点。

系列文章:

  • Swift4 基础部分:The Basics
  • Swift4 基础部分:Basic Operators
  • Swift4 基础部分:Strings and Characters
  • Swift4 基础部分:Collection Types
  • Swift4 基础部分:Control Flow
  • Swift4 基础部分:Functions
  • Swift4 基础部分:Closures
  • Swift4 基础部分: Enumerations
  • Swift4 基础部分: Classes and Structures
  • Swift4 基础部分: Properties
  • Swift4 基础部分: Methods
  • Swift4 基础部分: Subscripts
  • Swift4 基础部分: Inheritance
  • Swift4 基础部分: Initialization
  • Swift4 基础部分: Deinitialization
  • Swift4 基础部分: Automatic Reference Counting(自动引用计数)

可选链可替代强制解析(Optional Chaining as an Alternative to Forced Unwrapping)

You specify optional chaining by placing a question mark 
(?) after the optional value on which you wish to call a 
property, method or subscript if the optional is non-nil. 
This is very similar to placing an exclamation mark (!) 
after an optional value to force the unwrapping of its 
value. The main difference is that optional chaining fails 
gracefully when the optional is nil, whereas forced 
unwrapping triggers a runtime error when the optional is 
nil.
  • 在想调用的属性、方法、或下标脚本的可选值后面放一个?,可以定义一个可选链。这很像在可选值后面放一个!来强制拆得其封包内的值。它们的主要的区别在于当可选值为空时可选链即刻失败,然而一般的强制解析将会引发运行时错误。

例子:

class Residence {
    var numberOfRooms = 1;
}

class Person {
    var residence: Residence?;
}
let john = Person();
let rootCount = john.residence!.numberOfRooms;

执行结果:

fatal error: unexpectedly found nil while unwrapping an Optional value

我们改写成可选链的方式去访问numberOfRooms:

let john = Person();
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).");
}else{
    print("Unable to retrieve the number of rooms.");
}

执行结果:

Unable to retrieve the number of rooms.

通过可选链调用属性(Accessing Properties Through Optional Chaining)

例子:

class Person {
    var residence: Residence?;
}

class Residence {
    var rooms = [Room]();
    var numberOfRooms: Int {
        return rooms.count;
    }
    subscript(i: Int) -> Room {
        return rooms[i];
    }
    func printNumberOfRooms() {
        print("The number of rooms is \(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();
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).");
} else {
    print("Unable to retrieve the number of rooms.");
}

john.residence = Residence();
if let roomCount = john.residence?.numberOfRooms {
    print("John's residence has \(roomCount) room(s).");
} else {
    print("Unable to retrieve the number of rooms.");
}

执行结果:

Unable to retrieve the number of rooms.
John's residence has 0 room(s).

通过可选链调用方法(Calling Methods Through Optional Chaining)

You can use optional chaining to call a method on an optional value, 
and to check whether that method call is successful. You can do this 
even if that method does not define a return value.
  • 可以使用可选链来调用方法去判断是否方法调用成功。即使该方法没有返回值。

例子:

let john = Person();
john.residence = Residence();
if john.residence?.printNumberOfRooms() != nil {
    print("It was possible to print the number of rooms.")
} else {
    print("It was not possible to print the number of rooms.")
}

执行结果:

It was possible to print the number of rooms.

使用可选链调用下标脚本(Accessing Subscripts Through Optional Chaining)

You can use optional chaining to try to retrieve and set a value from a 
subscript on an optional value, and to check whether that subscript 
call is successful.
  • 可以使用可选链尝试从下标脚本获取值并且检查是否调用成功。

例子:

let john = Person();
john.residence = Residence();
let room:Room = Room(name:"xz");
john.residence?.rooms.append(room);
if let firstRoomName = john.residence?[0].name {
    print("The first room name is \(firstRoomName).")
} else {
    print("Unable to retrieve the first room name.")
}

执行结果:

The first room name is xz.

连接多层链接(Linking Multiple Levels of Chaining)

You can link together multiple levels of optional chaining to drill 
down to properties, methods, and subscripts deeper within a model. 
However, multiple levels of optional chaining do not add more levels of 
optionality to the returned value.
  • 可以将多层可选链连接在一起,可以掘取模型内更下层的属性方法和下标脚本。然而多层可选链不能再添加比已经返回的可选值更多的层。

例子:

let john = Person();
john.residence = Residence();
john.residence?.address = Address();
john.residence?.address?.street = "beijing road";
if let johnsStreet = john.residence?.address?.street {
    print("John's street name is \(johnsStreet).");
} else {
    print("Unable to retrieve the address.");
}

执行结果:

John's street name is beijing road.

链接可选返回值的方法(Chaining on Methods with Optional Return Values)

例子:

let john = Person();
john.residence = Residence();
john.residence?.address = Address();
john.residence?.address?.street = "beijing road";
john.residence?.address?.buildingName = "beijing building";

if let buildingIdentifier = john.residence?.address?.buildingIdentifier()?.uppercased() {
    print("John's building identifier is \(buildingIdentifier).");
}

执行结果:

John's building identifier is BEIJING BUILDING.

你可能感兴趣的:(Swift4 基础部分: Optional Chaining(可选链))