弱引用动态库
弱引用动态库:标记
-weak_framework参数,允许在运行时不链接该动态库
正常情况下,运行时找不到动态库所在位置,程序崩溃并提示
image not found搭建
LGApp项目,将动态库SYTimer.framework拷贝到项目根目录
打开
LGApp项目,创建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三要素,编译可以成功。但运行时,程序崩溃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>指定动态库为weak imports。如果在运行时找不到该库,会自动将该库的地址及内容返回NULL使用
man ld查看ld命令,找到-weak_framework参数
-weak_framework:标记为弱引用动态库。运行时找不到地址不会报错,而是返回一个NULL打开
xcconfig文件,修改OTHER_LDFLAGS配置项:OTHER_LDFLAGS = $(inherited) -Xlinker -weak_framework -Xlinker "SYTimer"项目运行成功,输出内容如下:
2021-03-08 17:46:30.286532+0800 LGApp[3397:9187180] (null)
使用
-weak_framework标记为弱引用动态库,Mach-O中记录的Load Command名称不再是LC_LOAD_DYLIB,变为LC_LOAD_WEAK_DYLIB使用
otool -l test | grep 'DYLIB' -A 2命令,查看Mach-O中动态库的路径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)
静态库代码冲突
搭建
LGApp项目,将静态库AFNetworking代码,在项目根目录下拷贝两份。将静态库目录,分别命名为AFNetworking和AFNetworking2
打开
AFNetworking2目录,将libAFNetworking.a文件,重命名为libAFNetworking2.a
打开
LGApp项目,创建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"此时编译可以通过,因为链接静态库默认使用
-noall_load参数。当链接静态库AFNetworking找到代码后,就不会链接静态库AFNetworking2但真实项目中,我们使用
Pods导入的三方库,大部分使用-all_load或-ObjC参数,此时问题出现了打开
xcconfig文件,修改OTHER_LDFLAGS配置项:OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking" -l"AFNetworking2"编译报错,出现大量的重复符号
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参数,强制链接的静态库AFNetworking- 使用
-load_hidden参数,将静态库AFNetworking2的所有符号设置为隐藏编译报错,依然提示重复符号
ld: 223 duplicate symbols for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)结论:如果导入相同静态库,又指定了
-all_load或-ObjC参数,建议对静态库重新打包,删除重复的Symbol
动态库链接动态库
搭建
LGFramework项目
LGFramework是一个动态库项目,项目中使用Pods导入动态库AFNetworking
使用
Pods向一个Framework中导入三方库,Pods只会配置链接参数,不会将三方库拷贝到指定位置,也不会生成.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:表示是否存在头文件- 导入头文件:判断
AFN,如果存在,执行#import AFN_HEADER_PATH代码testOneObject方法:判断AFN,如果存在,初始化AFNetworkReachabilityManager实例对象,并打印manager对象。否则打印NO AFN打开
LGFramework.h文件,写入以下代码:#import <LGFramework/LGOneObject.h>
搭建
LGApp项目
LGApp是一个App项目
创建
MulitProject.xcworkspace,加入LGFramework动态库和Pods项目。LGApp链接LGFramework动态库
- 项目结构:
LGApp(App) -> LGFramework(动态库A) -> AFNetworking(动态库B)在
LGApp项目中,打开ViewController文件,写入以下代码:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end运行项目后,程序直接崩溃
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项目中,创建xcconfig文件,并配置到Tatget上,写入以下代码:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" LD_RUNPATH_SEARCH_PATHS = $(inherited) ${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking
- 导入
Pods生成的xcconfig- 按照
AFNetworking.framework所在路径,修改@rpath路径选择模拟器,运行项目,输出内容如下:
2021-03-09 16:05:33.972325+0800 LGApp[10862:9536454] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x600000856920>选择真机,运行项目,程序崩溃:
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
- 在设备上运行
App,需要将链接的动态库拷贝到App包内
【方式二】
使用
Pods向LGApp项目中导入动态库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选择真机,运行项目,输出内容如下:
2021-03-09 16:18:57.810101+0800 LGApp[1471:289515] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x280d231c0>使用
Pods向App中导入三方库,会生成一个.sh脚本。它的作用就是将.framework拷贝到App中的Frameworks目录
【方式三】
通过脚本,将
AFNetworking.framework拷贝到App中的Frameworks目录将
方式二中,Pods生成的Pods-LGApp-frameworks.sh脚本,拷贝到LGApp项目的根目录
在
Pods项目中,打开Podfile文件,恢复初始代码:platform :ios, '9.0' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end在
LGApp项目中,创建xcconfig文件,并配置到Tatget上,写入以下代码:SCRIPT_DIR = ${SRCROOT}/Pods-LGApp-frameworks.sh
- 定义
SCRIPT_DIR变量,存储.sh脚本路径在
LGApp项目中,选择Build Phases,在Run Script中写入脚本:"${SCRIPT_DIR}"
选择真机,运行项目,输出内容如下:
2021-03-09 17:51:16.113484+0800 LGApp[1556:311935] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x2831fa2c0>此时
LGApp项目不再使用Pods导入AFNetworking动态库,而是通过脚本,将AFNetworking.framework拷贝到App中的Frameworks目录
App想使用动态库B的方法
基于上述案例:
LGApp(App) -> LGFramework(动态库A) -> AFNetworking(动态库B)如果
App想使用动态库B的方法,也就是让LGApp直接调用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使用动态库B的方法:%@", manager); } @end编译失败,提示错误信息:找不到头文件
'AFNetworking/AFNetworking.h' file not found
介绍以下两种解决办法:
【方式一】
使用
Pods向LGApp项目中导入动态库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"
- 导入
Pods生成的xcconfig选择真机,运行项目,输出内容如下:
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使用动态库B的方法:<AFNetworkReachabilityManager: 0x283afac60>
【方式二】
标记
-reexport_framework或-reexport_l参数,重新将AFNetworking通过动态库LGFramework导出给LGApp在
Pods项目中,打开Podfile文件,恢复初始代码: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参数,想要将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"选择真机,运行项目,输出内容如下:
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使用动态库B的方法:<AFNetworkReachabilityManager: 0x283afac60>
动态库的反向依赖
动态库的反向依赖,由于符合的作用空间,在运行时,动态库可以动态找到
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
- 导入
LGApp项目中的LGAppObject.h头文件- 调用了
LGAppObject的test_app方法在
LGFramework项目中,打开xcconfig文件,写入以下代码:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" HEADER_SEARCH_PATHS = $(inherited) "${SRCROOT}/../LGApp/LGApp"
- 导入
LGApp项目中的头文件编译报错,提示错误信息:
_OBJC_CLASS_$_LGAppObject符号未定义Undefined symbols for architecture arm64: "_OBJC_CLASS_$_LGAppObject", referenced from: objc-class-ref in LGOneObject.o
介绍以下两种解决办法:
【方式一】
使用
-U参数,标记某个符号为动态查找符号在
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参数,标记符号_OBJC_CLASS_$_LGAppObject为动态查找符号选择真机,运行项目,输出内容如下:
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参数,将动态库中的符号全部标记为动态查找符号。配置后动态库中可以使用任意符号,这样风险较高,不建议使用在
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参数,将整个LGFramework动态库中的符号,都标记为动态查找符号选择真机,运行项目,输出内容如下:
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>
动态库链接静态库
搭建
LGFramework项目
LGFramework是一个动态库项目,项目中使用Pods导入静态库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项目
创建
MulitProject.xcworkspace,加入LGFramework动态库和Pods项目。LGApp链接LGFramework动态库
- 项目结构:
LGApp(App) -> LGFramework(动态库A) -> AFNetworking(静态库A)在
LGApp项目中,打开ViewController文件,写入以下代码:#import "ViewController.h" #import <LGFramework/LGFramework.h> @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; LGOneObject *object = [LGOneObject new]; [object testOneObject]; } @end选择真机,运行项目,输出内容如下:
2021-03-10 10:16:12.781430+0800 LGApp[2185:436467] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x280dc7a60>
- 动态库
LGFramework生成的过程中,链接静态库AFNetworking时,会把静态库AFNetworking所有代码都链接进去。所以编译链接都不会报错
App想使用静态库AFNetworking的方法在
LGApp项目中,创建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使用静态库AFNetworking的方法:%@", manager); } @end选择真机,运行项目,输出内容如下:
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使用静态库AFNetworking的方法:<AFNetworkReachabilityManager: 0x281493d20>
- 动态库链接静态库时,会把静态库所有代码都链接进去。静态库的导出符号,在动态库中依然是导出符号。所以
App可以直接使用
隐藏静态库
AFNetworking的全局符号如果动态库
LGFramework不想把静态库AFNetworking的全局符号(导出符号)暴露出去,可以通过-hidden-l<libraryname>参数隐藏静态库的全局符号使用
man ld查看ld命令,找到-hidden-l<libraryname>参数
在
LGFramework项目中,创建xcconfig文件,并配置到Tatget上,写入以下代码:#include "Pods/Target Support Files/Pods-LGFramework/Pods-LGFramework.debug.xcconfig" OTHER_LDFLAGS = -Xlinker -hidden-l"AFNetworking" $(inherited)
- 导入
Pods生成的xcconfig- 因为
Cocoapods生成的xcconfig文件包含了-framework AFNetworking参数,想要将AFNetworking指定为-hidden-l,需将其放在$(inherited)前面编译报错,提示错误信息:
_OBJC_CLASS_$_AFNetworkReachabilityManager符号未定义Undefined symbols for architecture arm64: "_OBJC_CLASS_$_AFNetworkReachabilityManager", referenced from: objc-class-ref in ViewController.o
静态库链接静态库
搭建
LGFramework项目
LGFramework是一个静态库项目,项目中使用Pods导入静态库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项目
创建
MulitProject.xcworkspace,加入LGFramework静态库和Pods项目。LGApp链接LGFramework静态库
- 项目结构:
LGApp(App) -> LGFramework(静态库A) -> AFNetworking(静态库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)
- 静态库
LGFramework生成时,只保存了静态库AFNetworking的头文件信息或静态库AFNetworking的名称(Auto-Link)。App链接静态库LGFramework后,会把静态库LGFramework所有代码都链接进去。但是并不知道静态库AFNetworking的位置和名称。所以编译报错
介绍以下两种解决办法:
【方式一】
使用
Pods向LGApp项目中导入静态库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选择真机,运行项目,输出内容如下:
2021-03-10 11:33:33.533189+0800 LGApp[2257:453229] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x28164b920>
【方式二】
手动配置静态库
AFNetworking的路径和名称在
LGApp项目中,创建xcconfig文件,并配置到Tatget上,写入以下代码:LIBRARY_SEARCH_PATHS = $(inherited) "${BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/AFNetworking" OTHER_LDFLAGS = $(inherited) -ObjC -l"AFNetworking"选择真机,运行项目,输出内容如下:
2021-03-10 11:37:57.163689+0800 LGApp[2275:454837] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x28232b040>
静态库链接动态库
搭建
LGFramework项目
LGFramework是一个静态库项目,项目中使用Pods导入动态库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项目
创建
MulitProject.xcworkspace,加入LGFramework静态库和Pods项目。LGApp链接LGFramework静态库
- 项目结构:
LGApp(App) -> LGFramework(静态库A) -> AFNetworking(动态库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)
- 静态库
LGFramework生成时,只保存了动态库AFNetworking的名称(Auto-Link)。App链接静态库LGFramework后,会把静态库LGFramework所有代码都链接进去。但是并不知道动态库AFNetworking的位置,也没有提供@rpath路径。所以编译报错
介绍以下两种解决办法:
【方式一】
使用
Pods向LGApp项目中导入动态库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选择真机,运行项目,输出内容如下:
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文件,恢复初始代码:platform :ios, '9.0' target 'LGFramework' do use_frameworks! pod 'AFNetworking' end在
LGApp项目中,创建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}"
选择真机,运行项目,输出内容如下:
2021-03-10 13:46:27.990741+0800 LGApp[2393:481513] LGFramework-----LGOneObject-----AFN: <AFNetworkReachabilityManager: 0x282a61360>
配置Cocoapods
指定动态库+静态库
Cocoapods导入三方库,有些场景下,需要指定某些库为动态库、某些库为静态库。此时配置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
有些复杂项目,使用的并不是
Cocoapods提供xcworkspace最上层是自定义的
MulitProject.xcworkspace,包含LGApp和LGFramework两个Project。而Cocoapods提供xcworkspace在LGFramework目录中
此时往
MulitProject.xcworkspace中的LGApp导入三方库,可以使用以下代码: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中导入三方库,指定Project路径
总结
弱引用动态库
- 标记
-weak_framework参数,允许在运行时不链接该动态库- 标记为弱引用动态库,运行时找不到地址不会报错,而是返回一个
NULL静态库代码冲突
- 使用
-force_load参数,强制链接指定静态库- 使用
-load_hidden参数,将指定静态库的所有符号设置为隐藏- 指定
-all_load或-ObjC参数,建议对静态库重新打包,删除重复的Symbol
App -> 动态库A -> 动态库B
- 使用
Pods向App项目中导入动态库B- 通过脚本,将
动态库B拷贝到App中的Frameworks目录
App想使用动态库B的方法
- 使用
Pods向App项目中导入动态库B- 标记
-reexport_framework或-reexport_l参数,重新将动态库B通过动态库A导出给App动态库的反向依赖
- 使用
-U参数,标记某个符号为动态查找符号- 使用
-undefined参数,将动态库中的符号全部标记为动态查找符号。配置后动态库中可以使用任意符号,这样风险较高,不建议使用
App -> 动态库A -> 静态库A
App可以直接使用静态库A的导出符号- 使用
-hidden-l<libraryname>参数,隐藏静态库A的全局符号(导出符号)
App -> 静态库A -> 静态库B
- 使用
Pods向App项目中导入静态库B- 手动配置
静态库B的路径和名称
App -> 静态库A -> 动态库A
- 使用
Pods向App项目中导入动态库A- 指定头文件路径、
Framework所在目录、@rpath路径。通过脚本,将动态库A拷贝到App中的Frameworks目录




















