Swift及SwiftUI學習筆記

持續更新中......

swift官方文檔


swift官方文檔(英文)

協議


swift主要基于協議編程的,所以協議無處不在。
先看看這篇文章:Swift學習:協議

官方的一些常用協議:
1. Equtable
在Swift中可以通過實現Equatable協議使自定義類型支持==以及!=這兩種運算符。

2. Comparable
Comparable協議繼承于Equatable,實現Comparable協議可以在Equatable的基礎上使類型支持>,>=,<,<=四種運算符。

3. CustomStringConvertible
當類實現這個協議,可使用print打印類的自定義信息。

4. CustomDebugStringConvertible
當類實現這個協議,可使用debugPrint打印類的自定義信息。

5. Hashable
繼承于Equatable。
一個類型為了存儲在集合中,該類型必須是可哈?;?該類型必須提供一種方法計算它的哈希值,一個哈希值為Int類型,相等的對象哈希值必須相同。
Swift的所有基本類型(形如String,Int,Double,Bool)默認是可哈?;?,可以作為集合的值的類型或者字典的鍵的類型。沒有關聯值的枚舉成員值默認也是可哈?;?。

用我的話來說:當想把自定義對象當做key存入set和dict中時,那么這個key必須是哈希的,并且要重載等號來對比key之間的不同。

官方的文檔說的比較清楚,這里有篇中文翻譯:
Swift之Hashable協議

6. Codable
Codable = Decodable & Encodable
顧名思義,即編解碼序列化。
具體參看以下文章:
Swift 4.0: Codable
Swift 4 踩坑之 Codable 協議

這里的“&”符號的意思是協議合成:
協議合成并不會生成新的、永久的協議類型,而是將多個協議中的要求合成到一個只在局部作用域有效的臨時協議中。
協議合成的意思是都羅列的協議都需要遵循。
其實不僅僅是協議可以合成,類也可以跟協議一起使用“&”符號合成。

7. CaseIterable
一句話:CaseIterable被用于合成簡單枚舉類型的 allCases 靜態屬性。
Swift 4.2 新特性詳解 CaseIterable.allCases
Swift--enum枚舉,協議CaseIterable

8. Identifiable
這個協議只需要你定義一個 id 屬性,這個屬性必須是一個 Hashable 類型。

協議和泛型


加粗的這句話非常重要:

針對Class和Function,都是通過<Type>來定義。而當我們需要給協議實現一個泛型的時候,需要使用associatedtype關鍵字來定義泛型:這里需要注意,泛型協議并不能像普通協議那樣作為一個類型使用,這是因為 GenericProtocol 表示一組類型,并不是一個單一類型。比如你有一個關于 GenericProtocol 的隨機數組,并不能確定每個元素的 magic() 方法返回的類型到底是什么,因為數組中每個元素可能都是不同的。

泛型最終在使用時都要被推斷出來,一種情況是實現的時候指定了類型,另一種在調用時明確類型。

參考:

  1. swift的泛型協議為什么不用<T>語法
  2. 為什么 Swift 關聯類型的協議需要做為泛型約束使用(譯)

元類型.Type 與 .self


一開始看到官方例子中有一行這樣的代碼:

func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
...
}
//調用方法
let landmarkData: [Landmark] = load("landmarkData.json")

對于as type: T.Type = T.self這一部分不理解,搞懂這個需要先學習元類型。

元類型就是類型的類型。

let n : Int = 5

變量n的類型是Int類型,這個很容易理解。
那么Int的類型又是什么呢?
Int的類型就是:Int.Type,類型的類型,即元類型。
說完類型來說值:
n的類型是Int,值是5。

let m: Int.Type = Int.self

那么變量m的類型是元類型Int.Type,m的值是Int.self。

到這兒我們再回頭來看上面的代碼:

func load<T: Decodable>(_ filename: String, as type: T.Type = T.self) -> T {
...
}

as在這兒是標簽名字,type是參數名,它的類型是:T.Type元類型,默認值是T.self。
所以我們也可以這樣調用方法,跟不寫第2個參數是等價的:

let landmarkData: [Landmark] = load("landmarkData.json", as: [Landmark].self)

class和static的區別


class和static用于修飾方法和計算屬性使其成為靜態方法或者靜態屬性。

最大的區別:

  1. class只能在類中使用,static可以在類和結構中使用。
  2. class修飾的方法可以被子類重寫,而static不能被重寫。

其他細節的區別參看:
swift3.0 中class和static

ForEach和\.self


官方例子:

static var previews: some View {
        ForEach(["iPhone SE", "iPhone XS Max"], id: \.self) { deviceName in
            LandmarkList()
                .previewDevice(PreviewDevice(rawValue: deviceName))
                .previewDisplayName(deviceName)
        }
        .environmentObject(UserData())
    }

需要先學習這篇文章:
SwiftUI 和 Swift 5.1 新特性(3) Key Path Member Lookup

enum: if case,guard case,for case


模式匹配第四彈:if case,guard case,for case

關鍵字


associatedtype:
從字面上來理解,就是相關類型。意思也就是被associatedtype關鍵字修飾的變量,相當于一個占位符,而不能表示具體的類型。具體的類型需要讓實現的類來指定。

typealias:
用來為已經存在的類型重新定義名字的,通過命名,可以使代碼變得更加清晰。使用的語法也很簡單,使用typealias 關鍵字像使用普通的賦值語句一樣,可以將某個已經存在的類型賦值為新的名字。

Combine


Combine可以看作是簡化版的RxSwift,Combine目前學習資料不多,可以先學RxSwift了解基本概念,再使用下面的對照速查表快速學習Combine。
RxSwift中文文檔
RxSwift 使用詳解系列
Swift Combine 入門導讀
RxSwift到Apple的Combine速查表(Cheat Sheet)

Apple Combine 的開源實現:
有空可以看看,對于加深Combine的理解有好處。
有兩個項目:

  1. OpenCombine
    項目地址:broadwaylamb/OpenCombine

  2. Apple Combine 的開源實現 CombineX 的第一個 beta 發布啦!
    項目地址:luoxiu/CombineX

SwiftUI學習資料


  1. 這個是官方Demo的中文翻譯文檔
    建議先從這里開始學,結合源碼學的更快。
    WillieWangWei/SwiftUI-Tutorials

  2. 基本控件、狀態流、手勢等知識的簡單說明和示范
    Jinxiansen/SwiftUI

3.SwiftUI之屬性包裝
講解了以下屬性包裝:

@State
ObservableObject
@Published
@ObservedObject
@EnvironmentObject
@Environment
@Binding
@GestureState

學習SwiftUI遇到的問題和bug


  1. SwiftUI update navigation bar title color
  2. 滾動ScrollView到指定位置:
    SwiftUI ScrollView: How to modify .content.offset aka Paging?
  3. 鍵盤彈出/隱藏時修改布局
    How to show complete List when keyboard is showing up in SwiftUI
  4. SecureField
  • 只要在頁面中使用了SecureField那么該頁面的第三方輸入法就被禁用,在其他TextField上也不能調出。
    在切換到另外頁面中可以調出第三方鍵盤,不過因為在此頁面中已經被切換到系統輸入法,所以在別的頁面需要手動切換第三方鍵盤。
  • 運行時焦點切換到SecureField會打印以下log:

[AutoFill] Cannot show Automatic Strong Passwords for app bundleID: xxx.xxx due to error: Cannot save passwords for this app. Make sure you have set up Associated Domains for your app and AutoFill Passwords is enabled in Settings

可以忽略不管。
參看此篇文章:WWDC18 iOS 自動生成強密碼和自動填充驗證碼/密碼

  1. 去掉導航頭
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
.navigationBarTitle("注冊", displayMode:.inline)//tmd,必須設置這個才能真使.navigationBarHidden(true)有效
  1. xcode的一個bug
    在一個文件中SwiftUI預覽時右邊工具欄的屬性欄始終出不來,另一個文件可以看到屬性欄,折騰了半天把文件名一改屬性欄居然出來了,再把文件名改回去也一切正常。
  2. 去掉List或者Form的左邊空白
    加在List/Form的子級中:
.listRowInsets(EdgeInsets())

以上還會留一點點空白,使用以下把空白完全去除:

.listRowInsets(EdgeInsets(top: 0, leading: -8, bottom: 0, trailing: 0))

或者

.padding(.horizontal, -24)

以上的-8,-24是自己對著界面調出來的,不一定通用(可能在不同平臺有不同表現)。一般問題不用太精確,湊合用著可以了。

  1. 不要隨便用Button
    在Form的Section底下用了Button,當點擊一欄中不被其他控件比如TextField完全填充的空白區域時都會激活Button的action事件,把Button換成Image并且使用onTapGesture事件就正常了。
    Image點擊事件代碼例子:
 Image(systemName: "xmark.circle.fill")
                                    .foregroundColor(.gray).opacity(0.5)
                                    .imageScale(.small)
                                    .onTapGesture {
                                           print("image click")
                                    }
  1. TextField在系統自帶的簡體拼音輸入法時有bug
    首先是輸入時鍵盤上的候選區閃動,另外輸入會莫明其妙的被自動刪除或者多出字符,總之該輸入法在TextField中基本不能用。
    然后我換成UITextField后就沒問題了,shit!
    目前iOS13.2.3依然有此bug。

  2. TextField和SecureField回車后無法自動切換到下一個輸入框。

  3. 根據上面第9和第10條,TextField和SecureField最好還是別用,用UIKit版封裝一下替代。

  4. 最好不要自定義previewDevice

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ForEach("iPhone SE","iPhone XS Max", "iPhone 11 ", "iPhone 11 Pro"], id: \.self) { deviceName in
            ContentView()
                .previewDevice(PreviewDevice(rawValue: deviceName))
                .previewDisplayName(deviceName)
        }
        .environmentObject(UserData())
    }
}
  • 以上"iPhone 11 "在我機器上一定要加后面那個空格,否則preview時一直出不來。
  • 我實際上只使用一個設備比如"iPhone XS Max"或者"iPhone 11 Pro",當使用Xcode一段時間后,Xcode的子進程:SourceKitService會瘋狂占用內存,占用的內存多達幾十G,機器變得非常慢,最后只好強制殺死SourceKitService進程。
    不使用以上自定義previewDevice,只使用以下默認代碼則一切正常:
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
  1. 改變全屏顏色包括SafeArea區域
//  Color實際是個View,所以可以使用edgesIgnoringSafeArea來忽略安全區達到全屏效果
.background(Color(red: 0.9, green: 0.9, blue:0.9).edgesIgnoringSafeArea(.all))
  1. 當在xcode中打開多個Tab窗口時,只在一個Tab中開啟Preview。如果在多個Tab中開啟Preview的話可能會預覽失敗。

Font Icon和SF Symbols


Font Icon:
開源庫好幾個,我先選擇了這個:
ranesr/SwiftIcons
不過后來發現蘋果官方有SF Symbols

SF Symbols:
ios13以上系統自帶SF Symbols,應該也是Font Icon,可以直接調用。
官方文檔說明:
SF Symbols
要想知道所有符號名字需要下載上面頁面提供的一個mac軟件,不過直接下載很慢,使用迅雷快很多。

所以使用SwiftUI開發APP的話可以不使用第三方FontIcon直接使用SF Symbols
調用例子:

 Image(systemName: "arkit").foregroundColor(.blue)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374