最新更新
1、在 Swift 4.2 里可以使用 CaseIterable 協議,讓編譯器自動為我們創建 allCases:
//這個allCases的自動合成僅替換沒有參數的case值, 但是如果需要你需要所有case值, 可以重寫allCases屬性自己添加
//如果有枚舉項標記為unavailable,則默認無法合成allCases,只能依靠自己來手動合成
enum LogLevel: CaseIterable {
case warn
case info
}
for level in LogLevel.allCases {
print(level)
}
2、雖然 Swift 4.2 里最重要的是 ABI 兼容性的提升,但還是實現了一套隨機數的 API:
let randomIntFrom0To10 = Int.random(in: 0 ..< 10)
let randomFloat = Flow.random(in: 0 ..< 1)
let greetings = ["hey", "hi", "hello", "hola"]
print(greetings.randomElement()!)
let randomlyOrderGreetings = greetings.shuffled()
print(randomlyOrderedGreetings)
var numbers = [1, 2, 3, 4, 5, 6]
let shuffledNumbers = numbers.shuffled()
// shuffledNumbers == [6, 1, 3, 2, 5, 4]
// numbers == [1, 2, 3, 4, 5, 6]
numbers.shuffle()
// numbers == [4, 2, 6, 5, 1, 3]
3、Swift 4.2 新增了一個判斷庫是否能導入的宏:
#if canImport(UIKit)
import UIKit
typealias Color = UIColor
#elseif canImport(AppKit)
import AppKit
typealias Color = NSColor
#else
#error("Unsupported platform")
#endif
// Swift 4.2
//判斷是否為模擬器環境的代碼:
#if hasTargetEnviroment(simulator)
...
#endif
4、Bool類型取反:.toggle()
5、檢查序列元素是否符合條件:
//判斷數組的所有元素是否全部大于85
let scores = [86, 88, 95, 92]
//返回一個BOOL
let passed = scores.allSatisfy({ $0 > 85 })
print(passed)
//輸出: true
6、自定義運算符
前置運算符 prefix
中間運算符 infix
后置運算符 postfix
以前整理
1、where關鍵字指定額外的要求,可以用來設置約束條件、限制類型
2、在方法的func關鍵字之前加上關鍵字static或者class都可以用于指定類方法.不同的是用class關鍵字指定的類方法可以被子類重寫,但是用static關鍵字指定的類方法是不能被子類重寫的,被static指定的類方法包含final(不可更改的)關鍵字的特性--防止被重寫.
3、deinit屬于析構函數
析構函數(destructor) 與構造函數相反,當對象結束其生命周期時(例如對象所在的函數已調用完畢),系統自動執行析構函數
和OC中的dealloc 一樣的
4、Swift中mutating關鍵字:為了能夠在實例方法中修改屬性值,可以在方法定義前添加關鍵字mutating;值類型的實例方法中,也可以直接修改self屬性值。
5、代理繼承的父類NSObjectProtocol的時候,判斷代理是否實現某個方法responds(to: #selector()能提示處理,繼承自class則沒法判斷
6、let content = (newSrting as NSString).addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
7、打印內存地址:
withUnsafePointer(to: &subArr) { p in
print(p)
}
8、數組中獲取子數組
let arr = [1,2,3,4,5]
//是個切片數組和數組之間可以轉化
let arrSlice = arr[0..<3]
let subArr = Array(arrSlice)
9、多繼承,運行時方法
10、Swift 同時也提供兩個等價運算符( === 和 !== ),你可以使用它們來判斷兩個對象的引用是否相同。
11、Swift 標準庫包含的元組比較運算符僅支持小于七個元素的元組。要比較擁有七個或者更多元素的元組,你必須自己實現比較運算符。
12、Swift 的 String類型橋接到了基礎庫中的 NSString類。Foundation 同時也擴展了所有 NSString 定義的方法給 String 。也就是說,如果你導入 Foundation ,就可以在 String 中訪問所有的 NSString 方法,無需轉換格式。
13、子字符串并不適合長期保存——因為它們重用了原字符串的內存,只要這個字符串有子字符串在使用中,那么這個字符串就必須一直保存在內存里。
14、hashValue 的實質
15、 ? 使用 intersection(_:)方法來創建一個只包含兩個合集共有值的新合集;
- 使用 symmetricDifference(_:)方法來創建一個只包含兩個合集各自有的非共有值的新合集;
- 使用 union(_:)方法來創建一個包含兩個合集所有值的新合集;
- 使用 subtracting(_:)方法來創建一個兩個合集當中不包含某個合集值的新合集。
16、使用 stride(from:to:by:) 函數來跳過不想要的標記。stride(from:through:by:)(閉區間)
17、continue 語句告訴循環停止正在做的事情并且再次從頭開始循環的下一次遍歷。它是說“我不再繼續當前的循環遍歷了”而不是離開整個的循環。
18、如果你確實需要 C 風格的貫穿行為,你可以選擇在每個情況末尾使用 fallthrough 關鍵字
19、相對于使用 if 語句來做同樣的事情,為需求使用 guard 語句來提升你代碼的穩定性。它會讓正常地寫代碼而不用把它們包裹進else 代碼塊,并且它允許你保留在需求之后處理危險的需求。
20、輸入輸出形式參數:在形式參數定義開始的時候在前邊添加一個 inout關鍵字,函數能夠修改一個形式參數的值,而且這些改變在函數結束之后依然生效,輸入輸出形式參數是函數能影響到函數范圍外的另一種替代方式。
21、結構體和枚舉是值類型,類是引用類型
22、 public private(set) var area: Double = 0 公開屬性 私有set
23、結構體是值類型。當一個值類型的實例被標記為常量時,該實例的其他屬性也均為常量。
24、你必須把延遲存儲屬性聲明為變量(使用 var 關鍵字),因為它的初始值可能在實例初始化完成之前無法取得。常量屬性則必須在初始化完成之前有值,因此不能聲明為延遲。
25、如果被標記為 lazy 修飾符的屬性同時被多個線程訪問并且屬性還沒有被初始化,則無法保證屬性只初始化一次。
26、你必須用 var 關鍵字定義計算屬性——包括只讀計算屬性——為變量屬性,因為它們的值不是固定的。 let 關鍵字只用于常量屬性,用于明確那些值一旦作為實例初始化就不能更改。
27、結構體和枚舉是值類型。默認情況下,值類型屬性不能被自身的實例方法修改。(可以選擇在 func關鍵字前放一個 mutating關鍵字來改變屬性值)
28、swift正常的方法如果有返回值的話,調用的時候必須有一個接收方,否則的話編譯器會報一個警告,如果在方法前加上 @discardableResult 不處理的時候就不會有警告了。或者 : _ =
29、你不能為同一個屬性同時提供重寫的setter和重寫的屬性觀察器
30、你可以通過在類定義中在 class 關鍵字前面寫 final 修飾符( final class )標記一整個類為終點。任何想要從終點類創建子類的行為都會被報告一個編譯時錯誤。
31、你可以通過標記為終點來阻止一個方法、屬性或者下標腳本被重寫。通過在方法、屬性或者下標腳本的關鍵字前寫 final 修飾符(比如 final var , final func , final class func , final subscript )
32、convenience:對現有的類增加init方法、通過extension給原有的People類增加init方法(無法重寫)。 ? 子類對象調用父類的convenience的init方法:只要在子類中實現重寫了父類convenience方法所需要的init方法的話,我們在子類中就可以使用父類的convenience初始化方法了
33、如果你想要你自己的自定義值類型能夠使用默認初始化器和成員初始化器初始化,以及你的自定義初始化器來初始化,把你的自定義初始化器寫在擴展里而不是作為值類型原始實的一部分。
34、指定初始化器必須保證在向上委托給父類初始化器之前,其所在類引入的所有屬性都要初始化完成。
35、指定初始化器必須先向上委托父類初始化器,然后才能為繼承的屬性設置新值。如果不這樣做,指定初始化器賦予的新值將被父類中的初始化器所覆蓋。
36、便捷初始化器必須先委托同類中的其它初始化器,然后再為任意屬性賦新值(包括同類里定義的屬性)。如果沒這么做,便捷構初始化器賦予的新值將被自己類中其它指定初始化器所覆蓋。
37、在類的初始化器前添加 required 修飾符來表明所有該類的子類都必須實現該初始化器:
38、使用 defer語句來在代碼離開當前代碼塊前執行語句
39、Any類型表示了任意類型的值,包括可選類型。
40、擴展可以向一個類型添加新的方法,但是不能重寫已有的方法。
41、擴展可以添加新的計算屬性,但是不能添加存儲屬性,也不能向已有的屬性添加屬性觀察者。
42、如果你使用擴展提供了一個新的初始化器,你仍應確保每一個實例都在初始化完成時完全初始化。
43、結構體和枚舉是值類型。默認情況下,值類型屬性不能被自身的實例方法修改。你可以選擇在 func關鍵字前放一個 mutating關鍵字來改變(如果你在協議中標記實例方法需求為 mutating ,在為類實現該方法的時候不需要寫 mutating 關鍵字。 mutating 關鍵字只在結構體和枚舉類型中需要書寫。)
44、你可以通過實現指定初始化器或便捷初始化器來使遵循該協議的類滿足協議的初始化器要求。在這兩種情況下,你都必須使用required 關鍵字修飾初始化器的實現,required 修飾的使用保證了你為協議初始化器要求提供了一個明確的繼承實現。(在類的初始化器前添加 required 修飾符來表明所有該類的子類都必須實現該初始化器,在重寫父類的必要初始化器時,不需要添加 override 修飾符)
45、由于 final 的類不會有子類,如果協議初始化器實現的類使用了 final 標記,你就不需要使用 required 來修飾了。因為這樣的類不能被繼承子類
46、如果一個子類重寫了父類指定的初始化器,并且遵循協議實現了初始化器要求,那么就要為這個初始化器的實現添加required 和 override 兩個修飾符
47、協議作為參數的話,飲用的實例必須采納 RandomNumberGenerator 協議
48、注意類型不會因為滿足需要就自動采納協議。它們必須顯式地聲明采納了哪個協議。(滿足協議,也必須顯示的聲明一下extension Hamster: TextRepresentable {})
49、通過添加 AnyObject 關鍵字到協議的繼承列表,你就可以限制協議只能被類類型采納(并且不是結構體或者枚舉)。
50、協議組合使用 SomeProtocol & AnotherProtocol 的形式。你可以列舉任意數量的協議,用和符號連接( & ),使用逗號分隔。除了協議列表,協議組合也能包含類類型,這允許你標明一個需要的父類。(celebrator 形式參數的類型是 Named & Aged ,這意味著“任何同時遵循 Named 和 Aged 的協議。”它不關心具體是什么樣的類型傳入函數,只要它遵循這兩個要求的協議即可。)
51、注意 @objc 協議只能被繼承自 Objective-C 類或其他 @objc 類采納。它們不能被結構體或者枚舉采納。
52、通過給協議創建擴展,所有的遵循類型自動獲得這個方法的實現而不需要任何額外的修改。
53、你可以使用協議擴展來給協議的任意方法或者計算屬性要求提供默認實現。通過擴展給協議要求提供默認實現與可選協議要求的區別是明確的。盡管遵循協議都不需要提供它們自己的實現。有默認實現的要求不需要使用可選鏈就能調用。
54、如果遵循類型滿足了為相同方法或者屬性提供實現的多限制擴展的要求,Swift 會使用最匹配限制的實現。
55、你可以在一個泛型** where 分句中包含多個要求來作為擴展的一部分,就如同你在其它地方寫的泛型 where **分句一樣。每一個需求用逗號分隔。
56、解決循環引用(弱引用和無主引用)
lazy var someClosure: () -> String = {
[unowned self, weak delegate = self.delegate!] in
*// closure body goes here*
}
57、具體來說,如果下面的條件可以滿足就說明重疊訪問結構體的屬性是安全的:
- 你只訪問實例的存儲屬性,不是計算屬性或者類屬性;
- 結構體是局部變量而非全局變量;
- 結構體要么沒有被閉包捕獲要么只被非逃逸閉包捕獲。
如果編譯器不能保證訪問是安全的,它就不允許訪問。
58、如果你使用@testable 屬性標注了導入的生產模塊并且用使能測試的方式編譯了這個模塊,單元測試目標就能訪問任何 internal 的實體。
59、接下來的關鍵字被預留,不能被用作標識符,除非它們像上一節標識符中描述的那樣使用反引號( ` )。
- 用在聲明中的關鍵字: associatedtype 、 class 、 deinit 、 enum 、 extension 、 func 、 import 、 init 、inout 、 internal 、 let 、 operator 、 private 、 protocol 、 public 、 static 、 struct 、 subscript 、typealias 和 var 。
- 用在語句中的關鍵字: break 、 case 、 continue 、 default 、 defer 、 do 、 else 、 fallthrough 、 for 、guard 、 if 、 in 、 repeat 、 return 、 switch 、 where 和 while 。
- 用在表達式和類型中的關鍵字: as 、 catch 、 dynamicType 、 false 、 is 、 nil , rethrows 、 super 、 self 、Self 、 throw 、 throws 、 true 和 try 。
- 用在模式中的關鍵字: _ 。
- 起始于數字標記( # )的關鍵字: #available 、 #column 、 #else 、 #elseif 、 #endif 、 #file 、 #function 、#if 、 #line 、 #selector 和 #sourceLocation 。
- 特定上下文中被保留的關鍵字: associativity 、 convenience 、 dynamic 、 didSet 、 final 、 get 、 infix 、indirect 、 lazy 、 left 、 mutating 、 none 、 nonmutating 、 optional 、 override 、 postfix 、precedence 、 prefix 、 Protocol 、 required 、 right 、 set 、 Type 、 unowned 、 weak 和 willSet 。這些關鍵字在特定上下文語法之外可以被用于標識符。
以下標記被當作保留符號,不能用于自定義操作符: ( 、 ) 、 { 、 } 、 [ 、 ] 、 . 、 , 、 : 、 ; 、 = 、 @ 、 # 、 & (作為前綴操作符)、 -> 、` 、 ? 和 ! (作為后綴操作符)。
60、觀察者:KVO 是一個純 OC 的特性,所以如果是 swift class 需要在聲明的時候增加 @objcMembers 關鍵字。否則在運行的時候你會得到一個 error。另外一件事就是被觀察的屬性需要用dynamic修飾,否則也無法觀察到。一個好消息是不需要在對象被回收時手動 remove observer。但是這也帶來了另外一個容易被忽略的事情:觀察的閉包沒有被強引用,需要我們自己添加引用,否則當前函數離開后這個觀察閉包就會被回收了。
61、一個繼承 NSObject 的 swift 類不再默認給所有函數添加 @objc。只在實現 OC 接口和重寫 OC 方法時才自動給函數添加 @objc 標識。
62、在 4.2 中蘋果終于響應了這個要求!現在 otional binding 中 self 不再作為保留關鍵字。