「 iOS知識小集 」2018 · 第 22 期

知識小集發表於2018-07-25

小集微博話題 #iOS知識小集# 閱讀量已達到 1500w+,小小成就。歡迎更多童鞋加入一起來分享。

上週公眾號釋出的以下文章:

本期知識小集的主要內容包括:

  • iOS 記憶體洩露工具

  • 靜態 UITableView 兩種 style 的差異

  • 怎麼解決網路請求的依賴關係

  • 對 AppStore 在蜂窩網150MB的下載限制的理解

  • 配置 xcodebuild 命令打包支援 Bitcode

  • Swift 版本建私有庫時需要注意的地方

iOS 記憶體洩露工具

作者: Lefe_x

在日常開發中總會遇到記憶體洩漏的的問題,而排除記憶體洩漏一般會依靠以下這些工具:

  • MLeaksFinder

這個 WeRead 團隊開發的一個記憶體洩漏檢測工具,主要用來檢測 UIViewController 和 UIView 中存在的記憶體洩漏。如果檢查到記憶體洩漏,會彈出 Alert 提示存在記憶體洩漏。當然,如果某個 UIViewController 是單例,將會誤檢。

如果檢查出記憶體洩漏,點選 Alert 上的 Retain Cycle 將使用 FBRetainCycleDetector 檢查存在迴圈引用的物件。比如:

-> DownloadAudioListViewController ,
-> _callblock -> __NSMallocBlock__ 
複製程式碼
  • FBRetainCycleDetector

這是 facebook 開源的一個記憶體洩漏檢測工具,它可以檢測出迴圈引用:

FBRetainCycleDetector *detector = [FBRetainCycleDetector new];
[detector addCandidate:myObject];
NSSet *retainCycles = [detector findRetainCycles];
複製程式碼

檢查出的記憶體洩漏將列印出來:

-> DownloadAudioListViewController ,
-> _callblock -> __NSMallocBlock__ 
複製程式碼
  • Instrument 的 Leak 工具

Instrument 中的 Leak 工具主要用來“突襲”,開發者定期地使用它來檢測記憶體洩漏。而上面介紹的工具主要在開發過程中即可發現記憶體問題,提前暴露給開發者。

Xcode 中的 Debug Memory Graph

這個工具主要以圖表的形式顯示了當前記憶體的使用情況,可以檢視迴圈引用,如果有記憶體問題會顯示一個歎號。

靜態 UITableView 兩種 style 的差異

作者: Vong_HUST

想必設定頁應該是各大應用所必備的,相信大部分還是採用靜態 UITableView 的方式在構建,我們專案中也用到了。最近測試反饋一個問題就是一些配置項的描述文案會蓋住單元格內容,如圖所示。由於之前配置項比較少,所以沒有發現,最近新增了好幾個配置,所以問題暴露出來了。

「 iOS知識小集 」2018 · 第 22 期

圖中【接收哪些人】的私信是一個 SectionFooter,由於 SectionFooter 是懸停的,內容超過一屏的情況下,SectionFooter 會將單元格擋住,由於 footer 背景是透明的,所以看起來是重疊的。由於 tableView 設定的 style 是 Plain 的,這種情況下 SectionFooter 和 SectionHeader 都是懸停的。如果要想他們不懸停,只需要把 tableView 的 style 設定成 Grouped 即可。

但是需要注意的是 Grouped 樣式的 SectionFooter 是自帶間隔的,會比 Plain 樣式下的 SectionFooter 高 18pt,所以改成 Grouped 樣式之後如果要同步 Plain 樣式的間隔,這個 tableView:heightForFooterInSection: 代理方法返回的高度要減小 18。

怎麼解決網路請求的依賴關係

作者: 蔣匿

怎麼解決網路請求的依賴關係:當一個介面的請求需要依賴於另一個網路請求的結果?

  1. 思路 1:操作依賴:NSOperation 操作依賴和優先順序。

例如[operationB addDependency:operationA]; 雖然這個想法很好,但不適用非同步,非同步網路請求並不是立刻返回,無法保證回撥時再開啟下一個網路請求。

  1. 思路 2:邏輯判斷:在上一個網路請求的響應回撥中進行下一網路請求的啟用。

這是最原始的想法,但還是有 BUG:可能拿不到回撥無法執行到 block 塊裡面的程式碼。

  1. 思路 3:執行緒同步 -- 組佇列(dispatch_group)。

先建一個全域性佇列 queue,並新建一個 group(用 dispatch_group_create()),然後向 Group Queue 依次追加 block,最後用 dispatch_group_notify 新增 block。當前面的 block 全部執行完,就會執行最後的 block。例如下圖。

「 iOS知識小集 」2018 · 第 22 期

  1. 思路4:執行緒同步 --任務阻塞(dispatch_barrier)。

通過 dispatch_barrier_async 新增的操作會暫時阻塞當前佇列,即等待前面的併發操作都完成後執行該阻塞操作,待其完成後後面的併發操作才可繼續。使用 dispatch_barrier_async 可以實現類似組佇列的效果。例如下圖。

「 iOS知識小集 」2018 · 第 22 期

  1. 思路5:執行緒同步 -- 訊號量機制(dispatch_semaphore)。

除了任務阻塞,還可以利用訊號量實現這種阻塞效果:在非同步開啟任務 1 和任務 2 之前,初始化一個訊號量並設定為 0,然後在任務 1 的 block 中寫好請求操作,操作執行完後對前面的訊號量加 1,在任務 2 的 block 中,需要在開始請求之前加上等待訊號量的操作。這樣一來,只有任務 1 中的請求執行完後,任務 2 等到了訊號量加 1 才接著執行它的請求。例如下圖。

「 iOS知識小集 」2018 · 第 22 期

對 App Store 在蜂窩網 150MB 的下載限制的理解

作者: 高老師很忙

大家應該都有這樣的一個印象:在蜂窩網下,150MB 的包在 AppStore 是不能下載的,每當看到 AppStore 下面展示的 Size 接近 150MB 的時候就會很緊張,這意味著又要來一波艱難的減包操作了。

「 iOS知識小集 」2018 · 第 22 期

那麼這個 150MB 指的是什麼呢?是 AppStore 展示的 Size 麼?我做了一個小小的調研,發現並非如此,150MB 是包的下載大小,而 AppStore 裡展示的 Size 是安裝後(有解壓操作)的大小,對幾個 App 進行了抓包操作:(這個是前段時間的調研,因為版本迭代可能資料會有出入,但足以說明問題)

「 iOS知識小集 」2018 · 第 22 期

從蘋果之前的官方新聞也能看出端倪:

「 iOS知識小集 」2018 · 第 22 期

所以說 AppStore 蜂窩下載限制指的是下載的實際大小而非 AppStore 展示的 Size。

在 ITC 構建版本處理完成後,可以看到詳細資訊:在各個機型上的下載大小以及安裝大小,同時也會提示你是 150MB 下載限制,超過限制還會給你一個黃色警告哦。

「 iOS知識小集 」2018 · 第 22 期

減包是一個任重而道遠的事情,不要等到在 150MB 的危險邊緣再去處理哦!

配置 xcodebuild 命令打包支援 Bitcode

作者: KANGZUBIN

我們通常會把一些公用的模組抽離出來打成一個 或者 .framework 動態庫,然後再嵌入到宿主工程中。

最近我們的 App 工程開啟 Bitcode 編譯選項後(Enable Bitcode = YES),發現在進行 Archive 歸檔打 Release 包時,報如下錯誤,提示說工程使用的 libTestStaticSDK.a 靜態庫不支援 Bitcode:

ld: bitcode bundle could not be generated because '/.../TestApp/TestStaticSDKLib/libTestStaticSDK.a(TestStaticSDK.o)' was built without full bitcode. All object files and libraries for bitcode must be generated from Xcode Archive or Install build for architecture armv7
複製程式碼

但是我們的 libTestStaticSDK 靜態庫工程的 Build Settings 中同樣是有配置開啟 Bitcode 的,為什麼打出來的 .a 包卻不支援 Bitcode 呢?

通過查閱 StackOverflow 我們發現,原來開啟 Bitcode 後,在 Xcode 中進行 "Build" 或 "Archive" 時,Xcode 會自動在編譯命令後面新增 -fembed-bitcode 標識,而如果使用 xcodebuild 命令進行打包,則需要手動新增一個 OTHER_CFLAGS,如下:

xcodebuild build OTHER_CFLAGS="-fembed-bitcode" -target libTestStaticSDK ...

另外一種解決方案是,在靜態庫 Xcode 工程的 Build Settings 中,新增一個 "User-Define Setting",內容為:'BITCODE_GENERATION_MODE' => 'bitcode',如下圖所示:

「 iOS知識小集 」2018 · 第 22 期

這樣在使用 xcodebuild 命令時就不用新增 OTHER_CFLAGS="-fembed-bitcode" 了。

綜上,為了通用,我們可以在 xcodebuild 命令後同時新增上述兩種標識,因此一個完整的靜態庫打包指令碼大致如下(同樣適用於 Framework 的打包):

「 iOS知識小集 」2018 · 第 22 期

參考連結

How do I xcodebuild a static library with Bitcode enabled?

https://stackoverflow.com/questions/31486232/how-do-i-xcodebuild-a-static-library-with-bitcode-enabled

iOS 中動/靜態庫支援 Bitcode 的問題

https://juejin.im/post/5ab311c76fb9a028c42e18a9

Swift 版本建私有庫時需要注意的地方

作者: 這個湯圓沒有餡

利用 cocoapods 建 swift 版本私有庫步驟和 OC 版本一樣,只要把語言 Objc 切換成 Swift 即可。一般情況下,pod lib lint驗證會報警告,如下圖,加 --allow-warnings 直接忽略即可。

「 iOS知識小集 」2018 · 第 22 期

但是如果私有庫裡依賴了其他三方庫,且該三方庫的 swift 版本不一致,則 pod lib lint 會報一堆 error,如下圖。

「 iOS知識小集 」2018 · 第 22 期

這個時候就需要根據警告裡的提示配置 .swift-version。該檔案預設情況是不會有的,需要手動新增,如下圖。這個時候再次執行 pod lib lint --allow-warnings 驗證就能通過。

關注我們

歡迎關注我們的公眾號:iOS-Tips,也歡迎加入我們的群組討論問題。可以公眾號留言 ios、flutter、web、pwa、小程式 等關鍵詞獲取入群方式。

「 iOS知識小集 」2018 · 第 22 期

相關文章