Rangkaian pilihan pantas
Perangkaian Pilihan ialah proses yang boleh meminta dan memanggil sifat, kaedah dan subskrip Sasaran untuk meminta atau membuat panggilan mungkin tiada.
Rantai pilihan mengembalikan dua nilai:
Jika sasaran mempunyai nilai, panggilan akan berjaya dan mengembalikan nilai tersebut
Jika sasaran adalah sifar, panggilan akan kembali sifar
Berbilang permintaan atau panggilan boleh dipautkan ke dalam rantaian Jika mana-mana nod sifar, keseluruhan rantai akan gagal.
Perantaian pilihan boleh menggantikan penghuraian paksa
Pilihan boleh ditakrifkan dengan meletakkan tanda soal (?) selepas nilai pilihan bagi harta, kaedah atau rantaian skrip subskrip.
可选链 '?' | 感叹号(!)强制展开方法,属性,下标脚本可选链 |
? 放置于可选值后来调用方法,属性,下标脚本 | ! 放置于可选值后来调用方法,属性,下标脚本来强制展开值 |
当可选为 nil 输出比较友好的错误信息 | 当可选为 nil 时强制展开执行错误 |
Gunakan tanda seru (!) contoh rantai pilihan
class Person { var residence: Residence? } class Residence { var numberOfRooms = 1 } let john = Person() //将导致运行时错误 let roomCount = john.residence!.numberOfRooms
Hasil output pelaksanaan program di atas ialah:
fatal error: unexpectedly found nil while unwrapping an Optional value
Gunakan tanda seru (!) contoh rantai pilihan
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("不能查看房间号") }
Hasil output pelaksanaan program di atas ialah:
不能查看房间号
Disebabkan oleh operasi ini cuba mendapatkan numberOfRooms Jika gagal, rantai pilihan akan mengembalikan nilai jenis Int?, juga dikenali sebagai "Int pilihan". Apabila kediaman kosong (contoh di atas), Int yang dipilih akan kosong, jadi numberOfRooms tidak akan dapat diakses.
Perhatikan bahawa ini berlaku walaupun numberOfRooms ialah Int bukan pilihan (Int?). Selagi permintaan itu melalui rangkaian pilihan, ini bermakna numberOfRooms terakhir sentiasa mengembalikan Int dan bukannya Int.
Tentukan kelas model untuk rantai pilihan
Anda boleh menggunakan rantai pilihan untuk memanggil sifat, kaedah dan skrip subskrip pada berbilang peringkat. Ini membolehkan anda memanfaatkan model kompleks di antara mereka untuk mendapatkan sifat peringkat rendah dan menyemak sama ada anda boleh berjaya mendapatkan sifat peringkat rendah tersebut.
Instance
mentakrifkan empat kelas model, yang termasuk berbilang lapisan rantai pilihan:
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 } } }
Kaedah panggilan melalui rantai pilihan
Anda boleh menggunakan rantaian pilihan untuk memanggil kaedah pada nilai pilihan dan semak sama ada panggilan kaedah berjaya. Walaupun kaedah ini tidak mengembalikan nilai, anda masih boleh menggunakan rantaian pilihan untuk tujuan ini.
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("无法输出房间号") }
Output pelaksanaan program di atas ialah:
无法输出房间号
Gunakan pernyataan if untuk menyemak sama ada kaedah printNumberOfRooms boleh berjaya dipanggil: Jika kaedah itu berjaya dipanggil melalui rantai pilihan, nilai pulangan tersirat printNumberOfRooms akan menjadi Is Void, jika tidak berjaya, tiada akan dikembalikan.
Menggunakan rantaian pilihan untuk memanggil skrip subskrip
Anda boleh menggunakan rantaian pilihan untuk cuba mendapatkan nilai daripada skrip subskrip dan semak sama ada panggilan ke skrip subskrip berjaya, walau bagaimanapun, skrip Subskrip anda tidak boleh ditetapkan melalui rantaian pilihan.
Contoh 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("无法检索到房间") }
Hasil output pelaksanaan program di atas ialah:
无法检索到房间
Tanda soal rantai pilihan dalam panggilan skrip subskrip terus mengikuti circname.print, dalam subskrip sebelum kurungan skrip, kerana circname.print ialah nilai pilihan yang cuba diperolehi oleh rantai pilihan.
Instance 2
Buat instance Residence untuk john.residence, dan terdapat satu atau lebih tika Room dalam susunan biliknya, kemudian anda boleh menggunakan rantai pilihan untuk memuat turunnya melalui skrip Residence Subscript untuk mendapatkan contoh dalam tatasusunan bilik:
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("无法检索到房间") }
Hasil output pelaksanaan program di atas ialah:
第一个房间名为客厅
Akses subskrip
<🎜 melalui pautan pilihan panggilan >Melalui panggilan pautan pilihan, kami boleh menggunakan subskrip untuk membaca atau menulis nilai pilihan, dan menentukan sama ada panggilan subskrip berjaya. Contohclass 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("无法检索到房间")
}
Hasil output pelaksanaan program di atas ialah:第一个房间名为客厅
Mengakses subskrip jenis pilihanJika subskrip dikembalikan, ia boleh menjadi nilai Jenis nol, seperti subskrip utama Kamus dalam Swift. Anda boleh memautkan nilai pulangan nullable subskrip dengan meletakkan tanda soal selepas kurungan penutup subskrip:
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]
Contoh di atas mentakrifkan tatasusunan testScores, yang mengandungi dua pasangan nilai kunci dan memetakan kekunci jenis Rentetan kepada tatasusunan integer.
Contoh ini menggunakan panggilan rantai pilihan untuk menetapkan elemen pertama dalam tatasusunan "Dave" kepada 91, +1 elemen pertama dalam tatasusunan "Bev", dan kemudian cuba untuk menetapkan elemen pertama dalam "Brian " tatasusunan Satu elemen ditetapkan kepada 72.
Dua panggilan pertama berjaya kerana dua kekunci ini wujud. Tetapi kunci "Brian" tidak wujud dalam kamus, jadi panggilan ketiga gagal.
Sambungkan pautan berbilang lapisan
Anda boleh menyambung rantai pilihan berbilang lapisan bersama-sama dan anda boleh melombong kaedah atribut peringkat rendah dan skrip subskrip dalam model. Walau bagaimanapun, rantai pilihan berbilang peringkat tidak boleh menambah lebih banyak tahap daripada nilai pilihan yang telah dikembalikan.
Jika anda cuba mendapatkan nilai Int melalui rantaian pilihan, tidak kira berapa tahap rantaian digunakan, hasilnya akan sentiasa Int?. Begitu juga, jika anda cuba mendapatkan nilai Int melalui rantaian pilihan, hasilnya akan sentiasa menjadi Int?, tidak kira berapa tahap rantaian digunakan.
Contoh 1
Contoh berikut cuba mendapatkan atribut jalanan alamat dalam atribut kediaman john. Dua lapisan rantai pilihan digunakan di sini untuk menyambungkan sifat kediaman dan alamat, kedua-duanya adalah jenis pilihan:
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("不能检索地址") }
Hasil output pelaksanaan program di atas ialah:
不能检索地址
Contoh 2
Jika anda menetapkan contoh Alamat sebagai nilai john.residence.address, dan menetapkan nilai sebenar untuk atribut jalan alamat, anda boleh mendapatkan nilai atribut ini melalui berbilang rantai pilihan.
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("无法检索房间") }
Hasil keluaran contoh di atas ialah:
第一个房间是客厅
Fungsi pautan yang mengembalikan nilai pilihan
Kita juga boleh memanggil nilai nullable pulangan melalui nilai pautan pilihan , dan boleh terus merantai nilai pilihan.
Contoh
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("未指定房间号") }
Hasil output pelaksanaan program di atas ialah:
未指定房间号