一、#available和@available
@available是編譯時(shí)期作用,#available是運(yùn)行時(shí)起作用。
1. @available
在Swift中用于修飾一個(gè)類型、擴(kuò)展、協(xié)議、方法、屬性,用來(lái)表達(dá)它的可用性,比如平臺(tái)、操作系統(tǒng)、是否廢棄、已經(jīng)不可用,例子如下:
extension String {
// 1.表示iOS 11.0及以上可用,除操作系統(tǒng)外沒(méi)有其他條件,后面參數(shù)寫*
@available(iOS 11.0, *)
// 2.除了操作系統(tǒng)外還有其他的條件,這個(gè)時(shí)候平臺(tái)和系統(tǒng)版本號(hào)要分開(kāi)。
// 如下表示,iOS 11后已經(jīng)廢棄,方法新命名為stringxxx
// iOS表示是iOS平臺(tái)
// introduced表示從那個(gè)操作系統(tǒng)版本號(hào)開(kāi)始
// deprecated的作用:表示已經(jīng)廢棄如果在iOS11之后使用會(huì)有警告'string(date:)' is deprecated in iOS:
// renamed的作用是警告時(shí)有提示:renamed to 'stringxxx' Use 'stringxxx' instead
@available(iOS, introduced: 11.0, deprecated, renamed: "stringxxx")
// 3.如果對(duì)所有平臺(tái)和系統(tǒng)版本都起作用,則第一個(gè)參數(shù)寫*
// @available(*, deprecated, renamed: "abcd")
// 4.如果要添加更加詳細(xì)的描述,可以使用message參數(shù):
// message參數(shù)可以添加對(duì)該方法的描述
// unavailable表示該方法已經(jīng)不可用,使用時(shí)會(huì)報(bào)錯(cuò),報(bào)錯(cuò)信息為message的值
@available(*, message: "withUnretained has been deprecated for Driver. Consider using `drive(with:onNext:onCompleted:onDisposed:)`, instead", unavailable)
func string(date: Int) -> String? {
return nil
}
}
2. #available
用于執(zhí)行過(guò)程中的平臺(tái)和操作系統(tǒng)條件判斷,在OC中不能使用。
if #available(iOS 13.0, *) {
actionBackgroundColor = UIColor.systemRed
} else {
actionBackgroundColor = #colorLiteral(red: 1, green: 0.2352941176, blue: 0.1882352941, alpha: 1)
}
二、#colorLiteral
view.backgroundColor = #colorLiteral(red: 1, green: 0.2352941176, blue: 0.1882352941, alpha: 1)
這樣寫在Xcode中會(huì)顯示這個(gè)顏色,并且點(diǎn)擊顏色可以自己選擇其它顏色,這讓我們?cè)O(shè)置的顏色時(shí)很直觀。
三、mutating
值類型(枚舉、結(jié)構(gòu)體)中寫方法時(shí),如果涉及到修改自身內(nèi)存時(shí),需要使用mutating 修飾。
留有疑問(wèn)?那么mutating修飾前后,該方法有什么本質(zhì)區(qū)別?為什么要設(shè)計(jì)mutating?
簡(jiǎn)述:mutating本質(zhì)上是給self參數(shù)加了inout修飾。
- 值類型的方法中默認(rèn)有
self作為參數(shù),參數(shù)是let類型的值類型,不可修改,所以方法涉及修改自身值時(shí)會(huì)報(bào)錯(cuò); - 當(dāng)使用
mutating修飾方法之后, 編譯器背后把參數(shù)變?yōu)?code>inout修飾了,參數(shù)self變?yōu)?code>var,并且inout是指針傳遞,所以可以修改。
詳述:Swift關(guān)鍵字(mutating)
四、inout
方法的參數(shù)是值類型時(shí),如果方法中涉及到修改該參數(shù)的內(nèi)存(如存儲(chǔ)屬性)時(shí),需要加inout修飾。
func incrementChecked(_ i: inout Int) throws -> Int {
if i == Int.max {
throw RxError.overflow
}
defer { i += 1 }
return i
}
var aaa = 10
let bbb = try? incrementChecked(&aaa)
print("aaa = \(aaa)", "bbb = \(bbb!)") // aaa = 11 bbb = 10
inout參數(shù)的本質(zhì):
- 如果實(shí)參有物理內(nèi)存地址,且沒(méi)有設(shè)置屬性觀察器:直接將實(shí)參的內(nèi)存地址傳入函數(shù)。
- 如果實(shí)參是計(jì)算屬性或者設(shè)置了屬性觀察器:采取了
Copy In Copy Out的策略,
- 調(diào)用該函數(shù)時(shí),先復(fù)制實(shí)參的值產(chǎn)生副本『參數(shù)是傳計(jì)算屬性時(shí)會(huì)調(diào)用get』。
- 將副本的內(nèi)存地址傳入函數(shù),在函數(shù)內(nèi)部可以修改副本的值。
- 函數(shù)返回后再將副本的值覆蓋實(shí)參的值『參數(shù)是計(jì)算屬性會(huì)調(diào)set』
五、defer、do、fatalError、@discardableResult、final
@discardableResult // 作用:外部調(diào)用時(shí)未使用結(jié)果不會(huì)有警告
func testKeys() -> Int {
defer {
print("函數(shù)結(jié)束之前會(huì)執(zhí)行的代碼塊, 包括向上throws錯(cuò)誤,但程序執(zhí)行某一句代碼奔潰除外")
}
fatalError("測(cè)試拋出終止執(zhí)行的錯(cuò)誤")
do {// 局部作用域,程序會(huì)順序執(zhí)行,這里可以用來(lái)寫一個(gè)邏輯相對(duì)獨(dú)立的代碼塊
print("do")
}
return 10
}
// final只能用于類中,修飾的方法、屬性,不能被重寫;
// final修飾的類不能被繼承