iOS一些常見配置

來源:互聯網
上載者:User

標籤:blog   http   io   ar   os   使用   sp   for   檔案   

關於Xcode的Other Linker Flags

背景

在ios開發過程中,有時候會用到第三方的靜態庫(.a檔案),然後匯入後發現編譯正常但運行時會出現selector not recognized的錯誤,從而導致app閃退。接著仔細閱讀庫檔案的說明文檔,你可能會在文檔中發現諸如在Other Linker Flags中加入-ObjC或者-all_load這樣的解決方案。

那麼,Other Linker Flags到底是用來幹什麼的呢?還有-ObjC-all_load到底發揮了什麼作用呢?

連結器

首先,要說明一下Other Linker Flags到底是用來幹嘛的。說白了,就是ld命令除了預設參數外的其他參數。ld命令實現的是連結器的工作,詳細說明可以在終端man ld查看。

如果有人不清楚連結器是什麼東西的話,我可以作個簡單的說明。

一個程式從簡單易讀的代碼到可執行檔往往要經曆以下步驟:

原始碼 > 前置處理器 > 編譯器 > 彙編器 > 機器碼 > 連結器 > 可執行檔

源檔案經過一系列處理以後,會產生對應的.obj檔案,然後一個項目必然會有許多.obj檔案,並且這些檔案之間會有各種各樣的聯絡,例如函數調用。連結器做的事就是把這些目標檔案和所用的一些庫連結在一起形成一個完整的可執行檔。

可能我描述的比較膚淺,因為我自己瞭解的也不是很深,建議大家讀一下這篇文章,可以對連結器做的事情有個大概的瞭解:連結器做了什麼

為什麼會閃退

蘋果官方Q&A上有這麼一段話:

The "selector not recognized" runtime exception occurs due to an issue between the implementation of standard UNIX static libraries, the linker and the dynamic nature of Objective-C. Objective-C does not define linker symbols for each function (or method, in Objective-C) - instead, linker symbols are only generated for each class. If you extend a pre-existing class with categories, the linker does not know to associate the object code of the core class implementation and the category implementation. This prevents objects created in the resulting application from responding to a selector that is defined in the category.

翻譯過來,大概意思就是Objective-C的連結器並不會為每個方法建立符號表,而是僅僅為類建立了符號表。這樣的話,如果靜態庫中定義了已存在的一個類的分類,連結器就會以為這個類已經存在,不會把分類和核心類的代碼合起來。這樣的話,在最後的可執行檔中,就會缺少分類裡的代碼,這樣函數調用就失敗了。

解決方案

解決方案在背景那塊我就提到了,就是在Other Linker Flags裡加上所需的參數,用到的參數一般有以下3個:

  • -ObjC
  • -all_load
  • -force_load

下面來說說每個參數存在的意義和具體做的事情。

首先是-ObjC,一般這個參數足夠解決前面提到的問題,蘋果官方說明如下:

This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application), it will allow the successful creation of effective Objective-C static libraries that contain categories on existing classes.

簡單說來,加了這個參數後,連結器就會把靜態庫中所有的Objective-C類和分類都載入到最後的可執行檔中,雖然這樣可能會因為載入了很多不必要的檔案而導致可執行檔變大,但是這個參數很好地解決了我們所遇到的問題。但是事實真的是這樣的嗎?

如果-ObjC參數真的這麼有效,那麼事情就會簡單多了。

Important: For 64-bit and iPhone OS applications, there is a linker bug that prevents -ObjC from loading objects files from static libraries that contain only categories and no classes. The workaround is to use the -allload or -forceload flags.

當靜態庫中只有分類而沒有類的時候,-ObjC參數就會失效了。這時候,就需要使用-all_load或者-force_load了。

-all_load會讓連結器把所有找到的目標檔案都載入到可執行檔中,但是千萬不要隨便使用這個參數!假如你使用了不止一個靜態庫檔案,然後又使用了這個參數,那麼你很有可能會遇到ld: duplicate symbol錯誤,因為不同的庫檔案裡面可能會有相同的目標檔案,所以建議在遇到-ObjC失效的情況下使用-force_load參數。

-force_load所做的事情跟-all_load其實是一樣的,但是-force_load需要指定要進行全部載入的庫檔案的路徑,這樣的話,你就只是完全載入了一個庫檔案,不影響其餘庫檔案的按需載入。

 

 

 

 

iOS一些常見配置

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.