Chaînage optionnel rapide
Le chaînage facultatif est un processus qui peut demander et appeler des propriétés, des méthodes et des indices. La cible de la demande ou de l'appel peut être nulle.
La chaîne facultative renvoie deux valeurs :
Si la cible a une valeur, l'appel réussira et renverra cette valeur
Si la cible est nulle, l'appel retournera nul
Plusieurs requêtes ou appels peuvent être liés dans une chaîne. Si un nœud est nul, la chaîne entière échouera.
Le chaînage facultatif peut remplacer l'analyse forcée
Un facultatif peut être défini en plaçant un point d'interrogation (?) après la valeur facultative d'une propriété, d'une méthode ou d'une chaîne de script d'indice.
可选链 '?' | 感叹号(!)强制展开方法,属性,下标脚本可选链 |
? 放置于可选值后来调用方法,属性,下标脚本 | ! 放置于可选值后来调用方法,属性,下标脚本来强制展开值 |
当可选为 nil 输出比较友好的错误信息 | 当可选为 nil 时强制展开执行错误 |
Utiliser le point d'exclamation (!) instance de chaîne facultative
class Person { var residence: Residence? } class Residence { var numberOfRooms = 1 } let john = Person() //将导致运行时错误 let roomCount = john.residence!.numberOfRooms
Le résultat de l'exécution du programme ci-dessus est :
fatal error: unexpectedly found nil while unwrapping an Optional value
Utiliser le point d'exclamation (!) instance de chaîne facultative
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("不能查看房间号") }
Le résultat de sortie de l'exécution du programme ci-dessus est :
不能查看房间号
En raison de cette opération de essayer d'obtenir numberOfRooms En cas d'échec, la chaîne facultative renverra une valeur de type Int ?, également connue sous le nom de « Int facultatif ». Lorsque la résidence est vide (l'exemple ci-dessus), le Int sélectionné sera vide, donc numberOfRooms ne sera pas accessible.
Notez que cela est vrai même lorsque numberOfRooms est un Int (Int ?) non facultatif. Tant que la requête passe par la chaîne facultative, cela signifie que le numberOfRooms final renvoie toujours un Int au lieu d'un Int ?
Définissez des classes de modèle pour les chaînes facultatives
Vous pouvez utiliser des chaînes facultatives pour appeler des propriétés, des méthodes et des scripts d'indice à plusieurs niveaux. Cela vous permet d'exploiter des modèles complexes entre eux pour obtenir des propriétés de niveau inférieur et de vérifier si vous pouvez obtenir avec succès de telles propriétés de bas niveau.
Instance
définit quatre classes de modèles, qui incluent plusieurs couches de chaînes facultatives :
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 } } }
Appeler des méthodes via des chaînes facultatives
Vous pouvez utiliser chaînage facultatif pour appeler des méthodes sur des valeurs facultatives et vérifier si l'appel de méthode a réussi. Même si cette méthode ne renvoie pas de valeur, vous pouvez toujours utiliser le chaînage facultatif à cette fin.
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("无法输出房间号") }
Le résultat de l'exécution du programme ci-dessus est :
无法输出房间号
Utilisez l'instruction if pour vérifier si la méthode printNumberOfRooms peut être appelée avec succès : Si la méthode est appelée avec succès via la chaîne facultative, le la valeur de retour implicite de printNumberOfRooms sera Is Void, en cas d'échec, nul sera renvoyé.
Utiliser le chaînage facultatif pour appeler un script d'indice
Vous pouvez utiliser le chaînage facultatif pour essayer d'obtenir la valeur du script d'indice et vérifier si l'appel au script d'indice a réussi, cependant, vos scripts d'indice ne peuvent pas être définis via un chaînage facultatif.
Exemple 1
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("无法检索到房间") }
Le résultat de l'exécution du programme ci-dessus est :
无法检索到房间
Dans l'appel du script d'indice, le point d'interrogation en chaîne facultatif suit directement circname.print, dans l'indice avant les parenthèses du script, car circname.print est la valeur facultative que la chaîne facultative tente d'obtenir.
Instance 2
Créez une instance Residence pour john.residence, et il y a une ou plusieurs instances Room dans son tableau Rooms, vous pouvez ensuite utiliser la chaîne facultative pour la télécharger via le script Residence Subscript pour obtenir l'instance dans le tableau Rooms :
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("无法检索到房间") }
Le résultat de sortie de l'exécution du programme ci-dessus est :
第一个房间名为客厅
Accédez à l'indice
<🎜 via le lien facultatif call >Grâce aux appels de lien facultatifs, nous pouvons utiliser des indices pour lire ou écrire des valeurs facultatives et déterminer si l'appel d'indice réussit. Instanceclass 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("无法检索到房间")
}
Le résultat de sortie de l'exécution du programme ci-dessus est :第一个房间名为客厅
Accès à l'indice de type facultatifSi l'indice est renvoyé, il peut s'agir d'une valeur de type nulle, telle que l'indice clé du dictionnaire dans Swift. Vous pouvez lier la valeur de retour nullable d'un indice en plaçant un point d'interrogation après la parenthèse fermante de l'indice :
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]
L'exemple ci-dessus définit un tableau testScores, qui contient deux paires clé-valeur et mappe la clé de type String à un tableau d'entiers.
Cet exemple utilise des appels de chaînage facultatifs pour définir le premier élément du tableau "Dave" à 91, +1 le premier élément du tableau "Bev", puis essaie de définir le premier élément du tableau "Brian " tableau Un élément est défini sur 72.
Les deux premiers appels réussissent car ces deux clés existent. Mais la clé « Brian » n’existe pas dans le dictionnaire, donc le troisième appel échoue.
Connectez des liens multicouches
Vous pouvez connecter des chaînes facultatives multicouches ensemble et vous pouvez exploiter des méthodes d'attributs de niveau inférieur et des scripts d'indice dans le modèle. Cependant, une chaîne facultative à plusieurs niveaux ne peut pas ajouter plus de niveaux que les valeurs facultatives déjà renvoyées.
Si vous essayez d'obtenir une valeur Int via un chaînage facultatif, quel que soit le nombre de niveaux de chaînage utilisés, le résultat sera toujours Int ?. De même, si vous essayez d'obtenir une valeur Int? via un chaînage facultatif, le résultat sera toujours un Int?, quel que soit le nombre de niveaux de chaînage utilisés.
Exemple 1
L'exemple suivant tente d'obtenir l'attribut rue de l'adresse dans l'attribut de résidence de John. Deux couches de chaînes facultatives sont utilisées ici pour connecter les attributs de résidence et d'adresse, qui sont tous deux de types facultatifs :
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("不能检索地址") }
Le résultat de sortie de l'exécution du programme ci-dessus est :
不能检索地址
Exemple 2
Si vous définissez une instance de Address comme valeur de john.residence.address et définissez une valeur réelle pour l'attribut street de l'adresse, vous pouvez obtenir cette valeur d'attribut via plusieurs chaînes facultatives.
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("无法检索房间") }
Le résultat de sortie de l'exemple ci-dessus est :
第一个房间是客厅
Fonctions de lien qui renvoient des valeurs facultatives
Nous pouvons également appeler la valeur de retour nullable via une valeur de liens facultative , et peut continuer à enchaîner des valeurs facultatives.
Exemple
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("未指定房间号") }
Le résultat de l'exécution du programme ci-dessus est :
未指定房间号