弱引用動態(tài)庫
弱引用動態(tài)庫:標(biāo)記
-weak_framework
參數(shù)供炎,允許在運(yùn)行時不鏈接該動態(tài)庫
正常情況下辨图,運(yùn)行時找不到動態(tài)庫所在位置,程序崩潰并提示
image not found
搭建
LGApp
項目,將動態(tài)庫SYTimer.framework
拷貝到項目根目錄
打開
LGApp
項目崩瓤,創(chuàng)建xcconfig
文件,并配置到Tatget
上踩官,寫入以下代碼:HEADER_SEARCH_PATHS = $(inherited) ${SRCROOT}/SYTimer.framework/Headers FRAMEWORK_SEARCH_PATHS = $(inherited) ${SRCROOT} OTHER_LDFLAGS = $(inherited) -framework "SYTimer"
- 指定頭文件路徑
Header Search Paths
- 指定
Framework
所在目錄Framework Search Paths
- 指定鏈接
Framework
的名稱Other Linker Flags -framework SYTimer
配置鏈接
Framework
三要素却桶,編譯可以成功。但運(yùn)行時蔗牡,程序崩潰dyld: Library not loaded: @rpath/SYTimer.framework/SYTimer Referenced from: /Users/zang/Library/Developer/CoreSimulator/Devices/BC871859-6A76-4967-A245-287615D883E6/data/Containers/Bundle/Application/BF848C5E-4E7E-440C-B266-6FEAD05BB6B2/LGApp.app/LGApp Reason: image not found
使用
-weak-l<library name>
或-weak_framework <framework name>
指定動態(tài)庫為weak imports
颖系。如果在運(yùn)行時找不到該庫,會自動將該庫的地址及內(nèi)容返回NULL
使用
man ld
查看ld
命令辩越,找到-weak_framework
參數(shù)
-weak_framework
:標(biāo)記為弱引用動態(tài)庫嘁扼。運(yùn)行時找不到地址不會報錯,而是返回一個NULL
打開
xcconfig
文件区匣,修改OTHER_LDFLAGS
配置項:OTHER_LDFLAGS = $(inherited) -Xlinker -weak_framework -Xlinker "SYTimer"
項目運(yùn)行成功偷拔,輸出內(nèi)容如下:
2021-03-08 17:46:30.286532+0800 LGApp[3397:9187180] (null)
使用
-weak_framework
標(biāo)記為弱引用動態(tài)庫蒋院,Mach-O
中記錄的Load Command
名稱不再是LC_LOAD_DYLIB
,變?yōu)?code>LC_LOAD_WEAK_DYLIB使用
otool -l test | grep 'DYLIB' -A 2
命令莲绰,查看Mach-O
中動態(tài)庫的路徑cmd LC_LOAD_WEAK_DYLIB cmdsize 64 name @rpath/SYTimer.framework/SYTimer (offset 24) -- cmd LC_LOAD_DYLIB cmdsize 88 name /System/Library/Frameworks/Foundation.framework/Foundation (offset 24)
靜態(tài)庫代碼沖突
搭建
LGApp
項目欺旧,將靜態(tài)庫AFNetworking
代碼,在項目根目錄下拷貝兩份
蛤签。將靜態(tài)庫目錄辞友,分別命名為AFNetworking
和AFNetworking2
打開
AFNetworking2
目錄,將libAFNetworking.a
文件震肮,重命名為libAFNetworking2.a
打開
LGApp
項目称龙,創(chuàng)建xcconfig
文件,并配置到Tatget
上戳晌,寫入以下代碼:HEADER_SEARCH_PATHS = $(inherited) "${SRCROOT}/AFNetworking" "${SRCROOT}/AFNetworking2" LIBRARY_SEARCH_PATHS = $(inherited) "${SRCROOT}/AFNetworking" "${SRCROOT}/AFNetworking2" OTHER_LDFLAGS = $(inherited) -l"AFNetworking" -l"AFNetworking2"
此時編譯可以通過鲫尊,因為鏈接靜態(tài)庫默認(rèn)使用
-noall_load
參數(shù)。當(dāng)鏈接靜態(tài)庫AFNetworking
找到代碼后沦偎,就不會鏈接靜態(tài)庫AFNetworking2
但真實項目中疫向,我們使用
Pods
導(dǎo)入的三方庫,大部分使用-all_load
或-ObjC
參數(shù)豪嚎,此時問題出現(xiàn)了打開
xcconfig
文件搔驼,修改OTHER_LDFLAGS
配置項:OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -l"AFNetworking2"
編譯報錯,出現(xiàn)大量的重復(fù)符號
ld: 223 duplicate symbols for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
嘗試解決:
打開
xcconfig
文件侈询,修改OTHER_LDFLAGS
配置項:OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -l"AFNetworking2" -Xlinker -force_load -Xlinker "${SRCROOT}/AFNetworking/libAFNetworking.a" -Xlinker -load_hidden -Xlinker "${SRCROOT}/AFNetworking2/libAFNetworking2.a"
- 使用
-force_load
參數(shù)舌涨,強(qiáng)制鏈接的靜態(tài)庫AFNetworking
- 使用
-load_hidden
參數(shù),將靜態(tài)庫AFNetworking2
的所有符號設(shè)置為隱藏編譯報錯扔字,依然提示重復(fù)符號
ld: 223 duplicate symbols for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
結(jié)論:如果導(dǎo)入相同靜態(tài)庫囊嘉,又指定了
-all_load
或-ObjC
參數(shù),建議對靜態(tài)庫重新打包啦租,刪除重復(fù)的Symbol
動態(tài)庫鏈接動態(tài)庫
搭建
LGFramework
項目
LGFramework
是一個動態(tài)庫項目哗伯,項目中使用Pods
導(dǎo)入動態(tài)庫AFNetworking
使用
Pods
向一個Framework
中導(dǎo)入三方庫荒揣,Pods
只會配置鏈接參數(shù)篷角,不會將三方庫拷貝到指定位置,也不會生成.sh
腳本
打開
LGOneObject.h
文件系任,寫入以下代碼:#import <Foundation/Foundation.h> @interface LGOneObject : NSObject - (void)testOneObject; @end
打開
LGOneObject.m
文件恳蹲,寫入以下代碼:#ifndef AFN_HEADER_PATH #define AFN_HEADER_PATH <AFNetworking/AFNetworking.h> #endif #ifndef AFN #define AFN __has_include(AFN_HEADER_PATH) #endif #if AFN #import AFN_HEADER_PATH #endif #import "LGOneObject.h" @implementation LGOneObject - (void)testOneObject { #if AFN AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager]; NSLog(@"LGFramework-----LGOneObject-----AFN: %@", manager); #else NSLog(@"LGFramework-----LGOneObject-----NO AFN"); #endif } @end
AFN_HEADER_PATH
:表示<AFNetworking/AFNetworking.h>
頭文件AFN
:表示是否存在頭文件- 導(dǎo)入頭文件:判斷
AFN
,如果存在俩滥,執(zhí)行#import AFN_HEADER_PATH
代碼testOneObject
方法:判斷AFN
嘉蕾,如果存在,初始化AFNetworkReachabilityManager
實例對象霜旧,并打印manager
對象错忱。否則打印NO AFN
打開
LGFramework.h
文件,寫入以下代碼:#import <LGFramework/LGOneObject.h>
搭建
LGApp
項目
LGApp
是一個App
項目
創(chuàng)建
MulitProject.xcworkspace
,加入LGFramework
動態(tài)庫和Pods
項目以清。LGApp
鏈接LGFramework
動態(tài)庫
- 項目結(jié)構(gòu):
LGApp(App) -> LGFramework(動態(tài)庫A) -> AFNetworking(動態(tài)庫B)
在
LGApp
項目中儿普,打開ViewController
文件,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end
運(yùn)行項目后掷倔,程序直接崩潰
dyld: Library not loaded: @rpath/AFNetworking.framework/AFNetworking Referenced from: /Users/zang/Library/Developer/Xcode/DerivedData/MulitProject-dfauhknlvaapxgbchtdxxhwuixsn/Build/Products/Debug-iphonesimulator/LGFramework.framework/LGFramework Reason: image not found
在
LGFramework
項目中眉孩,打開Pods-LGFramework.debug.xcconfig
文件,查看LD_RUNPATH_SEARCH_PATHS
配置項LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks'
來到項目編譯后的目錄勒葱,
AFNetworking.framework
存放在AFNetworking
目錄下浪汪,而AFNetworking
和LGApp.app
平級。所以按照LD_RUNPATH_SEARCH_PATHS
配置項凛虽,無法找到AFNetworking.framework
介紹以下三種解決辦法:
【方式一】
修改
LGFramework
提供的@rpath
路徑(僅適用于模擬器
)在
LGFramework
項目中死遭,創(chuàng)建xcconfig
文件,并配置到Tatget
上凯旋,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" LD_RUNPATH_SEARCH_PATHS = $(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking
- 導(dǎo)入
Pods
生成的xcconfig
- 按照
AFNetworking.framework
所在路徑殃姓,修改@rpath
路徑選擇模擬器,運(yùn)行項目瓦阐,輸出內(nèi)容如下:
2021-03-09 16:05:33.972325+0800 LGApp[10862:9536454] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x600000856920>
選擇真機(jī)蜗侈,運(yùn)行項目,程序崩潰:
dyld: Library not loaded: @rpath/AFNetworking.framework/AFNetworking Referenced from: /private/var/containers/Bundle/Application/BCCBC8EC-0333-4C46-B2E1-E024C4030916/LGApp.app/Frameworks/LGFramework.framework/LGFramework Reason: image not found
- 在設(shè)備上運(yùn)行
App
睡蟋,需要將鏈接的動態(tài)庫拷貝到App
包內(nèi)
【方式二】
使用
Pods
向LGApp
項目中導(dǎo)入動態(tài)庫AFNetworking
在
Pods
項目中踏幻,打開Podfile
文件,寫入以下代碼:platform :ios, '9.0' workspace '../MulitProject.xcworkspace' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end target 'LGApp' do project '../LGApp/LGApp.xcodeproj' use_frameworks! pod 'AFNetworking' end
選擇真機(jī)戳杀,運(yùn)行項目该面,輸出內(nèi)容如下:
2021-03-09 16:18:57.810101+0800 LGApp[1471:289515] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x280d231c0>
使用
Pods
向App
中導(dǎo)入三方庫,會生成一個.sh
腳本信卡。它的作用就是將.framework
拷貝到App
中的Frameworks
目錄
【方式三】
通過腳本隔缀,將
AFNetworking.framework
拷貝到App
中的Frameworks
目錄將
方式二
中,Pods
生成的Pods-LGApp-frameworks.sh
腳本傍菇,拷貝到LGApp
項目的根目錄
在
Pods
項目中猾瘸,打開Podfile
文件,恢復(fù)初始代碼:platform :ios, '9.0' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end
在
LGApp
項目中丢习,創(chuàng)建xcconfig
文件牵触,并配置到Tatget
上,寫入以下代碼:SCRIPT_DIR = ${SRCROOT}/Pods-LGApp-frameworks.sh
- 定義
SCRIPT_DIR
變量咐低,存儲.sh
腳本路徑在
LGApp
項目中揽思,選擇Build Phases
,在Run Script
中寫入腳本:"${SCRIPT_DIR}"
選擇真機(jī)见擦,運(yùn)行項目钉汗,輸出內(nèi)容如下:
2021-03-09 17:51:16.113484+0800 LGApp[1556:311935] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x2831fa2c0>
此時
LGApp
項目不再使用Pods
導(dǎo)入AFNetworking
動態(tài)庫羹令,而是通過腳本,將AFNetworking.framework
拷貝到App
中的Frameworks
目錄
App想使用動態(tài)庫B的方法
基于上述案例:
LGApp(App) -> LGFramework(動態(tài)庫A) -> AFNetworking(動態(tài)庫B)
如果
App
想使用動態(tài)庫B
的方法损痰,也就是讓LGApp
直接調(diào)用AFNetworking
的方法在
LGApp
項目中特恬,打開ViewController.m
文件,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> #import <AFNetworking/AFNetworking.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager]; NSLog(@"App使用動態(tài)庫B的方法:%@", manager); } @end
編譯失敗徐钠,提示錯誤信息:找不到頭文件
'AFNetworking/AFNetworking.h' file not found
介紹以下兩種解決辦法:
【方式一】
使用
Pods
向LGApp
項目中導(dǎo)入動態(tài)庫AFNetworking
在
Pods
項目中癌刽,打開Podfile
文件,寫入以下代碼:platform :ios, '9.0' workspace '../MulitProject.xcworkspace' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end target 'LGApp' do project '../LGApp/LGApp.xcodeproj' use_frameworks! pod 'AFNetworking' end
在
LGApp
項目中尝丐,打開xcconfig
文件显拜,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig"
- 導(dǎo)入
Pods
生成的xcconfig
選擇真機(jī),運(yùn)行項目爹袁,輸出內(nèi)容如下:
2021-03-09 18:32:15.142101+0800 LGApp[1583:320382] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x283afa7a0> 2021-03-09 18:32:15.142263+0800 LGApp[1583:320382] App使用動態(tài)庫B的方法:<AFNetworkReachabilityManager: 0x283afac60>
【方式二】
標(biāo)記
-reexport_framework
或-reexport_l
參數(shù)远荠,重新將AFNetworking
通過動態(tài)庫LGFramework
導(dǎo)出給LGApp
在
Pods
項目中,打開Podfile
文件失息,恢復(fù)初始代碼:platform :ios, '9.0' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end
在
LGFramework
項目中譬淳,打開xcconfig
文件,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" OTHER_LDFLAGS = -Xlinker -reexport_framework -Xlinker AFNetworking $(inherited)
- 因為
Cocoapods
生成的xcconfig
文件包含了-framework AFNetworking
參數(shù)盹兢,想要將AFNetworking
指定為-reexport_framework
邻梆,需將其放在$(inherited)
前面在
LGApp
項目中,打開xcconfig
文件绎秒,寫入以下代碼:SCRIPT_DIR = ${SRCROOT}/Pods-LGApp-frameworks.sh HEADER_SEARCH_PATHS = $(inherited) "${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AFNetworking/AFNetworking.framework/Headers" FRAMEWORK_SEARCH_PATHS = $(inherited) "${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AFNetworking"
選擇真機(jī)浦妄,運(yùn)行項目,輸出內(nèi)容如下:
2021-03-09 18:32:15.142101+0800 LGApp[1583:320382] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x283afa7a0> 2021-03-09 18:32:15.142263+0800 LGApp[1583:320382] App使用動態(tài)庫B的方法:<AFNetworkReachabilityManager: 0x283afac60>
動態(tài)庫的反向依賴
動態(tài)庫的反向依賴见芹,由于符合的作用空間剂娄,在運(yùn)行時,動態(tài)庫可以動態(tài)找到
App
的符號玄呛。所以只要在編譯期間阅懦,繞過符號未定義的錯誤即可在
LGApp
項目中,打開LGAppObject.h
文件徘铝,寫入以下代碼:#import <Foundation/Foundation.h> @interface LGAppObject : NSObject - (void)test_app; @end
在
LGApp
項目中耳胎,打開LGAppObject.m
文件,寫入以下代碼:#import "LGAppObject.h" @implementation LGAppObject - (void)test_app { NSLog(@"test_app"); } @end
在
LGFramework
項目中庭砍,打開LGOneObject
文件场晶,寫入以下代碼:#ifndef AFN_HEADER_PATH #define AFN_HEADER_PATH <AFNetworking/AFNetworking.h> #endif #ifndef AFN #define AFN __has_include(AFN_HEADER_PATH) #endif #if AFN #import AFN_HEADER_PATH #endif #import "LGOneObject.h" #import "LGAppObject.h" @implementation LGOneObject - (void)testOneObject { [[LGAppObject new] test_app]; #if AFN AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager]; NSLog(@"LGFramework-----LGOneObject-----AFN: %@", manager); #else NSLog(@"LGFramework-----LGOneObject-----NO AFN"); #endif } @end
- 導(dǎo)入
LGApp
項目中的LGAppObject.h
頭文件- 調(diào)用了
LGAppObject
的test_app
方法在
LGFramework
項目中,打開xcconfig
文件怠缸,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" HEADER_SEARCH_PATHS = $(inherited) "${SRCROOT}/../LGApp/LGApp"
- 導(dǎo)入
LGApp
項目中的頭文件編譯報錯,提示錯誤信息:
_OBJC_CLASS_$_LGAppObject
符號未定義Undefined symbols for architecture arm64: "_OBJC_CLASS_$_LGAppObject", referenced from: objc-class-ref in LGOneObject.o
介紹以下兩種解決辦法:
【方式一】
使用
-U
參數(shù)钳宪,標(biāo)記某個符號為動態(tài)查找符號在
LGFramework
項目中揭北,打開xcconfig
文件扳炬,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" HEADER_SEARCH_PATHS = $(inherited) "${SRCROOT}/../LGApp/LGApp" OTHER_LDFLAGS = -Xlinker -U -Xlinker _OBJC_CLASS_$_LGAppObject
- 使用
-U
參數(shù),標(biāo)記符號_OBJC_CLASS_$_LGAppObject
為動態(tài)查找符號選擇真機(jī)搔体,運(yùn)行項目恨樟,輸出內(nèi)容如下:
2021-03-09 19:29:53.986715+0800 LGApp[1611:332497] test_app 2021-03-09 19:29:53.987340+0800 LGApp[1611:332497] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x282785a60>
【方式二】
使用
-undefined
參數(shù),將動態(tài)庫中的符號全部標(biāo)記為動態(tài)查找符號疚俱。配置后動態(tài)庫中可以使用任意符號劝术,這樣風(fēng)險較高,不建議使用在
LGFramework
項目中呆奕,打開xcconfig
文件养晋,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" HEADER_SEARCH_PATHS = $(inherited) "${SRCROOT}/../LGApp/LGApp" OTHER_LDFLAGS = -Xlinker -undefined -Xlinker dynamic_lookup
- 使用
-undefined
參數(shù),將整個LGFramework
動態(tài)庫中的符號梁钾,都標(biāo)記為動態(tài)查找符號選擇真機(jī)绳泉,運(yùn)行項目,輸出內(nèi)容如下:
2021-03-10 09:34:26.692354+0800 LGApp[2143:427804] test_app 2021-03-10 09:34:26.693179+0800 LGApp[2143:427804] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x2828047a0>
動態(tài)庫鏈接靜態(tài)庫
搭建
LGFramework
項目
LGFramework
是一個動態(tài)庫項目姆泻,項目中使用Pods
導(dǎo)入靜態(tài)庫AFNetworking
打開
LGOneObject.h
文件零酪,寫入以下代碼:#import <Foundation/Foundation.h> @interface LGOneObject : NSObject - (void)testOneObject; @end
打開
LGOneObject.m
文件,寫入以下代碼:#ifndef AFN_HEADER_PATH #define AFN_HEADER_PATH <AFNetworking/AFNetworking.h> #endif #ifndef AFN #define AFN __has_include(AFN_HEADER_PATH) #endif #if AFN #import AFN_HEADER_PATH #endif #import "LGOneObject.h" @implementation LGOneObject - (void)testOneObject { #if AFN AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager]; NSLog(@"LGFramework-----LGOneObject-----AFN: %@", manager); #else NSLog(@"LGFramework-----LGOneObject-----NO AFN"); #endif } @end
打開
LGFramework.h
文件拇勃,寫入以下代碼:#import <LGFramework/LGOneObject.h>
搭建
LGApp
項目
LGApp
是一個App
項目
創(chuàng)建
MulitProject.xcworkspace
四苇,加入LGFramework
動態(tài)庫和Pods
項目。LGApp
鏈接LGFramework
動態(tài)庫
- 項目結(jié)構(gòu):
LGApp(App) -> LGFramework(動態(tài)庫A) -> AFNetworking(靜態(tài)庫A)
在
LGApp
項目中方咆,打開ViewController
文件蛔琅,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end
選擇真機(jī),運(yùn)行項目峻呛,輸出內(nèi)容如下:
2021-03-10 10:16:12.781430+0800 LGApp[2185:436467] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x280dc7a60>
- 動態(tài)庫
LGFramework
生成的過程中罗售,鏈接靜態(tài)庫AFNetworking
時,會把靜態(tài)庫AFNetworking
所有代碼都鏈接進(jìn)去钩述。所以編譯鏈接都不會報錯
App
想使用靜態(tài)庫AFNetworking
的方法在
LGApp
項目中寨躁,創(chuàng)建xcconfig
文件,并配置到Tatget
上牙勘,寫入以下代碼:HEADER_SEARCH_PATHS = "${SRCROOT}/../LGFramework/Pods/Headers/Public/AFNetworking" $(inherited)
- 指定
AFNetworking
頭文件路徑在
LGApp
項目中职恳,打開ViewController.m
文件,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> #import <AFNetworking.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager]; NSLog(@"App使用靜態(tài)庫AFNetworking的方法:%@", manager); } @end
選擇真機(jī)方面,運(yùn)行項目放钦,輸出內(nèi)容如下:
2021-03-10 10:20:52.143445+0800 LGApp[2189:437620] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x281490760> 2021-03-10 10:20:52.143627+0800 LGApp[2189:437620] App使用靜態(tài)庫AFNetworking的方法:<AFNetworkReachabilityManager: 0x281493d20>
- 動態(tài)庫鏈接靜態(tài)庫時,會把靜態(tài)庫所有代碼都鏈接進(jìn)去恭金。靜態(tài)庫的導(dǎo)出符號操禀,在動態(tài)庫中依然是導(dǎo)出符號。所以
App
可以直接使用
隱藏靜態(tài)庫
AFNetworking
的全局符號如果動態(tài)庫
LGFramework
不想把靜態(tài)庫AFNetworking
的全局符號(導(dǎo)出符號)暴露出去横腿,可以通過-hidden-l<libraryname>
參數(shù)隱藏靜態(tài)庫的全局符號使用
man ld
查看ld
命令颓屑,找到-hidden-l<libraryname>
參數(shù)
在
LGFramework
項目中斤寂,創(chuàng)建xcconfig
文件,并配置到Tatget
上揪惦,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" OTHER_LDFLAGS = -Xlinker -hidden-l"AFNetworking" $(inherited)
- 導(dǎo)入
Pods
生成的xcconfig
- 因為
Cocoapods
生成的xcconfig
文件包含了-framework AFNetworking
參數(shù)遍搞,想要將AFNetworking
指定為-hidden-l
,需將其放在$(inherited)
前面編譯報錯器腋,提示錯誤信息:
_OBJC_CLASS_$_AFNetworkReachabilityManager
符號未定義Undefined symbols for architecture arm64: "_OBJC_CLASS_$_AFNetworkReachabilityManager", referenced from: objc-class-ref in ViewController.o
靜態(tài)庫鏈接靜態(tài)庫
搭建
LGFramework
項目
LGFramework
是一個靜態(tài)庫項目溪猿,項目中使用Pods
導(dǎo)入靜態(tài)庫AFNetworking
打開
LGOneObject.h
文件,寫入以下代碼:#import <Foundation/Foundation.h> @interface LGOneObject : NSObject - (void)testOneObject; @end
打開
LGOneObject.m
文件纫塌,寫入以下代碼:#ifndef AFN_HEADER_PATH #define AFN_HEADER_PATH <AFNetworking/AFNetworking.h> #endif #ifndef AFN #define AFN __has_include(AFN_HEADER_PATH) #endif #if AFN #import AFN_HEADER_PATH #endif #import "LGOneObject.h" @implementation LGOneObject - (void)testOneObject { #if AFN AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager]; NSLog(@"LGFramework-----LGOneObject-----AFN: %@", manager); #else NSLog(@"LGFramework-----LGOneObject-----NO AFN"); #endif } @end
打開
LGFramework.h
文件诊县,寫入以下代碼:#import <LGFramework/LGOneObject.h>
搭建
LGApp
項目
LGApp
是一個App
項目
創(chuàng)建
MulitProject.xcworkspace
,加入LGFramework
靜態(tài)庫和Pods
項目护戳。LGApp
鏈接LGFramework
靜態(tài)庫
- 項目結(jié)構(gòu):
LGApp(App) -> LGFramework(靜態(tài)庫A) -> AFNetworking(靜態(tài)庫B)
在
LGApp
項目中翎冲,打開ViewController
文件,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end
編譯報錯媳荒,提示錯誤信息:
_OBJC_CLASS_$_AFNetworkReachabilityManager
符號未定義Undefined symbols for architecture arm64: "_OBJC_CLASS_$_AFNetworkReachabilityManager", referenced from: objc-class-ref in LGFramework(LGOneObject.o)
- 靜態(tài)庫
LGFramework
生成時抗悍,只保存了靜態(tài)庫AFNetworking
的頭文件信息或靜態(tài)庫AFNetworking
的名稱(Auto-Link
)。App
鏈接靜態(tài)庫LGFramework
后钳枕,會把靜態(tài)庫LGFramework
所有代碼都鏈接進(jìn)去缴渊。但是并不知道靜態(tài)庫AFNetworking
的位置和名稱。所以編譯報錯
介紹以下兩種解決辦法:
【方式一】
使用
Pods
向LGApp
項目中導(dǎo)入靜態(tài)庫AFNetworking
在
Pods
項目中鱼炒,打開Podfile
文件衔沼,寫入以下代碼:platform :ios, '9.0' workspace '../MulitProject.xcworkspace' target 'LGFramework' do # use_frameworks! pod 'AFNetworking' end target 'LGApp' do project '../LGApp/LGApp.xcodeproj' # use_frameworks! pod 'AFNetworking' end
選擇真機(jī),運(yùn)行項目昔瞧,輸出內(nèi)容如下:
2021-03-10 11:33:33.533189+0800 LGApp[2257:453229] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x28164b920>
【方式二】
手動配置靜態(tài)庫
AFNetworking
的路徑和名稱在
LGApp
項目中指蚁,創(chuàng)建xcconfig
文件,并配置到Tatget
上自晰,寫入以下代碼:LIBRARY_SEARCH_PATHS = $(inherited) "${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AFNetworking" OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking"
選擇真機(jī)凝化,運(yùn)行項目,輸出內(nèi)容如下:
2021-03-10 11:37:57.163689+0800 LGApp[2275:454837] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x28232b040>
靜態(tài)庫鏈接動態(tài)庫
搭建
LGFramework
項目
LGFramework
是一個靜態(tài)庫項目酬荞,項目中使用Pods
導(dǎo)入動態(tài)庫AFNetworking
打開
LGOneObject.h
文件搓劫,寫入以下代碼:#import <Foundation/Foundation.h> @interface LGOneObject : NSObject - (void)testOneObject; @end
打開
LGOneObject.m
文件,寫入以下代碼:#ifndef AFN_HEADER_PATH #define AFN_HEADER_PATH <AFNetworking/AFNetworking.h> #endif #ifndef AFN #define AFN __has_include(AFN_HEADER_PATH) #endif #if AFN #import AFN_HEADER_PATH #endif #import "LGOneObject.h" @implementation LGOneObject - (void)testOneObject { #if AFN AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager]; NSLog(@"LGFramework-----LGOneObject-----AFN: %@", manager); #else NSLog(@"LGFramework-----LGOneObject-----NO AFN"); #endif } @end
打開
LGFramework.h
文件混巧,寫入以下代碼:#import <LGFramework/LGOneObject.h>
搭建
LGApp
項目
LGApp
是一個App
項目
創(chuàng)建
MulitProject.xcworkspace
枪向,加入LGFramework
靜態(tài)庫和Pods
項目。LGApp
鏈接LGFramework
靜態(tài)庫
- 項目結(jié)構(gòu):
LGApp(App) -> LGFramework(靜態(tài)庫A) -> AFNetworking(動態(tài)庫A)
在
LGApp
項目中咧党,打開ViewController
文件秘蛔,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end
編譯報錯,提示錯誤信息:
_OBJC_CLASS_$_AFNetworkReachabilityManager
符號未定義Undefined symbols for architecture arm64: "_OBJC_CLASS_$_AFNetworkReachabilityManager", referenced from: objc-class-ref in LGFramework(LGOneObject.o)
- 靜態(tài)庫
LGFramework
生成時,只保存了動態(tài)庫AFNetworking
的名稱(Auto-Link
)缠犀。App
鏈接靜態(tài)庫LGFramework
后数苫,會把靜態(tài)庫LGFramework
所有代碼都鏈接進(jìn)去聪舒。但是并不知道動態(tài)庫AFNetworking
的位置辨液,也沒有提供@rpath
路徑。所以編譯報錯
介紹以下兩種解決辦法:
【方式一】
使用
Pods
向LGApp
項目中導(dǎo)入動態(tài)庫AFNetworking
在
Pods
項目中箱残,打開Podfile
文件滔迈,寫入以下代碼:platform :ios, '9.0' workspace '../MulitProject.xcworkspace' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end target 'LGApp' do project '../LGApp/LGApp.xcodeproj' use_frameworks! pod 'AFNetworking' end
選擇真機(jī),運(yùn)行項目被辑,輸出內(nèi)容如下:
2021-03-10 13:35:10.416174+0800 LGApp[2380:479215] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x282363440>
【方式二】
指定頭文件路徑燎悍、
Framework
所在目錄、@rpath
路徑盼理。通過腳本谈山,將AFNetworking.framework
拷貝到App
中的Frameworks
目錄將
方式一
中,Pods
生成的Pods-LGApp-frameworks.sh
腳本宏怔,拷貝到LGApp
項目的根目錄
在
Pods
項目中奏路,打開Podfile
文件,恢復(fù)初始代碼:platform :ios, '9.0' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end
在
LGApp
項目中臊诊,創(chuàng)建xcconfig
文件鸽粉,并配置到Tatget
上,寫入以下代碼:HEADER_SEARCH_PATHS = $(inherited) "${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AFNetworking/AFNetworking.framework/Headers" FRAMEWORK_SEARCH_PATHS = $(inherited) "${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AFNetworking" LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks' SCRIPT_DIR = ${SRCROOT}/../LGApp/Pods-LGApp-frameworks.sh
- 指定頭文件路徑
Header Search Paths
- 指定
Framework
所在目錄Framework Search Paths
- 指定
@rpath
路徑- 定義
SCRIPT_DIR
變量抓艳,存儲.sh
腳本路徑在
LGApp
項目中触机,選擇Build Phases
,在Run Script
中寫入腳本:"${SCRIPT_DIR}"
選擇真機(jī)玷或,運(yùn)行項目儡首,輸出內(nèi)容如下:
2021-03-10 13:46:27.990741+0800 LGApp[2393:481513] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x282a61360>
配置Cocoapods
指定動態(tài)庫+靜態(tài)庫
Cocoapods
導(dǎo)入三方庫,有些場景下偏友,需要指定某些庫為動態(tài)庫蔬胯、某些庫為靜態(tài)庫。此時配置use_frameworks!
無法滿足需求约谈,可以使用以下代碼:
platform :ios, '9.0'
target 'LGFramework' do
use_frameworks!
pod 'AFNetworking'
pod 'SDWebImage'
end
#指定需要被編譯成static_framework的庫
$static_framework = ['SDWebImage']
pre_install do |installer|
installer.pod_targets.each do |pod|
if $static_framework.include?(pod.name)
def pod.build_type;
Pod::BuildType.static_framework
end
end
end
end
自定義xcworkspace
有些復(fù)雜項目笔宿,使用的并不是
Cocoapods
提供xcworkspace
最上層是自定義的
MulitProject.xcworkspace
,包含LGApp
和LGFramework
兩個Project
棱诱。而Cocoapods
提供xcworkspace
在LGFramework
目錄中
此時往
MulitProject.xcworkspace
中的LGApp
導(dǎo)入三方庫泼橘,可以使用以下代碼:platform :ios, '9.0' workspace '../MulitProject.xcworkspace' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end target 'LGApp' do project '../LGApp/LGApp.xcodeproj' use_frameworks! pod 'AFNetworking' end
- 指定
MulitProject.xcworkspace
路徑- 往
LGApp
中導(dǎo)入三方庫,指定Project
路徑
總結(jié)
弱引用動態(tài)庫
- 標(biāo)記
-weak_framework
參數(shù)迈勋,允許在運(yùn)行時不鏈接該動態(tài)庫- 標(biāo)記為弱引用動態(tài)庫炬灭,運(yùn)行時找不到地址不會報錯,而是返回一個
NULL
靜態(tài)庫代碼沖突
- 使用
-force_load
參數(shù)靡菇,強(qiáng)制鏈接指定靜態(tài)庫- 使用
-load_hidden
參數(shù)重归,將指定靜態(tài)庫的所有符號設(shè)置為隱藏- 指定
-all_load
或-ObjC
參數(shù)米愿,建議對靜態(tài)庫重新打包,刪除重復(fù)的Symbol
App -> 動態(tài)庫A -> 動態(tài)庫B
- 使用
Pods
向App
項目中導(dǎo)入動態(tài)庫B
- 通過腳本鼻吮,將
動態(tài)庫B
拷貝到App
中的Frameworks
目錄
App
想使用動態(tài)庫B
的方法
- 使用
Pods
向App
項目中導(dǎo)入動態(tài)庫B
- 標(biāo)記
-reexport_framework
或-reexport_l
參數(shù)育苟,重新將動態(tài)庫B
通過動態(tài)庫A
導(dǎo)出給App
動態(tài)庫的反向依賴
- 使用
-U
參數(shù),標(biāo)記某個符號為動態(tài)查找符號- 使用
-undefined
參數(shù)椎木,將動態(tài)庫中的符號全部標(biāo)記為動態(tài)查找符號违柏。配置后動態(tài)庫中可以使用任意符號,這樣風(fēng)險較高香椎,不建議使用
App -> 動態(tài)庫A -> 靜態(tài)庫A
App
可以直接使用靜態(tài)庫A
的導(dǎo)出符號- 使用
-hidden-l<libraryname>
參數(shù)漱竖,隱藏靜態(tài)庫A
的全局符號(導(dǎo)出符號)
App -> 靜態(tài)庫A -> 靜態(tài)庫B
- 使用
Pods
向App
項目中導(dǎo)入靜態(tài)庫B
- 手動配置
靜態(tài)庫B
的路徑和名稱
App -> 靜態(tài)庫A -> 動態(tài)庫A
- 使用
Pods
向App
項目中導(dǎo)入動態(tài)庫A
- 指定頭文件路徑擎厢、
Framework
所在目錄枫疆、@rpath
路徑。通過腳本龙宏,將動態(tài)庫A
拷貝到App
中的Frameworks
目錄