生活随笔
收集整理的這篇文章主要介紹了
Swift之深入解析可选链的功能和使用
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
一、什么是可選鏈?
可選鏈(Optional Chaining)是一種可以請求和調用屬性、方法和子腳本的過程,用于請求或調用的目標可能為nil。 可選鏈返回兩個值: 多次請求或調用可以被鏈接成一個鏈,如果任意一個節點為 nil 將導致整條鏈失效。
二、可選鏈可替代強制解析
通過在屬性、方法、或下標腳本的可選值后面放一個問號(?),即可定義一個可選鏈。
可選鏈 ‘?’感嘆號(!)強制展開方法,屬性,下標腳本可選鏈 ? 放置于可選值后來調用方法,屬性,下標腳本 ! 放置于可選值后來調用方法,屬性,下標腳本來強制展開值 當可選為 nil 輸出比較友好的錯誤信息 當可選為 nil 時強制展開執行錯誤
① 使用感嘆號(!)可選鏈
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
想使用感嘆號(!)強制解析獲得這個人 residence 屬性 numberOfRooms 屬性值,將會引發運行時錯誤,因為這時沒有可以供解析的 residence 值。
② 使用問號(?)可選鏈
class Person { var residence
: Residence ?
} class Residence { var numberOfRooms
= 1
} let john
= Person ( )
if let roomCount
= john
. residence
? . numberOfRooms
{ print ( "John 的房間號為 \( roomCount) 。" )
} else { print ( "不能查看房間號" )
}
不能查看房間號
因為這種嘗試獲得 numberOfRooms 的操作有可能失敗,可選鏈會返回 Int? 類型值,或者稱作“可選Int”。當 residence 是空的時候,選擇 Int 將會為空,因此會出現無法訪問 numberOfRooms 的情況。 要注意的是,即使 numberOfRooms 是非可選 Int(Int?)時這一點也成立。只要是通過可選鏈的請求就意味著最后 numberOfRooms 總是返回一個 Int? 而不是 Int。
三、為可選鏈定義模型類
可以使用可選鏈來多層調用屬性、方法和下標腳本,這可以利用它們之間的復雜模型來獲取更底層的屬性,并檢查是否可以成功獲取此類底層屬性。 如下所示,定義了四個模型類,其中包括多層可選鏈:
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 ( "房間號為 \( 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 } }
}
四、通過可選鏈調用方法
可以使用可選鏈的來調用可選值的方法并檢查方法調用是否成功,即使這個方法沒有返回值,依然可以使用可選鏈來達成這一目的。 如下所示:
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 ( "房間號為 \( 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 ( ( john
. residence
? . printNumberOfRooms ( ) ) != nil ) { print ( "輸出房間號" )
} else { print ( "無法輸出房間號" )
}
無法輸出房間號
使用 if 語句來檢查是否能成功調用 printNumberOfRooms 方法:如果方法通過可選鏈調用成功,printNumberOfRooms 的隱式返回值將會是 Void,如果沒有成功,將返回 nil。
五、使用可選鏈調用下標腳本
可以使用可選鏈來嘗試從下標腳本獲取值并檢查下標腳本的調用是否成功,然而,不能通過可選鏈來設置下標腳本。 如下所示:
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 ( "房間號為 \( 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 firstRoomName
= john
. residence
? [ 0 ] . name
{ print ( "第一個房間名 \( firstRoomName) ." )
} else { print ( "無法檢索到房間" )
}
無法檢索到房間
在下標腳本調用中可選鏈的問號直接跟在 john.residence 的后面,在下標腳本括號的前面,因為 john.residence 是可選鏈試圖獲得的可選值。 如下所示,創建一個 Residence 實例給 john.residence,且在他的 rooms 數組中有一個或多個 Room 實例,那么可以使用可選鏈通過 Residence 下標腳本來獲取在 rooms 數組中的實例:
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 ( "房間號為 \( 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 ( )
let johnsHouse
= Residence ( )
johnsHouse
. rooms
. append ( Room ( name
: "客廳" ) )
johnsHouse
. rooms
. append ( Room ( name
: "廚房" ) )
john
. residence
= johnsHouse
let johnsAddress
= Address ( )
johnsAddress
. buildingName
= "The Larches"
johnsAddress
. street
= "Laurel Street"
john
. residence
! . address
= johnsAddress
if let johnsStreet
= john
. residence
? . address
? . street
{ print ( "John 所在的街道是 \( johnsStreet) 。" )
} else { print ( "無法檢索到地址。 " )
}
John 所在的街道是
Laurel Street 。
六、通過可選鏈接調用來訪問下標
通過可選鏈接調用,我們可以用下標來對可選值進行讀取或寫入,并且判斷下標調用是否成功。 如下所示:
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 ( "房間號為 \( 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 ( ) 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 ( "無法檢索到房間" )
}
第一個房間名為客廳
七、訪問可選類型的下標
如果下標返回可空類型值,比如 Swift 中 Dictionary 的 key 下標,可以在下標的閉合括號后面放一個問號來鏈接下標的可空返回值。 如下所示,定義了一個 testScores 數組,包含了兩個鍵值對, 把 String 類型的 key 映射到一個整形數組:
var testScores
= [ "Dave" : [ 86 , 82 , 84 ] , "Bev" : [ 79 , 94 , 81 ] ]
testScores
[ "Dave" ] ? [ 0 ] = 91
testScores
[ "Bev" ] ? [ 0 ] ++
testScores
[ "Brian" ] ? [ 0 ] = 72
用可選鏈接調用把"Dave"數組中第一個元素設為 91,把"Bev"數組的第一個元素 +1,然后嘗試把"Brian"數組中的第一個元素設為 72。 前兩個調用是成功的,因為這兩個 key 存在,但是 key"Brian"在字典中不存在,所以第三個調用失敗。
八、連接多層鏈接
可以將多層可選鏈連接在一起,可以掘取模型內更下層的屬性方法和下標腳本,然而多層可選鏈不能再添加比已經返回的可選值更多的層。 如果試圖通過可選鏈獲得 Int 值,不論使用了多少層鏈接返回的總是 Int?。相似的,如果試圖通過可選鏈獲得 Int?值,不論使用了多少層鏈接返回的總是 Int?。 如下所示,試圖獲取 john 的 residence 屬性里的 address 的 street 屬性,使用了兩層可選鏈來聯系 residence 和 address 屬性,它們兩者都是可選類型:
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 ( "房間號為 \( 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 johnsStreet
= john
. residence
? . address
? . street
{ print ( "John 的地址為 \( johnsStreet) ." )
} else { print ( "不能檢索地址" )
}
不能檢索地址
如果為 Address 設定一個實例來作為 john.residence.address 的值,并為 address 的 street 屬性設定一個實際值,可以通過多層可選鏈來得到這個屬性值。
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 ( "無法檢索房間" )
}
第一個房間是客廳
九、對返回可選值的函數進行鏈接
還可以通過可選鏈接來調用返回可空值的方法,并且可以繼續對可選值進行鏈接。 如下所示:
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 ( "房間號為 \( 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 john
. residence
? . printNumberOfRooms ( ) != nil { print ( "指定了房間號)" )
} else { print ( "未指定房間號" )
}
未指定房間號
總結
以上是生活随笔 為你收集整理的Swift之深入解析可选链的功能和使用 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。