弱引用動(dòng)態(tài)庫
弱引用動(dòng)態(tài)庫:標(biāo)記
-weak_framework
參數(shù),允許在運(yùn)行時(shí)不鏈接該動(dòng)態(tài)庫
正常情況下,運(yùn)行時(shí)找不到動(dòng)態(tài)庫所在位置,程序崩潰并提示
image not found
搭建
LGApp
項(xiàng)目,將動(dòng)態(tài)庫SYTimer.framework
拷貝到項(xiàng)目根目錄
打開
LGApp
項(xiàng)目,創(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)行時(shí),程序崩潰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>
指定動(dòng)態(tài)庫為weak imports
。如果在運(yùn)行時(shí)找不到該庫,會(huì)自動(dòng)將該庫的地址及內(nèi)容返回NULL
使用
man ld
查看ld
命令,找到-weak_framework
參數(shù)
-weak_framework
:標(biāo)記為弱引用動(dòng)態(tài)庫。運(yùn)行時(shí)找不到地址不會(huì)報(bào)錯(cuò),而是返回一個(gè)NULL
打開
xcconfig
文件,修改OTHER_LDFLAGS
配置項(xiàng):OTHER_LDFLAGS = $(inherited) -Xlinker -weak_framework -Xlinker "SYTimer"
項(xiàng)目運(yùn)行成功,輸出內(nèi)容如下:
2021-03-08 17:46:30.286532+0800 LGApp[3397:9187180] (null)
使用
-weak_framework
標(biāo)記為弱引用動(dòng)態(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
中動(dòng)態(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
項(xiàng)目,將靜態(tài)庫AFNetworking
代碼,在項(xiàng)目根目錄下拷貝兩份
。將靜態(tài)庫目錄,分別命名為AFNetworking
和AFNetworking2
打開
AFNetworking2
目錄,將libAFNetworking.a
文件,重命名為libAFNetworking2.a
打開
LGApp
項(xiàng)目,創(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"
此時(shí)編譯可以通過,因?yàn)殒溄屿o態(tài)庫默認(rèn)使用
-noall_load
參數(shù)。當(dāng)鏈接靜態(tài)庫AFNetworking
找到代碼后,就不會(huì)鏈接靜態(tài)庫AFNetworking2
但真實(shí)項(xiàng)目中,我們使用
Pods
導(dǎo)入的三方庫,大部分使用-all_load
或-ObjC
參數(shù),此時(shí)問題出現(xiàn)了打開
xcconfig
文件,修改OTHER_LDFLAGS
配置項(xiàng):OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -l"AFNetworking2"
編譯報(bào)錯(cuò),出現(xiàn)大量的重復(fù)符號(hào)
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
配置項(xiàng):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
的所有符號(hào)設(shè)置為隱藏編譯報(bào)錯(cuò),依然提示重復(fù)符號(hào)
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
動(dòng)態(tài)庫鏈接動(dòng)態(tài)庫
搭建
LGFramework
項(xiàng)目
LGFramework
是一個(gè)動(dòng)態(tài)庫項(xiàng)目,項(xiàng)目中使用Pods
導(dǎo)入動(dòng)態(tài)庫AFNetworking
使用
Pods
向一個(gè)Framework
中導(dǎo)入三方庫,Pods
只會(huì)配置鏈接參數(shù),不會(huì)將三方庫拷貝到指定位置,也不會(huì)生成.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
實(shí)例對象,并打印manager
對象。否則打印NO AFN
打開
LGFramework.h
文件,寫入以下代碼:#import <LGFramework/LGOneObject.h>
搭建
LGApp
項(xiàng)目
LGApp
是一個(gè)App
項(xiàng)目
創(chuàng)建
MulitProject.xcworkspace
,加入LGFramework
動(dòng)態(tài)庫和Pods
項(xiàng)目。LGApp
鏈接LGFramework
動(dòng)態(tài)庫
- 項(xiàng)目結(jié)構(gòu):
LGApp(App) -> LGFramework(動(dòng)態(tài)庫A) -> AFNetworking(動(dòng)態(tài)庫B)
在
LGApp
項(xiàng)目中,打開ViewController
文件,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end
運(yùn)行項(xiàng)目后,程序直接崩潰
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
項(xiàng)目中,打開Pods-LGFramework.debug.xcconfig
文件,查看LD_RUNPATH_SEARCH_PATHS
配置項(xiàng)LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' '@executable_path/../../Frameworks'
來到項(xiàng)目編譯后的目錄,
AFNetworking.framework
存放在AFNetworking
目錄下,而AFNetworking
和LGApp.app
平級(jí)。所以按照LD_RUNPATH_SEARCH_PATHS
配置項(xiàng),無法找到AFNetworking.framework
介紹以下三種解決辦法:
【方式一】
修改
LGFramework
提供的@rpath
路徑(僅適用于模擬器
)在
LGFramework
項(xiàng)目中,創(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)行項(xiàng)目,輸出內(nèi)容如下:
2021-03-09 16:05:33.972325+0800 LGApp[10862:9536454] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x600000856920>
選擇真機(jī),運(yùn)行項(xiàng)目,程序崩潰:
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
,需要將鏈接的動(dòng)態(tài)庫拷貝到App
包內(nèi)
【方式二】
使用
Pods
向LGApp
項(xiàng)目中導(dǎo)入動(dòng)態(tài)庫AFNetworking
在
Pods
項(xiàng)目中,打開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)行項(xiàng)目,輸出內(nèi)容如下:
2021-03-09 16:18:57.810101+0800 LGApp[1471:289515] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x280d231c0>
使用
Pods
向App
中導(dǎo)入三方庫,會(huì)生成一個(gè).sh
腳本。它的作用就是將.framework
拷貝到App
中的Frameworks
目錄
【方式三】
通過腳本,將
AFNetworking.framework
拷貝到App
中的Frameworks
目錄將
方式二
中,Pods
生成的Pods-LGApp-frameworks.sh
腳本,拷貝到LGApp
項(xiàng)目的根目錄
在
Pods
項(xiàng)目中,打開Podfile
文件,恢復(fù)初始代碼:platform :ios, '9.0' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end
在
LGApp
項(xiàng)目中,創(chuàng)建xcconfig
文件,并配置到Tatget
上,寫入以下代碼:SCRIPT_DIR = ${SRCROOT}/Pods-LGApp-frameworks.sh
- 定義
SCRIPT_DIR
變量,存儲(chǔ).sh
腳本路徑在
LGApp
項(xiàng)目中,選擇Build Phases
,在Run Script
中寫入腳本:"${SCRIPT_DIR}"
選擇真機(jī),運(yùn)行項(xiàng)目,輸出內(nèi)容如下:
2021-03-09 17:51:16.113484+0800 LGApp[1556:311935] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x2831fa2c0>
此時(shí)
LGApp
項(xiàng)目不再使用Pods
導(dǎo)入AFNetworking
動(dòng)態(tài)庫,而是通過腳本,將AFNetworking.framework
拷貝到App
中的Frameworks
目錄
App想使用動(dòng)態(tài)庫B的方法
基于上述案例:
LGApp(App) -> LGFramework(動(dòng)態(tài)庫A) -> AFNetworking(動(dòng)態(tài)庫B)
如果
App
想使用動(dòng)態(tài)庫B
的方法,也就是讓LGApp
直接調(diào)用AFNetworking
的方法在
LGApp
項(xiàng)目中,打開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使用動(dòng)態(tài)庫B的方法:%@", manager); } @end
編譯失敗,提示錯(cuò)誤信息:找不到頭文件
'AFNetworking/AFNetworking.h' file not found
介紹以下兩種解決辦法:
【方式一】
使用
Pods
向LGApp
項(xiàng)目中導(dǎo)入動(dòng)態(tài)庫AFNetworking
在
Pods
項(xiàng)目中,打開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
項(xiàng)目中,打開xcconfig
文件,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig"
- 導(dǎo)入
Pods
生成的xcconfig
選擇真機(jī),運(yùn)行項(xiàng)目,輸出內(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使用動(dòng)態(tài)庫B的方法:<AFNetworkReachabilityManager: 0x283afac60>
【方式二】
標(biāo)記
-reexport_framework
或-reexport_l
參數(shù),重新將AFNetworking
通過動(dòng)態(tài)庫LGFramework
導(dǎo)出給LGApp
在
Pods
項(xiàng)目中,打開Podfile
文件,恢復(fù)初始代碼:platform :ios, '9.0' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end
在
LGFramework
項(xiàng)目中,打開xcconfig
文件,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" OTHER_LDFLAGS = -Xlinker -reexport_framework -Xlinker AFNetworking $(inherited)
- 因?yàn)?code>Cocoapods生成的
xcconfig
文件包含了-framework AFNetworking
參數(shù),想要將AFNetworking
指定為-reexport_framework
,需將其放在$(inherited)
前面在
LGApp
項(xiàng)目中,打開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)行項(xiàng)目,輸出內(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使用動(dòng)態(tài)庫B的方法:<AFNetworkReachabilityManager: 0x283afac60>
動(dòng)態(tài)庫的反向依賴
動(dòng)態(tài)庫的反向依賴,由于符合的作用空間,在運(yùn)行時(shí),動(dòng)態(tài)庫可以動(dòng)態(tài)找到
App
的符號(hào)。所以只要在編譯期間,繞過符號(hào)未定義的錯(cuò)誤即可在
LGApp
項(xiàng)目中,打開LGAppObject.h
文件,寫入以下代碼:#import <Foundation/Foundation.h> @interface LGAppObject : NSObject - (void)test_app; @end
在
LGApp
項(xiàng)目中,打開LGAppObject.m
文件,寫入以下代碼:#import "LGAppObject.h" @implementation LGAppObject - (void)test_app { NSLog(@"test_app"); } @end
在
LGFramework
項(xiàng)目中,打開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
項(xiàng)目中的LGAppObject.h
頭文件- 調(diào)用了
LGAppObject
的test_app
方法在
LGFramework
項(xiàng)目中,打開xcconfig
文件,寫入以下代碼:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" HEADER_SEARCH_PATHS = $(inherited) "${SRCROOT}/../LGApp/LGApp"
- 導(dǎo)入
LGApp
項(xiàng)目中的頭文件編譯報(bào)錯(cuò),提示錯(cuò)誤信息:
_OBJC_CLASS_$_LGAppObject
符號(hào)未定義Undefined symbols for architecture arm64: "_OBJC_CLASS_$_LGAppObject", referenced from: objc-class-ref in LGOneObject.o
介紹以下兩種解決辦法:
【方式一】
使用
-U
參數(shù),標(biāo)記某個(gè)符號(hào)為動(dòng)態(tài)查找符號(hào)在
LGFramework
項(xiàng)目中,打開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)記符號(hào)_OBJC_CLASS_$_LGAppObject
為動(dòng)態(tài)查找符號(hào)選擇真機(jī),運(yùn)行項(xiàng)目,輸出內(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ù),將動(dòng)態(tài)庫中的符號(hào)全部標(biāo)記為動(dòng)態(tài)查找符號(hào)。配置后動(dòng)態(tài)庫中可以使用任意符號(hào),這樣風(fēng)險(xiǎn)較高,不建議使用在
LGFramework
項(xiàng)目中,打開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ù),將整個(gè)LGFramework
動(dòng)態(tài)庫中的符號(hào),都標(biāo)記為動(dòng)態(tài)查找符號(hào)選擇真機(jī),運(yùn)行項(xiàng)目,輸出內(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>
動(dòng)態(tài)庫鏈接靜態(tài)庫
搭建
LGFramework
項(xiàng)目
LGFramework
是一個(gè)動(dòng)態(tài)庫項(xiàng)目,項(xiàng)目中使用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
項(xiàng)目
LGApp
是一個(gè)App
項(xiàng)目
創(chuàng)建
MulitProject.xcworkspace
,加入LGFramework
動(dòng)態(tài)庫和Pods
項(xiàng)目。LGApp
鏈接LGFramework
動(dòng)態(tài)庫
- 項(xiàng)目結(jié)構(gòu):
LGApp(App) -> LGFramework(動(dòng)態(tài)庫A) -> AFNetworking(靜態(tài)庫A)
在
LGApp
項(xiàng)目中,打開ViewController
文件,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end
選擇真機(jī),運(yùn)行項(xiàng)目,輸出內(nèi)容如下:
2021-03-10 10:16:12.781430+0800 LGApp[2185:436467] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x280dc7a60>
- 動(dòng)態(tài)庫
LGFramework
生成的過程中,鏈接靜態(tài)庫AFNetworking
時(shí),會(huì)把靜態(tài)庫AFNetworking
所有代碼都鏈接進(jìn)去。所以編譯鏈接都不會(huì)報(bào)錯(cuò)
App
想使用靜態(tài)庫AFNetworking
的方法在
LGApp
項(xiàng)目中,創(chuàng)建xcconfig
文件,并配置到Tatget
上,寫入以下代碼:HEADER_SEARCH_PATHS = "${SRCROOT}/../LGFramework/Pods/Headers/Public/AFNetworking" $(inherited)
- 指定
AFNetworking
頭文件路徑在
LGApp
項(xiàng)目中,打開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)行項(xiàng)目,輸出內(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>
- 動(dòng)態(tài)庫鏈接靜態(tài)庫時(shí),會(huì)把靜態(tài)庫所有代碼都鏈接進(jìn)去。靜態(tài)庫的導(dǎo)出符號(hào),在動(dòng)態(tài)庫中依然是導(dǎo)出符號(hào)。所以
App
可以直接使用
隱藏靜態(tài)庫
AFNetworking
的全局符號(hào)如果動(dòng)態(tài)庫
LGFramework
不想把靜態(tài)庫AFNetworking
的全局符號(hào)(導(dǎo)出符號(hào))暴露出去,可以通過-hidden-l<libraryname>
參數(shù)隱藏靜態(tài)庫的全局符號(hào)使用
man ld
查看ld
命令,找到-hidden-l<libraryname>
參數(shù)
在
LGFramework
項(xiàng)目中,創(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
- 因?yàn)?code>Cocoapods生成的
xcconfig
文件包含了-framework AFNetworking
參數(shù),想要將AFNetworking
指定為-hidden-l
,需將其放在$(inherited)
前面編譯報(bào)錯(cuò),提示錯(cuò)誤信息:
_OBJC_CLASS_$_AFNetworkReachabilityManager
符號(hào)未定義Undefined symbols for architecture arm64: "_OBJC_CLASS_$_AFNetworkReachabilityManager", referenced from: objc-class-ref in ViewController.o
靜態(tài)庫鏈接靜態(tài)庫
搭建
LGFramework
項(xiàng)目
LGFramework
是一個(gè)靜態(tài)庫項(xiàng)目,項(xiàng)目中使用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
項(xiàng)目
LGApp
是一個(gè)App
項(xiàng)目
創(chuàng)建
MulitProject.xcworkspace
,加入LGFramework
靜態(tài)庫和Pods
項(xiàng)目。LGApp
鏈接LGFramework
靜態(tài)庫
- 項(xiàng)目結(jié)構(gòu):
LGApp(App) -> LGFramework(靜態(tài)庫A) -> AFNetworking(靜態(tài)庫B)
在
LGApp
項(xiàng)目中,打開ViewController
文件,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end
編譯報(bào)錯(cuò),提示錯(cuò)誤信息:
_OBJC_CLASS_$_AFNetworkReachabilityManager
符號(hào)未定義Undefined symbols for architecture arm64: "_OBJC_CLASS_$_AFNetworkReachabilityManager", referenced from: objc-class-ref in LGFramework(LGOneObject.o)
- 靜態(tài)庫
LGFramework
生成時(shí),只保存了靜態(tài)庫AFNetworking
的頭文件信息或靜態(tài)庫AFNetworking
的名稱(Auto-Link
)。App
鏈接靜態(tài)庫LGFramework
后,會(huì)把靜態(tài)庫LGFramework
所有代碼都鏈接進(jìn)去。但是并不知道靜態(tài)庫AFNetworking
的位置和名稱。所以編譯報(bào)錯(cuò)
介紹以下兩種解決辦法:
【方式一】
使用
Pods
向LGApp
項(xiàng)目中導(dǎo)入靜態(tài)庫AFNetworking
在
Pods
項(xiàng)目中,打開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)行項(xiàng)目,輸出內(nèi)容如下:
2021-03-10 11:33:33.533189+0800 LGApp[2257:453229] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x28164b920>
【方式二】
手動(dòng)配置靜態(tài)庫
AFNetworking
的路徑和名稱在
LGApp
項(xiàng)目中,創(chuàng)建xcconfig
文件,并配置到Tatget
上,寫入以下代碼:LIBRARY_SEARCH_PATHS = $(inherited) "${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AFNetworking" OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking"
選擇真機(jī),運(yùn)行項(xiàng)目,輸出內(nèi)容如下:
2021-03-10 11:37:57.163689+0800 LGApp[2275:454837] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x28232b040>
靜態(tài)庫鏈接動(dòng)態(tài)庫
搭建
LGFramework
項(xiàng)目
LGFramework
是一個(gè)靜態(tài)庫項(xiàng)目,項(xiàng)目中使用Pods
導(dǎo)入動(dòng)態(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
項(xiàng)目
LGApp
是一個(gè)App
項(xiàng)目
創(chuàng)建
MulitProject.xcworkspace
,加入LGFramework
靜態(tài)庫和Pods
項(xiàng)目。LGApp
鏈接LGFramework
靜態(tài)庫
- 項(xiàng)目結(jié)構(gòu):
LGApp(App) -> LGFramework(靜態(tài)庫A) -> AFNetworking(動(dòng)態(tài)庫A)
在
LGApp
項(xiàng)目中,打開ViewController
文件,寫入以下代碼:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end
編譯報(bào)錯(cuò),提示錯(cuò)誤信息:
_OBJC_CLASS_$_AFNetworkReachabilityManager
符號(hào)未定義Undefined symbols for architecture arm64: "_OBJC_CLASS_$_AFNetworkReachabilityManager", referenced from: objc-class-ref in LGFramework(LGOneObject.o)
- 靜態(tài)庫
LGFramework
生成時(shí),只保存了動(dòng)態(tài)庫AFNetworking
的名稱(Auto-Link
)。App
鏈接靜態(tài)庫LGFramework
后,會(huì)把靜態(tài)庫LGFramework
所有代碼都鏈接進(jìn)去。但是并不知道動(dòng)態(tài)庫AFNetworking
的位置,也沒有提供@rpath
路徑。所以編譯報(bào)錯(cuò)
介紹以下兩種解決辦法:
【方式一】
使用
Pods
向LGApp
項(xiàng)目中導(dǎo)入動(dòng)態(tài)庫AFNetworking
在
Pods
項(xiàng)目中,打開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)行項(xiàng)目,輸出內(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
項(xiàng)目的根目錄
在
Pods
項(xiàng)目中,打開Podfile
文件,恢復(fù)初始代碼:platform :ios, '9.0' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end
在
LGApp
項(xiàng)目中,創(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
變量,存儲(chǔ).sh
腳本路徑在
LGApp
項(xiàng)目中,選擇Build Phases
,在Run Script
中寫入腳本:"${SCRIPT_DIR}"
選擇真機(jī),運(yùn)行項(xiàng)目,輸出內(nèi)容如下:
2021-03-10 13:46:27.990741+0800 LGApp[2393:481513] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x282a61360>
配置Cocoapods
指定動(dòng)態(tài)庫+靜態(tài)庫
Cocoapods
導(dǎo)入三方庫,有些場景下,需要指定某些庫為動(dòng)態(tài)庫、某些庫為靜態(tài)庫。此時(shí)配置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ù)雜項(xiàng)目,使用的并不是
Cocoapods
提供xcworkspace
最上層是自定義的
MulitProject.xcworkspace
,包含LGApp
和LGFramework
兩個(gè)Project
。而Cocoapods
提供xcworkspace
在LGFramework
目錄中
此時(shí)往
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é)
弱引用動(dòng)態(tài)庫
- 標(biāo)記
-weak_framework
參數(shù),允許在運(yùn)行時(shí)不鏈接該動(dòng)態(tài)庫- 標(biāo)記為弱引用動(dòng)態(tài)庫,運(yùn)行時(shí)找不到地址不會(huì)報(bào)錯(cuò),而是返回一個(gè)
NULL
靜態(tài)庫代碼沖突
- 使用
-force_load
參數(shù),強(qiáng)制鏈接指定靜態(tài)庫- 使用
-load_hidden
參數(shù),將指定靜態(tài)庫的所有符號(hào)設(shè)置為隱藏- 指定
-all_load
或-ObjC
參數(shù),建議對靜態(tài)庫重新打包,刪除重復(fù)的Symbol
App -> 動(dòng)態(tài)庫A -> 動(dòng)態(tài)庫B
- 使用
Pods
向App
項(xiàng)目中導(dǎo)入動(dòng)態(tài)庫B
- 通過腳本,將
動(dòng)態(tài)庫B
拷貝到App
中的Frameworks
目錄
App
想使用動(dòng)態(tài)庫B
的方法
- 使用
Pods
向App
項(xiàng)目中導(dǎo)入動(dòng)態(tài)庫B
- 標(biāo)記
-reexport_framework
或-reexport_l
參數(shù),重新將動(dòng)態(tài)庫B
通過動(dòng)態(tài)庫A
導(dǎo)出給App
動(dòng)態(tài)庫的反向依賴
- 使用
-U
參數(shù),標(biāo)記某個(gè)符號(hào)為動(dòng)態(tài)查找符號(hào)- 使用
-undefined
參數(shù),將動(dòng)態(tài)庫中的符號(hào)全部標(biāo)記為動(dòng)態(tài)查找符號(hào)。配置后動(dòng)態(tài)庫中可以使用任意符號(hào),這樣風(fēng)險(xiǎn)較高,不建議使用
App -> 動(dòng)態(tài)庫A -> 靜態(tài)庫A
App
可以直接使用靜態(tài)庫A
的導(dǎo)出符號(hào)- 使用
-hidden-l<libraryname>
參數(shù),隱藏靜態(tài)庫A
的全局符號(hào)(導(dǎo)出符號(hào))
App -> 靜態(tài)庫A -> 靜態(tài)庫B
- 使用
Pods
向App
項(xiàng)目中導(dǎo)入靜態(tài)庫B
- 手動(dòng)配置
靜態(tài)庫B
的路徑和名稱
App -> 靜態(tài)庫A -> 動(dòng)態(tài)庫A
- 使用
Pods
向App
項(xiàng)目中導(dǎo)入動(dòng)態(tài)庫A
- 指定頭文件路徑、
Framework
所在目錄、@rpath
路徑。通過腳本,將動(dòng)態(tài)庫A
拷貝到App
中的Frameworks
目錄