swift:
1.struct和class區(qū)別
struct SNode {
var Data: Int?
}
class CNode {
var Data: Int?
}
1.property初始化的不同
let snode = SNode(Data: 4) // struct可直接在構(gòu)造函數(shù)中初始化property
print("snode.data:\(String(describing: snode.Data))")
let cnode = CNode() // class不可直接在構(gòu)造函數(shù)中初始化property
cnode.Data = 5
print("cnode.data:\(String(describing: cnode.Data))")
2.賦值不同
struct 賦值“=”的時候,會copy一份完整相同的內(nèi)容給另一個變量 --> 【開辟了新的內(nèi)存地址】
class 賦值“=”的時候痊剖,不會copy一份完整的內(nèi)容給另一個變量船万,只是增加了原變量內(nèi)存地址的引用而已 --> 【沒有開辟了新的內(nèi)存地址】
3.繼承
struct不能繼承恋拍,class可以繼承。
4.struct比class更“輕量級”
struct分配在棧中狈邑,class分配在堆中。
知識延伸:為什么訪問struct比class快岛都?
“堆”和“棧”并不是數(shù)據(jù)結(jié)構(gòu)上的Heap跟Stack振峻,而是程序運行中的不同內(nèi)存空間臼疫。棧是程序啟動的時候,系統(tǒng)事先分配的扣孟,使用過程中烫堤,系統(tǒng)不干預(yù);堆是用的時候才向系統(tǒng)申請的凤价,用完了需要交還鸽斟,這個申請和交還的過程開銷相對就比較大了。
棧是編譯時分配空間利诺,而堆是動態(tài)分配(運行時分配空間)富蓄,所以棧的速度快。
從兩方面來考慮:
1.分配和釋放:堆在分配和釋放時都要調(diào)用函數(shù)(MALLOC,FREE)慢逾,比如分配時會到堆空間去尋找足夠大小的空間(因為多次分配釋放后會造成空洞)立倍,這些都會花費一定的時間,而棧卻不需要這些侣滩。
2.訪問時間:訪問堆的一個具體單元口注,需要兩次訪問內(nèi)存,第一次得取得指針君珠,第二次才是真正得數(shù)據(jù)寝志,而棧只需訪問一次。
2.map、flatMap和compactMap
map和flatMap
區(qū)別一
map 最終將它們組成一個二維的數(shù)組材部;
flatMap 中執(zhí)行的 closure 返回的是同樣的數(shù)組悠菜,但是 flatMap 將每一個返回的數(shù)組都拍扁,取出它的元素败富,構(gòu)成一個大的一維數(shù)組悔醋。
let numbers = [[1, 2, 3, 4], [5, 6], [7]]
let maped = numbers.map { $0 }
let flatMapped = numbers.flatMap { $0 }
print(maped)
print(flatMapped)
/// [[1, 2, 3, 4], [5, 6], [7]]
/// [1, 2, 3, 4, 5, 6, 7]
區(qū)別二
map是閉包內(nèi)return為非可選項,但最終返回值為可選項兽叮,即閉包return后又套了一層可選項芬骄。
flatMap是閉包內(nèi)return為可選項,最終返回值也為可選項鹦聪,即閉包內(nèi)return后對可選項進行解包账阻,最終又套了一層可選項。
func map<U>( transform: (Wrapped) -> U) -> U?
func flatMap<U>( transform: (Wrapped) -> U?) -> U?
compactMap函數(shù)的應(yīng)用
- 過濾 nil
let nums = [1, nil, 3, nil, 5]
let result = nums.compactMap { (item) -> Int? in
return item
}
print(result) // [1, 3, 5]
簡潔語法泽本,可這樣使用
let result = nums.compactMap { return $0 }
print(result) // [1, 3, 5]
2.類型轉(zhuǎn)換
let nums = [1, 2, 3, 4, 5]
let result = nums.compactMap { (item) -> String? in
return "\(item)"
}
print(result) // ["1", "2", "3", "4", "5"]
簡潔語法淘太,可這樣使用
let nums = [1, 2, 3, 4, 5]
let result = nums.compactMap { return "\($0)" }
print(result) // ["1", "2", "3", "4", "5"]
3.篩選數(shù)據(jù) - 能被4整除的數(shù)
let nums = [12, 55, 733, 77, 44]
let result = nums.compactMap { (item) -> Int? in
if item%4 == 0 {
return item
}
return nil
}
print(result) // [12, 44]
3.public、internal和private
??◆ privateprivate訪問級別所修飾的屬性或者方法只能在當前的Swift源文件里可以訪問规丽。
??◆ internal(默認訪問級別蒲牧,internal修飾符可寫可不寫)internal訪問級別所修飾的屬性或方法在源代碼所在的整個模塊都可以訪問。如果是框架或者庫代碼赌莺,則在整個框架內(nèi)部都可以訪問冰抢,框架由外部代碼所引用時,則不可以訪問艘狭。如果是App代碼挎扰,也是在整個App代碼,也是在整個App內(nèi)部可以訪問巢音。
??◆ public可以被任何人使用
4.閉包
非逃逸閉包
顯而易見是非逃逸閉包被限制在函數(shù)內(nèi)遵倦,當函數(shù)退出的時候,該閉包引用計數(shù)不會增加官撼,也就是說其引用計數(shù)在進入函數(shù)和退出函數(shù)時保持不變梧躺。逃逸閉包
逃逸閉包恰恰與非逃逸閉包相反,其生命周期長于相關(guān)函數(shù)歧寺,當函數(shù)退出的時候燥狰,逃逸閉包的引用仍然被其他對象持有,不會在相關(guān)函數(shù)結(jié)束后釋放斜筐。
Swift 3.x中, 閉包參數(shù)默認是非逃逸類型龙致,如果需要其逃逸類型的閉包,記得使用關(guān)鍵字 @escaping
而對于非逃逸型閉包顷链,由于其生命周期確定短于相關(guān)函數(shù)目代,編譯器可以據(jù)此做性能優(yōu)化。
注意
要謹慎使用@escaping(逃逸閉包),除非明確知道要使用它做什么榛了。
下面是使用逃逸閉包的2個場景:
異步調(diào)用: 如果需要調(diào)度隊列中異步調(diào)用閉包在讶, 這個隊列會持有閉包的引用,至于什么時候調(diào)用閉包霜大,或閉包什么時候運行結(jié)束都是不可預(yù)知的构哺。
存儲: 需要存儲閉包作為屬性,全局變量或其他類型做稍后使用战坤。