ห่วงโซ่ตัวเลือกสวิฟท์
ห่วงโซ่เป็นตัวเลือก (ตัวเลือก Chaining) เป็นวิธีการขอและเรียกร้องทรัพย์สินวิธีการกระบวนการและย่อยสคริปต์เรียกร้องให้มีการร้องขอเป้าหมายหรืออาจจะเป็นศูนย์
ห่วงโซ่ไม่บังคับส่งกลับสองค่า:
ถ้าเป้าหมายมีค่าโทรสำเร็จค่าส่งกลับ
ถ้าเป้าหมายเป็นศูนย์โทรจะกลับศูนย์
การร้องขอหรือหลายสายสามารถเชื่อมโยงในห่วงโซ่ถ้าโหนดใด ๆ ที่เป็นความล้มเหลวของศูนย์จะทำให้เกิดห่วงโซ่ทั้งหมด
ทางเลือกที่ห่วงโซ่เป็นตัวเลือกบังคับให้แก้ไข
โดยการผนวกคุณสมบัติของวิธีการหรือสคริปต์ดัชนีค่าตัวเลือกใส่เครื่องหมายคำถาม (?) คุณสามารถกำหนดโซ่ตัวเลือก
ห่วงโซ่ตัวเลือก '?' | เครื่องหมายอัศเจรีย์ (!) ในการบังคับวิธีการขยายตัวคุณสมบัติสคริปต์ห้อยโซ่ตัวเลือก |
? ค่าตัวเลือกที่วางอยู่บนต่อมาเรียกวิธีคุณสมบัติสคริปต์ห้อย | ! ค่าตัวเลือกที่วางอยู่บนวิธีการโทรต่อมาคุณสมบัติสคริปต์ห้อยที่จะขยายค่าบังคับ |
เมื่อการส่งออกที่ไม่จำเป็นเป็นศูนย์ข้อความผิดพลาดที่เป็นมิตรมากขึ้น | เมื่อการขยายตัวที่ไม่จำเป็นที่จะไม่มีข้อผิดพลาดการดำเนินการบังคับ |
ใช้เครื่องหมายอัศเจรีย์ (!) ตัวอย่างของห่วงโซ่ตัวเลือก
class Person { var residence: Residence? } class Residence { var numberOfRooms = 1 } let john = Person() //将导致运行时错误 let roomCount = john.residence!.numberOfRooms
เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:
fatal error: unexpectedly found nil while unwrapping an Optional valueต้องการที่จะใช้เครื่องหมายอัศเจรีย์ (!) ในการบังคับแยกของมูลค่า numberOfRooms อสังหาริมทรัพย์ที่อยู่อาศัยนี้คนก็จะโยนความผิดพลาด runtime แล้วเพราะไม่มีค่าสามารถนำมาใช้สำหรับการอยู่อาศัยได้รับการแก้ไข
ใช้เครื่องหมายอัศเจรีย์ (!) ตัวอย่างของห่วงโซ่ตัวเลือก
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("不能查看房间号") }
เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:
不能查看房间号
เนื่องจากการดำเนินความพยายามเหล่านี้อาจล้มเหลว numberOfRooms โซ่ตัวเลือกจะกลับ Int? ค่าชนิดหรือที่เรียกว่า "ตัวเลือก Int" เมื่อที่อยู่อาศัยเป็นที่ว่างเปล่าเมื่อ (ตัวอย่าง) เลือก Int จะว่างเปล่าดังนั้นจะไม่มีกรณีของ numberOfRooms เข้าถึง
มันควรจะตั้งข้อสังเกตว่าแม้ numberOfRooms ไม่เลือก Int (int?) เมื่อเป็นเช่นนี้ยังเป็นจริง ตราบใดที่ขอเป็นโซ่ตัวเลือกโดยวิธีการของ numberOfRooms สุดท้ายเสมอกลับ Int? แทน Int
รูปแบบการเรียนถูกกำหนดให้เป็นห่วงโซ่ที่เป็นตัวเลือก
คุณสามารถใช้โซ่เป็นตัวเลือกคุณสมบัติหลายโทรวิธีการและสคริปต์ดัชนี นี้จะช่วยให้คุณสามารถใช้โมเดลที่ซับซ้อนระหว่างพวกเขาที่จะได้รับคุณสมบัติพื้นฐานมากขึ้นและตรวจสอบว่าคุณสามารถได้รับคุณสมบัติพื้นฐานเช่น
ตัวอย่าง
รุ่นกำหนดสี่ชั้นเรียนรวมทั้งห่วงโซ่หลายตัวเลือก:
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 } } }
ด้วยวิธีการห่วงโซ่ตัวเลือกการโทร
วิธีที่จะก่อให้เกิดการตั้งค่าทางเลือกที่คุณสามารถใช้โซ่เป็นตัวเลือกและตรวจสอบวิธีการเรียกก็ประสบความสำเร็จ แม้ว่าวิธีนี้ไม่คืนค่าคุณยังสามารถใช้โซ่เป็นตัวเลือกเพื่อให้บรรลุวัตถุประสงค์นี้
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("无法输出房间号") }
เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:
无法输出房间号
ถ้าใช้งบเพื่อตรวจสอบว่าประสบความสำเร็จในการเรียกวิธี printNumberOfRooms: ถ้าเรียกวิธีการประสบความสำเร็จผ่านห่วงโซ่เลือก printNumberOfRooms ค่าตอบแทนโดยนัยจะถือเป็นโมฆะถ้าไม่ประสบความสำเร็จก็จะส่งกลับศูนย์
โดยใช้โซ่เป็นตัวเลือกสคริปต์โทรห้อย
คุณสามารถใช้โซ่เป็นตัวเลือกเพื่อให้ได้รับค่าจากสคริปต์มาตรฐานและตรวจสอบสคริปต์โทรห้อยต่อไปคือการประสบความสำเร็จอย่างไรก็ตามคุณไม่สามารถตั้งสคริปต์ดัชนีห่วงโซ่ตัวเลือก
ตัวอย่างที่ 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("无法检索到房间") }
เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:
无法检索到房间
สคริปต์มาตรฐานต่อไปเรียกว่าห่วงโซ่ตัวเลือกโดยตรงหลังเครื่องหมายคำถาม circname.print สคริปต์มาตรฐานต่อไปวงเล็บด้านหน้าเพราะ circname.print ห่วงโซ่ไม่จำเป็นพยายามที่จะได้รับค่าตัวเลือก
ตัวอย่างที่ 2
ตัวอย่างของกรณีที่จะสร้าง john.residence Residence และหนึ่งหรือมากกว่าหนึ่งอินสแตนซ์ของอาร์เรย์ห้องแล้วคุณสามารถใช้โซ่เป็นตัวเลือกที่จะได้รับห้องพักในกรณีอาร์เรย์โดย Residence ห้อยสคริปต์:
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("无法检索到房间") }
เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:
第一个房间名为客厅
ในการเข้าถึงดัชนีผ่านสาย link ตัวเลือก
ด้วยสาย 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() 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("无法检索到房间") }
เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:
第一个房间名为客厅
การเข้าถึงเลือกประเภทของดัชนี
หากดัชนีอาจกลับประเภทค่า null เช่นสวิฟท์ในพจนานุกรมของดัชนีที่สำคัญ คุณสามารถปิดเป้าหมายต่อไปในวงเล็บหลังเครื่องหมายคำถามใส่ลิงค์กับเรื่องภายใต้ 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]
ตัวอย่างข้างต้นกำหนดอาร์เรย์ testScores มีสองคู่ค่าคีย์ที่สำคัญชนิดสตริงถูกแมปไปอาร์เรย์จำนวนเต็ม
ตัวอย่างนี้สายที่มีการเชื่อมโยงที่ไม่จำเป็นที่จะ "เดฟ" ตั้งค่าเป็นองค์ประกอบแรกของอาร์เรย์ 91 องค์ประกอบแรก +1 "เบฟ" อาร์เรย์และจากนั้นพยายามที่จะ "ไบรอัน" องค์ประกอบแรกของอาร์เรย์ถูกตั้งไว้ที่ 72 .
สองสายแรกที่ประสบความสำเร็จเพราะการปรากฏตัวของทั้งสองคีย์ แต่ที่สำคัญ "ไบรอัน" ในพจนานุกรมไม่ได้อยู่เพื่อให้สายที่สามล้มเหลว
การเชื่อมต่อแบบมัลติลิงค์
คุณสามารถเข้าด้วยกันหลายชั้นเลือกที่อาจจะขุดภายในคุณสมบัติรุ่นต่อไปลงวิธีการและสคริปต์ดัชนี แต่ตัวเลือกหลายห่วงโซ่สามารถเพิ่มอัตราส่วนค่าตัวเลือกได้กลับเลเยอร์เพิ่มเติม
ถ้าคุณพยายามที่จะได้รับผ่านตัวเลือกห่วงโซ่คุณค่า Int โดยไม่คำนึงถึงวิธีการหลายชั้นเชื่อมโยงเสมอกลับ Int? ในทำนองเดียวกันถ้าคุณพยายามที่จะได้รับผ่านห่วงโซ่ตัวเลือก Int? ราคาโดยไม่คำนึงถึงวิธีการหลายชั้นเชื่อมโยงเสมอกลับ Int?
ตัวอย่างที่ 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 johnsStreet = john.residence?.address?.street { print("John 的地址为 \(johnsStreet).") } else { print("不能检索地址") }
เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:
不能检索地址
ตัวอย่างที่ 2
ถ้าคุณตั้งค่าตัวอย่างที่จะอยู่เป็น john.residence.address คุ้มค่าและการตั้งค่าสำหรับที่อยู่สถานที่จริงของทรัพย์สินที่คุณสามารถโซ่หลายชั้นจะได้รับนี้ค่าแอตทริบิวต์ตัวเลือก
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("无法检索房间") }
เอาท์พุทตัวอย่างข้างต้นคือ
第一个房间是客厅
ฟังก์ชั่นที่ไม่จำเป็นของความคุ้มค่าของการเชื่อมโยงกลับมาที่
นอกจากนี้เรายังสามารถเรียกวิธีส่งกลับค่า null โดยการเชื่อมโยงที่ไม่จำเป็นและคุณสามารถดำเนินการต่อในการตั้งค่าการเชื่อมโยงทางเลือก
ตัวอย่าง
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("未指定房间号") }
เอาท์พุทการทำงานของโปรแกรมข้างต้นเป็น:
未指定房间号