Xcode 工程添加 “动态” Framework 的几种方式

Xcode 工程添加 “动态” Framework 的几种方式,第1张

如何在 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,在d出的窗口选择 Add Other…,最后在 Finder 中选择你要添加的“动态 framework”,并勾选 Copy if needed 即可。需要注意的是,你不能直接在 Finder 中把 .framework 文件拖拽到 Embedded Binaries 中,否则会报错。

关于手动添加动态库的更多细节以及遇到问题的解决办法,可参考苹果官方的教程: 《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 集成的第三方库,在 Cartfile 文件中添加好依赖后,然后执行 carthage update 命令会帮我们生成一个个“动态 framework”,例如 AFNetworking.framework、SDWebImage.framework 等,然后把它们拖拽到工程中的 General ->Linked Frameworks and Libraries ,然后在配置相关拷贝脚本和命令,详细可参考 Carthage 的 Quick Start 教程。

这里有个关键 *** 作是,需要在 Xcode 工程的 Build Phases 中添加一个执行脚本(New Run Script Phase),并在脚本中执行如下命令:

如图 2 所示:

该命令的作用大概就是,在打包拷贝动态库时自动帮我们移除掉其中的 i386、x86_64。

同样地,通过 CocoaPods 集成动态库时,也会在工程中自动帮我们添加一个 Shell 脚本用于做这件事,如图 3 中的 [CP] Embed Pods Frameworks,

大家可以自行查阅该 Pods-xxx-frameworks.sh 脚本的内容,里面有个函数 strip_invalid_archs() 就是用于在打包时移除无用的处理器架构,如图 4:

因此,我们可以把自己开发的或者他人提供的动态 framework,通过 CocoaPods 来集成到工程中:创建一个 Pods 私有 git 库(相信大家已经很熟悉了),在 git 库中添加相关动态 .frameworks 文件,然后其 Podspec 文件的写法大致如图 5 所示,最后在你的工程中 pod install 即可。

最后我们思考一个问题:“静态 framework” 和 “动态 framework” 在使用上似乎也没什么不同,而工程添加 “动态 framework” 又比较繁琐,那么在 iOS/macOS 开发中什么情况下会使用动态库呢?

一:格式

二.制作静态库

首先

然后

在这里选择一个.a或者是framework.

默认选择的是Dynamic Library,要手动选择Static Library

再然后是添加一些可能需要添加的依赖库

然后暴露出头文件

最后编译生成静态库

设置 Build Active Architecture Only

方法一:

lipo -create 模拟器下的MyIMSDK的路径 真机下的MyIMSDK的路径 -output 合并的新的MyIMSDK的路径

方法二:

使用脚本生成

注意

(1).资源文件通过bundle文件引入:

(2).在制作framework的时候,如果使用了category,则使用该framework的项目运行时会crash,此时需要在该工程中 other linker flags添加一个参数 -ObjC

看了一个视频是一个什么cat老师.他说引入.xcconfig配置文件去引入静态库

这个. xcconfig以前确实没见过.是比较失败天天就知道吹水...

在这里创建:

在这里引入:

以前我们引入静态库是直接拖进去的.现在了解这个xcconfig 确实可以做一些修改.

二.动态库

静态库可以直接编译生成动态库.也是从这个视频看到的(以前的知识是多么狭隘)

静态库是.o文件的合集,动态库是.o文件链接完成的结果.(这个就是他们的本质区别)

(1).动态库的创建和静态库差不多,没有右边的.a创建.

(2).动态库可以暴露出来头文件,也可以不暴露出来.

(3).动态库的使用

可以通过注入(我们的加速动态库就是这么来的)

也可以拖入

三.动态库为什么能注入

mach-O中LoadCommands指令中,存放这需要加载的库,到时候由dyld读取,并且在运行时加载。注意到LoadCommands整个段尾部还留有一些空白。因此在这么多库的后面添加自定义的库即可

通过向宏DYLD_INSERT_LIBRARIES里写入动态库完整路径。就可以在执行文件加载时将该动态库插入。(动态库已经是一个可执行文件)

yololib注入

monkeyDev注入

(仅做总结:驳船用)

软件:xcode12

FrameWork既可能是动态库,也可能是静态库,我们这里创建的是动态库。

选择FrameWork。默认创建的是Framework动态库

设置动态库名称

修改项目的iOS Deployment Target为10.0(与使用动态库项目保持一致,或者低于使用的项目)

MyFramework.h是默认生成的,会自动添加到暴露的header中,可以在内部import一些自己需要暴露使用的头文件。

创建文件,并添加想要暴露的头文件

(可选)设置动态库支持bitcode,如果不支持bitcode,使用动态库的项目就不能支持bitcode

动态库支持bitcode: https://www.jianshu.com/p/c5570751fdbc

第一步,DEPLOYMENT_POSTPROCESSING = YES

第二步,设置 STRIP_STYLE 为 Debugging Symbols(默认是)

第三步,Build Settings ->Compiler Flags添加 -fembed-bitcode 参数

第四步,确认Build Settings ->Enable Bitcode 为YES(默认是)

设置Edit Scheme的Run的build Configuration为Release,以便于打出来的framework是release的。当然你也可以使用debug的进行调试。

simulator和真机的framework包如果需要进行合成一个调试包,需要去掉模拟器的arm64,因为xcode12合成的时候,会因为simulator和真机的包都包含arm64的而产生冲突。

选择任何simulator进行build,生成simulator的包,使用Any iOS Device进行build,生成真机的包。

生成之后在项目目录的products下的Myframework.framework进行Show in Finder,就可以看到生成的framework包。我们可以把两个包拷贝出来然后

两个包都可以单独进行调试,但是真机的包需要使用本地的证书进行重签名。

将两个包的可执行文件进行合成:

1>cd到你合成文件想要放置的文件夹下(避免当前文件夹下有和可执行文件名称相同的文件或者文件夹,有的话会报错)

2>终端执行命令:lipo -create sumulator的framework的可执行文件的目录 真机的framework的可执行文件的目录 -output 可执行文件名

lipo -create /Users/admin/Desktop/work/dylib/Release-iphonesimulator/MyFramework.framework/MyFramework /Users/admin/Desktop/work/dylib/Release-iphoneos/MyFramework.framework/MyFramework -output MyFramework

3>将生成的可执行文件替换Release-iphoneos中的MyFramework.framework下的可执行文件。MyFramework.framework则就是合成的包。

4>对合成的包进行开发者证书(使用动态库项目的开发者证书)签名,签名之后就生成了可进行sumulator和真机调试的framework动态包。

签名方式:重新打开终端输入/usr/bin/security find-identity -v -p codesigning 列出电脑上可用的签名,cd到XX.framework所在的目录,然后codesign -fs "Apple Development: xxxx (XXXX)" xx.framework进行签名。

注意:打包测试或者发布的时候是直接使用没有签名过的真机的framework,xcode会自动进行签名。

项目使用动态库framework

把动态库添加到项目,然后在Build Phases的Copy Bundle Resources中添加动态库,这样动态库在打包的时候可以打包到bundle中。Link Binary Libraries如果添加了的话,动态库在程序运行的时候就会自动动态加载,可以直接使用,如果没有添加,则需要我们使用loadAndReturnError或者dlopen(私有api不能上线使用)进行加载,加载成功之后进行使用。

动态加载库方式:

1> Build Phases的Copy Bundle Resources中添加动态库,Link Binary Libraries删掉动态库。如果Link Binary Libraries需要链接的话需要在Build Settings->Links->Runpath Search Paths中添加@executable_path/

2>使用

如果重复添加动态库,则后面添加的动态库失效。

如果framework中使用到了Category那么在使用framework的工程中要设置Build Settings中的Other Link Flag为-ObjC或者-all_load


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/bake/11569808.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-17
下一篇 2023-05-17

发表评论

登录后才能评论

评论列表(0条)

保存