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

知識小集發表於2018-12-04

原文連結

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

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

  • 忘記 AppleID 賬號安全問題的解決辦法
  • 對於“靜態庫”和“動態庫”的理解總結
  • Xcode 工程新增 “動態” Framework 的幾種方式
  • 不支援 __weak 修飾的類

忘記AppleID賬號安全問題的解決辦法

作者: 高老師很忙

悲劇的背景是這樣的:有一個較早時間註冊的AppleID,由於對自己記憶力的過分自信,沒有備份安全問題,並之前只在網頁端登入過,沒有在手機端登入過,並且沒有填寫過手機號和其他郵箱,各種找回安全問題的路都被堵死了。在嘗試了N次輸入錯誤答案,賬號被鎖了N次後,只能寄希望於蘋果爸爸幫我順利登入。

聯絡上蘋果技術支援,他們告訴我他們沒有許可權處理這類問題,並建議我好好回憶一下答案多嘗試幾次或者聯絡開發者支援試試;

開發者支援的電話實在太難打進去了,打了2天才打進去,得到的結果仍然是他們沒有許可權幫我處理,建議我開啟雙重認證,安全問題就自動廢除了。

那麼就又出現了一個新的難題,開啟雙重認證需要回答安全問題,感覺進入了一個死迴圈。。。。繼續給蘋果打電話,他們告訴我可以重置手機,啟用的時候登入AppleID,放置幾天,然後再在手機端開啟雙重認證,會跳過回答安全問題的步驟,問其原因,工作人員說他們也不清楚,這也不是官方做法,只是有人這樣成功過,抱著試一試的心態,果然這個辦法有效,以後還是好好備份才是王道呀!

對於“靜態庫”和“動態庫”的理解總結

作者: KANGZUBIN

通常,我們的 Xcode 工程會依賴一些第三方庫,包括:.a 靜態庫(Static Library)和 .framework 動態庫(Dynamic Library)。

不過簡單地把 .framework 字尾的檔案稱為“動態庫”並不嚴謹,因為在 iOS/macOS 開發中,framework 又分為靜態 framework動態 framework,區別如下:

  • 靜態 framework:可以理解為是 .a 靜態檔案 + .h 公共標頭檔案 + 資原始檔 的集合,本質上與 .a 靜態庫是一致的;

  • 動態 framework:即真正意義上的動態庫,一般包括動態二進位制檔案、標頭檔案和資原始檔等。

對於一個 Static Library 工程,其編譯產物為 .a 靜態二進位制檔案 + 公共 .h 標頭檔案;

對於一個 Framework 工程,其編譯的最終產物是動態庫還是靜態庫,我們可以通過在 Build Settings -> Linking -> Mach-O Type 中進行選擇設定其值為 Dynamic Library 或者 Static Library

此外,我們知道,對於一個 Mach-O 二進位制檔案,不管是 static 還是 dynamic,一般都包含了幾種不同的處理器架構(Architectures),例如:i386, x86_64, armv7, armv7s, arm64 等。

Xcode 在編譯連結時,對於靜態庫和動態庫的處理方式是不同的。

對於靜態庫,在連結時(Linking Time),Xcode 會自動篩選出靜態庫中的不同 architecture 合併到對應處理器架構的主可執行二進位制檔案中;而在打包歸檔(Archive)時,Xcode 會自動忽略掉靜態庫中未用到的 architecture,例如會移除掉 i386, x86_64 等 Mac 上模擬器專用的架構。

而對於動態庫,在編譯打包時,Xcode 會直接拷貝整個動態 framework 檔案到最終的 .ipa 包中,只有在 App 真正啟動執行時,才會進行動態連結。但是蘋果是不允許最終上傳到 App Store Connect 後臺的 .ipa 檔案包含 i386, x86_64 等模擬器架構的,會報 Invalid 錯誤,所以對於工程中的動態 framework,我們在打 Release 正式包時,一般會通過執行命令或者指令碼的方式移除掉這些 Invalid Architectures。

最後,如何在 Xcode 工程中新增這些靜態/動態庫呢?

對於 “.a 靜態庫” 和 “靜態 framework” ,直接拖拽到工程中,並勾選 Copy if needed 選項即可,無需其他設定;而對於新增“動態 framework”,稍微比較麻煩,我們將在下一條小集介紹幾種不同的方法。

以上,希望對你能有所幫助,不足之處,歡迎指出。

Xcode 工程新增 “動態” Framework 的幾種方式

作者: KANGZUBIN

在上一條小集,我們分別介紹了 “.a 靜態庫”、“靜態 framework” 和 “動態 framework” 的異同。

接下來我們將介紹一下,如何在 Xcode 工程中新增動態庫(Dynamic Library)。

首先我們知道,對於 “.a 靜態庫” 和 “靜態 framework”,直接把相關檔案拖拽到工程中,並勾選 Copy if needed 選項即可,無需其它額外的設定;

而對於新增“動態 framework”,稍微比較麻煩,主要有以下幾種方式。

PS:我們這裡說的“新增動態庫”是指第三方動態庫,而不是像 UIKit.framework、Foundation.framework 或者 libc++ 等系統自帶的動態庫,對於它們的依賴新增很簡單,直接在 General -> Linked Frameworks and Libraries 中點選加號搜尋新增即可。

手動方式

在 Xcode 工程中選中 app 對應的 target,然後在 General -> Embedded Binaries 下點選加號,如圖 1,在彈出的視窗選擇 Add Other...,最後在 Finder 中選擇你要新增的“動態 framework”,並勾選 Copy if needed 即可。需要注意的是,你不能直接在 Finder 中把 .framework 檔案拖拽到 Embedded Binaries 中,否則會報錯。

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

關於手動新增動態庫的更多細節以及遇到問題的解決辦法,可參考蘋果官方的教程:《Embedding Frameworks In An App》

但是!這種方式看似很方便,其實有個坑是:我們上一條小集提到,一般動態二進位制檔案都會包含很多處理器架構,例如:i386, x86_64, armv7, armv7s, arm64 等,然後 Xcode 在編譯連結時,對動態二進位制檔案是直接拷貝到 .ipa 包中,並不會像連結靜態庫那樣篩選掉未用到 architecture,而蘋果又不允許把包含 i386, x86_64 等模擬器架構的包上傳到 App Store Connect 後臺,會報錯。因此,我們在打 Release 正式包時往往需要手動通過 lipo 命令或者編寫指令碼移除掉這些 Invalid Architectures。(除非你的開發工程只通過真機來除錯,不準備在模擬器裡執行,且新增的動態庫剛好又不包含 i386、x86_64)

使用 Carthage 整合

對於通過 Carthage 整合的第三方庫,在 Cartfile 檔案中新增好依賴後,然後執行 carthage update 命令會幫我們生成一個個“動態 framework”,例如 AFNetworking.framework、SDWebImage.framework 等,然後把它們拖拽到工程中,詳細可參考 Carthage 的 Quick Start 教程。

這裡有個關鍵操作是,需要在 Xcode 工程的 Build Phases 中新增一個執行指令碼(New Run Script Phase),並在指令碼中執行如下命令:

/usr/local/bin/carthage copy-frameworks
複製程式碼

該命令的作用大概就是,在打包拷貝動態庫時自動幫我們移除掉其中的 i386、x86_64。

使用 CocoaPods 整合

同樣地,通過 CocoaPods 整合動態庫時,也會在工程中自動幫我們新增一個 Shell 指令碼用於做這件事,如圖 2 中的 [CP] Embed Pods Frameworks,大家可以自行查閱該 Pods-xxx-frameworks.sh 指令碼的內容,裡面有個函式 strip_invalid_archs() 就是用於在打包時移除無用的處理器架構。

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

因此,我們可以把自己開發的或者他人提供的動態 framework,通過 CocoaPods 來整合到工程中:建立一個 Pods 私有 git 庫(相信大家已經很熟悉了),在 git 庫中新增相關動態 .frameworks 檔案,然後其 Podspec 檔案的寫法大致如圖 3 所示,最後在你的工程中 pod install 即可。

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

最後我們思考一個問題:“靜態 framework” 和 “動態 framework” 在使用上似乎也沒什麼不同,而工程新增 “動態 framework” 又比較繁瑣,那麼在 iOS/macOS 開發中什麼情況下會使用動態庫呢?

不支援 __weak 修飾的類

作者: 夏天是一隻貓巛

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

如 NSMachPort。另外自定義的類實現了 allowsWeakReference/retainWeakReference 例項方法返回 NO(預設返回YES)也不能用 __weak 修飾。allowsWeakReference 返回 NO 後,使用後會異常終止。如下圖:

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

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

使用 retainWeakReference 返回 NO 後不會崩潰,但是 __weak 值為null,如下圖。也可以在在該方法內部控制物件的 weak 次數。

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

關注我們

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

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

相關文章