<b>本文講的是iOS 開發者一定要知道的 14 個知識點,</b>
<b></b>
作為一個 iOS 開發者(現在對 Swift 中毒頗深 )。我從零開始建立應用、維護應用,并且在很多團隊待過。在我的職業生涯中,一句話一直響徹耳邊:“如果你不能解釋一件事情,那你根本就不了解它。” 是以為了充分的了解我每天的日常,我建立了一個清單,在我看來,它适合任何 iOS 開發者。我會試着清晰的解釋每一個觀點。[請随時糾正我,提出你的意見,或者幹脆也來一發你覺得應該在清單上的“必須知道”的知識]
Topics: [源碼管控|架構|Objective-C vs Swift|響應式|依賴管理|資訊存儲|CollectionViews 和 TableViews|UI|協定|閉包|scheme|測試|定位|字元串本地化]
事不宜遲,沒有特定的順序,這就是我的清單。
恭喜你被雇傭了!現在從 repo 上拿代碼開始幹活吧,還等什麼?
每個項目都需要控制源碼的版本,即使隻有你一個開發者。最常見的就是 Git 和 SVN 了。
SVN 依賴于一個集中的系統來進行版本管理。它是一個用來生成工作副本(working copies)的中央倉庫,并且需要網絡連接配接才能通路。 它的通路授權是基于路徑的,追蹤的是注冊檔案的改變,更改曆史記錄隻能在中央倉庫中完全可見。 工作副本隻包含最新版本。
推薦的圖形界面工具:
<a href="http://versionsapp.com/">Versions - Mac Subversion Client (SVN) Versions, the first easy to use Mac OS X Subversion client versionsapp.com</a>
Git 依賴于一個分布式的系統來進行版本管理。你有一個本地的倉庫來進行工作,隻需要在同步代碼的時候聯網。它的通路授權是整個目錄,追蹤的是注冊内容的改變,在工作副本和主倉庫都可也看到完整的更改曆史。
<a href="https://www.sourcetreeapp.com/">SourceTree | Free Git and Hg Client for Mac and Windows SourceTree is a free Mercurial and Git Client for Windows and Mac that provides a graphical interface for your Hg and… www.sourcetreeapp.com</a>
你的指尖因興奮而顫抖,你想通了怎麼控制源碼!那先來杯咖啡壓壓驚?喝個P!現在的你正是巅峰狀态,正是寫代碼的最佳時刻!不,還需要再等等,等什麼?
在你蹂躏你的鍵盤之前,你需要先為項目選擇一個架構。因為項目還沒開始,你需要讓項目的結構符合你的選擇的架構。
有很多在移動應用開發中廣泛使用的架構,MVC、MVP、MVVM、VIPER 等等。我會簡短的概括這些之中 iOS 開發者最常用的:
MVC — 模型(Model)、視圖(View)、控制器(Controller)的縮寫。控制器的作用是連接配接模型和視圖,因為他們互不幹涉。視圖和控制器的聯系非常緊密,是以,控制器最終幾乎做了所有的工作。這意味着什麼?簡單來說,如果你建立了一個複雜的視圖,你的控制器(ViewController)會瘋狂的變大。有辦法繞過這個,但是他們不符合 MVC 規則。另一個 MVC 不好的地方是測試。如果你做測試(這對你有好處!),你會發現隻能測試模型,因為跟其他層相比,它是唯一能單獨分離出來的層。MVC 的加分項是直覺,而且大多數 iOS 開發者都用習慣了。
MVVM — 模型(Model)、視圖(View)、視圖模型(ViewModel)的縮寫。在視圖和視圖模型之間設定一種綁定(基本地響應式程式設計)的關系,這使得視圖模型來調用模型層改變自身時,由于和視圖之間的綁定關系而自動更新視圖。視圖模型并不知道視圖的所有事情,這樣利于測試,而且綁定節省了大量代碼。
對于其他架構更深入的說明和資訊,我建議閱讀這篇文章:
<a href="https://medium.com/ios-os-x-development/ios-architecture-patterns-ecba4c38de52">iOS Architecture Patterns Demystifying MVC, MVP, MVVM and VIPER medium.com</a>
這一條看上去不是很重要,但是代碼良好的結構性群組織性可以避免很多頭疼的問題。每個開發者有時候都會犯一個大錯,那就是為了得到想要的結果而放棄組織代碼,他們以為這節省了時間。如果你不同意,引用自 Benji:
組織代碼所耗費的每一分鐘,都相當于賺了一個小時。
— 本傑明·富蘭克林
我們的目标是讓代碼變得直覺易讀,這樣你才能簡單地建立并維護。
在決定選擇哪種語言編寫應用時,你需要知道不同的語言能帶來什麼。如果可以選擇的話,我個人建議使用 Swift。為什麼?實話說,Objective-C 相比于 Swift 是有微弱優勢的,大多數的例子和教程都是用 Objective-C 寫的,而且每次 Swift 語言更新的時候,都會對範式做調整,真是讓人發愁。但從長遠的角度來說,這些問題都會消失。
Swift 真的在很多方面都領先一步。它讀起來簡單,類似于自然語言,而且因為它不是基于 C 建構的,使得它可以抛棄 C 語言中的文法慣例。對于知道 Objective-C 的人來說,它意味着沒有分号,方法調用不需要括号,而且條件分支的表達式也不用括号。對代碼的維護也更容易了,Swift 隻有一個 .swift 檔案,而不是 .h 和 .m 檔案,因為 Xcode 和 LLVM 編譯器可以找出依賴關系,并且自動地執行增量建構。總而言之,你不需要擔心建立模闆代碼,而且你會發現用更少的代碼可以得到相同的結果。
不信?Swift 還更安全、更快而且還負責記憶體管理(大多數情況)。知道在 Objective-C 中用一個未初始化的指針變量調用一個方法會發生什麼嗎?什麼也不會發生。表達式變成空操作(no-op),然後跳過了。聽起來特棒,因為你不用擔心這會導緻應用崩潰了,盡管,它會導緻一系列嚴重的 bug 和不穩定的行為,以緻于你開始懷疑人生,決定重新考慮你的職業生涯。我非常确定你不想那樣。不過當一個職業遛狗人的念頭聽起來還是有那麼一點吸引人的。Swift 通過可選類型消除了這個問題。不僅你會精心思考什麼會是 nil,并在某個位置設定條件來來阻止它的使用,Swift 也會在 nil 值被使用時,彈出運作時的崩潰,以便更好的調試。記憶體方面,簡單的說,ARC(自動引用計數)在 Swift 上工作的更好。在 Objective-C 裡,ARC 并不支援 C 語言的代碼和 API,比如 Core Graphics。
<a href="https://camo.githubusercontent.com/bcbe54a8de9c16d0871bdb585d89db1eda9b52da/68747470733a2f2f63646e2d696d616765732d312e6d656469756d2e636f6d2f6d61782f3830302f312a7058783453455a375445787a3575436932736f5868772e676966" target="_blank"></a>
函數響應式程式設計(FRP)看上去似乎很潮。它的意圖是更簡單的組合異步操作并以事件/資料流的方式驅動。對于 Swift來說,通過 <code>Observable<Element></code> 接口來表示的通用計算抽象。(譯者注:這裡 <code>Observable<Element></code> 并不是原生的,而是 RxSwift 的接口)
最簡單的例子還是寫一點代碼。讓我們看看小 Timmy 和他的姐姐 Jenny,他們想要買一個新的遊戲機。Timmy 每周從他父母那裡得到 5€,Jenny 也一樣。不過 Jenny 每周末還能通過發報紙賺到 5€。如果他們把每一分錢都存下來,我們就可以每周檢查一下他們是否能得到遊戲機。每當他們其中一人的存款變化時,就計算一次他們的存款總額。如果錢夠了,一個消息就會被存儲在變量 isConsoleAttainable 裡。在任何時候,我們可以通過訂閱它來檢查消息。
我們做的這點東西對 FRP 來說都是皮毛,一旦你真的用起來了,它會為你打開新世界的大門,甚至允許你采用不同于傳統 MVC 的架構,對,就是 MVVM !
你可以看看 Swift FRP 王座的兩位主要競争者:
RxSwift
<a href="https://github.com/ReactiveX/RxSwift">ReactiveX/RxSwift RxSwift - Reactive Programming in Swift github.com</a>
ReactiveCocoa
<a href="https://github.com/ReactiveCocoa/ReactiveCocoa">ReactiveCocoa/ReactiveCocoa ReactiveCocoa - Streams of values over time github.com</a>
CocoaPods 和 Carthage 是 Swift 和 Objective-C Cocoa 項目裡最常見的依賴管理工具。他們簡化了庫的實作,并且保持庫的更新。
CocoaPods 有大量的三方庫支援,用 Ruby 建構,可以用下面的指令來安裝:
安裝過後,你需要為項目建立一個 Podfile 檔案,你可以運作下面這條指令:
或者按照這個結構自定義一個 Podfile 檔案:
一旦完成建立,那就是時候來安裝你的新 pods 了
現在,你可以打開項目裡的 .xcworkspace 檔案,别忘了引入你需要的依賴。
Carthage 是一個去中心化的依賴管理工具,和 Cocoapods 相對立。缺點是使用者很難找到現有的使用 Carthage 的庫。另一方面來說,它隻需要很少的維護工作,而且避免了各種中心化産生的問題。
你可以看看他們的 GitHub 來擷取更多的關于安裝和使用的資訊:
<a href="https://github.com/Carthage/Carthage">Carthage/Carthage Carthage - A simple, decentralized dependency manager for Cocoa github.com</a>
如果想用簡單的方式為你的應用存儲資料,那麼 NSUserDefaults 就是這種方式,因為它通常儲存的是使用者的預設資料,在應用首次加載的時候就被放入了。出于這個原因,它就變得簡單易用,盡管這也意味着一些限制。其中一條限制就是它接受對象的類型。它的作用和 Property List(Plist) 非常像(其中也有同樣的限制)。下面的六種類型能被存儲到裡面:
NSData
NSDate
NSNumber
NSDictionary
NSString
NSArray
為了和 Swift 相容,NSNumber 可以接受以下的類型:
UInt
Int
Float
Double
Bool
對象可以以下列方式儲存到 NSUserDefaults(要先建立一個常量,作為我們要儲存的對象的鍵):
想要從 NSUserDefaults 讀取一個對象時,這樣做:
為了擷取特定類型的對象而不是 AnyObject(Swift 3 中的 Any),有幾個便捷函數來讀寫 NSUserDefaults。
鑰匙串是一個可以儲存密碼、證書、私鑰以及私有資訊的密碼管理系統。keychain 的裝置加密有兩個級别。第一級别是使用鎖屏密碼作為密鑰,第二級别使用由裝置生成的密鑰,并存儲在裝置上。
這意味着什麼呢?意味着它不是很安全,尤其是你不使用鎖屏密碼的時候。同樣,也有很多方式可以擷取第二種密鑰,畢竟它是存在裝置上的。
最好的解決方案還是使用你自己的加密。(不要把密鑰存在裝置上)
CoreData 是一個蘋果公司開發的架構,它的目的是讓你的應用以面向對象的方式與資料庫溝通。它簡化了通路過程,減少了代碼量而且去掉了需要測試的那部分代碼。
如果你的應用需要資料持久化,那麼你就應該用它,它大大的簡化了資料持久化的過程,這意味着你再也不用建構與資料庫連接配接的這部分程式,以及這部分的測試代碼。
每個應用都有或多或少的 CollectionView 或 TableView。了解他們的工作原理,什麼時候用哪個,都會在未來防止你的應用發生複雜的更改。
TableViews 以單列的方式,展示了一個清單,它隻能垂直的滑動。清單的每項由 UITableViewCell 來表示,可以完全的自定義。這些項以 sections 和 rows 的方式來分類。
CollectionViews 也展示了一個清單,不過他可以有多行多列(像網格)。它水準豎直都可以滑動,每個項通過 UICollectionViewCell 來表示。和 UITableViewCell 一樣,也可以自定義,并按照 sections 和 rows 的方式來分類。
他們有相似的功能,并都使用可複用 cell 來提高流暢性。選擇哪個取決于你要寫的清單的複雜程度。集合視圖可以用于任何的清單,在我看來,始終是個不錯的選擇。現在假設你想做一個聯系人清單。這太簡單了,一列就可以搞定,是以你選擇用 UITableView。偉大的作品!幾個月以後,你們的設計師決定聯系人還是以網格的形式來顯示。那你就隻能把 UITableView 的實作全部換成 UICollectionView 的。我想說的是,即使你的清單很簡單,用 UITableView 足以搞定,如果有好靈感,設計也許會變,是以最好還是用 UICollectionView 來實作一個清單。
不管你最後選擇了哪個,最好寫一個通用的 tableview/collectionview,它讓你的實作更容易,并且可以重用很多代碼。
他們每一種方式都可以在編寫 UI 方面獨擋一面,當然,也沒有人不讓你一起用。
Storyboards 允許你為項目建立一個更寬泛的視圖,設計師們很喜歡,因為他們可以看到應用的流程和所有的螢幕。壞處在于,随着螢幕的增加,他們之間的連接配接變得越來越混亂,storyboard 的加載時間也會增加。合并代碼的沖突也會頻繁的發生,因為所有的 UI 都寫在了一個檔案上。而且這些沖突還很難解決。
Xibs 提供了一個螢幕或者部分螢幕的視圖。他們的好處是易于複用,合并代碼的沖突比用 storyboard 要少,而且也可以簡單的看到每個螢幕上有什麼。
手撸 UI 代碼 讓你在最大程度上控制你的代碼,并減少合并沖突,如果沖突發生,也可以很容易的解決。缺點就是沒法看到具體的内容,還要花額外的時間去撸 UI。
有多種不同的方式來實作你應用的 UI 部分。但我還是主觀的認為,最好的方式就是三種混合使用。使用多個 Storyboards(現在 storyboards 之間可以連接配接),然後用 Xibs 來展現那些非主螢幕上的内容,最後,在确定的情況下用代碼做額外的控制。
協定存在于我們的日常生活中,它可以來确定在給定的環境下,我們知道如何反應。假如你是一個消防員,現在有緊急情況。 每個消防隊員都必須遵守協定,按照既定要求,才能成功的應對。這同樣适用于一個 Swift/Objective-C 協定。
一個協定是按照給定的功能,定了了方法、屬性和其他需要的約定。它可以被類、結構體或枚舉采用,然後由他們提供這些功能具體的實作。
這裡有一個怎麼建立并使用協定的例子:
在例子中,我會使用一個枚舉,來列出不同的滅火材料。
接着,我要建立一個能應對緊急情況的協定。
現在我要建立一個消防員來實作協定。
幹的漂亮!現在讓消防員行動起來。
結果應該是 “Fire was put out using foam.”
協定也被用于委托。它允許類或結構體将功能委托給另一個類型的執行個體。建立具有委托職責的協定,以保證符合類型的執行個體為他們提供具體的功能。
快速示例!
消防站将處理緊急情況的的行動委托給消防員。
這就意味着消防員也要實作 FireStationDelegate 協定。
需要做的就是把待命的消防員設為消防站的代理,他會處理那些接到的火警電話。
結果應該是 “Fire was put out using water.”
可以看到,協定非常有用。用他們還可以做很多很多的事情,但現在我隻介紹到這裡。
這裡我隻說 Swift 裡的閉包。他們多數的用途是,作為一個函數完成的回調或者是高階函數。函數回調,顧名思義,就是一個任務完成,執行這段回調代碼。
Swift 裡的閉包類似于 C 和 Objective-C 中的 block。
閉包是第一類對象,是以可以被嵌套和傳遞(像 Objective-C 裡的 block)。
在 Swift 裡,函數是一種特殊的閉包。
這是一個學習閉包文法很不錯的地方。
簡單的說,schemes 就是在各種配置間切換的簡單方式。設想幾種情況。Workspace 包含了各種的相關聯的項目。項目可以多個 target(target指定了要建構的産品以及如何建構)。項目也可能有多種配置。Xcode scheme 定義了要建構的 target 集合、建構時使用的配置以及要執行測試的集合。
如果你配置設定時間為你的應用編寫測試代碼,那你正走向正軌。它不是萬能的,不能避免每一個錯誤,也不能保證你的應用沒有任何問題,但我還是覺得好處多于壞處。
讓我們從單元測試開始 壞處:
開發時間增加;
代碼量增加。
好處:
強制的建立子產品化代碼 (這樣才利于測試);
顯然,更多的 bug 會在正式版本釋出前被找到;
更好維護。
配合 Instruments 工具,你已經擁有了所有讓你應用變得流暢的工具,無論從處理 bug 角度還是解決崩潰的角度。
有不少的工具可以測試你的應用有什麼問題。你可以根據你想要知道的,來選擇其中的一個或者多個。最常用的,大概就是 Leak Checks(記憶體洩露檢測),Profile Timer(性能調優) 和 Memory Allocation(記憶體配置設定)了。
很多應用會有一些功能需要知道使用者的位置。是以了解一下 iOS 上定位系統的基本知識是一個不錯的點子。
有個叫做 Core Location 的架構給了你需要的一切:
Core Location 架構,可以讓你确定與裝置相關的目前位置或方向。它通過可用的硬體來确認使用者的位置與方向。你可以使用架構内部的類和協定來配置或計劃位置的變更和方向的轉變。你也可以使用它來定義地理區域,并監控使用者何時跨越邊界。在 iOS 裡,你也可以定義一個藍牙信标區域。
很不錯是吧?檢視蘋果的官方文檔和示例代碼,來更好的了解你能做什麼以及怎麼做。
<a href="https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/LocationAwarenessPG/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009497">關于定位服務和地圖 描述了定位和地圖服務的使用 developer.apple.com</a>
這是每個應用都需要實作的。它允許應用根據所在地區而改變語言。即使你的應用隻有一種語言,在将來也可能會有添加另一種語言的情況。如果所有的文本都使用了字元串本地化,需要做的所有工作就是為新語言添加一個 Localizable.strings 檔案的翻譯版本。
可以通過檔案檢查器将資源添加到一個語言。 要使用 NSLocalizedString 擷取字元串,所有你要做的就是下面的内容:
不幸地是,往 Localization 檔案裡添加新字元串是手動的。以下是一個結構示例:
現在一個相對應的,不同語言(葡萄牙語),Localizable 檔案格式:
甚至有辦法實作複數。
<b>原文釋出時間為:2017年2月16日</b>
<b>本文來自雲栖社群合作夥伴掘金,了解相關資訊可以關注掘金網站。</b>