在 iOS Swift 开发中 简单地使用 XCFramework

最近工作中的开发内容涉及到 Framework 的开发和使用,遇到一些问题,也算是解决了。
这里有一些基本的配置,记录一下,还有 简单的 XCFramework 配置使用。干货儿满满,收藏点赞?!

Framework 的配置

Build Setting

  • Build Libraries for Distribution – YES
  • Mach-O Type – Static Labriry (可选)

使用 .bundle

  1. 右键点击项目名。
  2. 选择 New Group
  3. 设置bundle名字:xxx.bundle
  4. 在这个目录汇中添加文件,可以添加代码用到的资源,路径就是xxx.bundle/xx

Pods 三方库

在 Framework 中使用了的pod依赖,那么在引入Framework 的项目中也要加入相应的依赖,并且版本不能小于Framework 中的三方库版本。

开发 Framework

在 demo 中开发 framework,可以使用 Add Files 加入xcodeproj。

  • General – Frameworks, Librarise, embed content – do not embed framework
  • Build Phases – Target Dependencies 添加 framework
  • Link Binary With Library – 添加 framework

构建

构建对应真机和模拟器的framework的文件,会在Xcode设置的目录下生成。
在这里 Xcode Setting – Loccasions – Derived Data 可以查看目录位置。在目录下的
/<Framework target name>/Build/Products/路径,可以看到对应的文件夹。
真机和模拟器(iphonesimulator),在这个文件夹下边,就可以找到 XXX.framework。直接拖到项目中即可使用。

Target 配置

Xcode 项目引入 Static Labriry 类型 Framework 配置,

引入的项目中的 Target – General – Frameworks and Libraries – Do Not Embed

如果是 dynamic library,则以上设置 需要是 – Embed and Sign

和 Framework 相关的 XCFramework

XCFramework 适用于打包多平台的情况,其包内会有相关配置,当把生成的 XCFramework 导入到项目中,自动就能根据运行的平台进行判断构建,方便开发。从而替代以前使用 lipo 合并 framework 架构的情况,也少了一些 target 的 build setting 设置。

至于运行创建 XCFramework,也很简单,使用命令行脚本即可。

下面,就开始一个例子,来看怎样开发一个framework,以及如何多平台打包吧。

创建 framework 的 demo

demo 使用的是 Xcode 14.2

依次选择:File – New – Project…,选择 iOS – Framework

截屏2023-06-09 16.11.41.png

设置 framework 名称为 DemoFramework,然后选择一个存储位置。

截屏2023-06-09 16.23.22.png

创建好的 demoFramework 如下图,我们已经加入一个 HelloworldViewController 文件,是一个展示Helloworld 文字的 UIViewController。

截屏2023-06-09 16.20.06.png

另外,还把 Build Libraries for Distribution 设置为 YES。这是根据前边的记录,打包 XCFramework 所用到的设置。

创建 调试Framework 的 Demo App

创建新的 App项目的话,大家已经很熟,不再详述。

创建好名为 DemoTestFramework 的项目后,右键点击左边目录的 DemoTestFramework Target – Add Files to “DemoTestFramework”,然后选择 DemoFramework,注意不要选择 Copy Item If needed

截屏2023-06-09 16.36.13.png

添加好之后,如下图所示,其中还添加了一些设置。

截屏2023-06-09 16.46.17.png

  • 图中1区:这是添加后的项目目录。
  • 图中2区:导入framework,然后让主视图控制继承 DemoFramework 中的 HelloworldViewController
  • 图中3区:在 TARGETS – DemoTestFramework – General选项卡 – Framework, Libraries, and Embedded Content 中,添加了我们引入项目的 demo framework。
  • 图中4区:在 TARGETS – DemoTestFramework – Build Phases – Target Dependencies 中,添加了 demo framework,这里是为了在修改 Framework 内容的同时,也会把 Framework 内容同时 build 一遍。

我们选择 14 pro模拟器 ,Run 一下,可以看到,项目已经成功运行,Demo Framework 也成功引入了 demo app。

现在,我们把 Demo Framework 中的 Label 内容,改为”Hello, Swift 6.0!”,然后 Run 一下。

运行成功,显示正确!?

这就说明,对于 Framework 的修改,已经成功被 Demo app 调用。

打包 Demo Framework 为 XCFramework

成功修改之后,就可以打包发布,以供其他项目引入使用。 这里直接上脚本,在脚本中解释吧。

#!/bin/sh

# 如果脚本放进Xcode的run script中运行,可以不设置这个PROJECT_NAME,

# 因为它同时也是 Xcode 项目的全局变量,用于获取项目名。

PROJECT_NAME=DemoFramework



# 我们framework的名字是和项目名一样的,如果不一样的的话,可以单独设置。

framework_name=$PROJECT_NAME



# 导出xcframework的路径
output_path=$HOME/${framework_name}_XCFramework


# 模拟器的存档位置
simulator_archive_path=$output_path/simulator.xcarchive
# 真机的存档位置
iOS_device_archive_path=$output_path/iOS.xcarchive

# 删除旧版,然后创建新版
rm -r $output_path
mkdir $output_path

# 打包模拟器
xcodebuild archive \
-scheme $framework_name \
-destination "generic/platform=iOS Simulator" \
-archivePath $simulator_archive_path \
SKIP_INSTALL=NO

# 打包真机
xcodebuild archive \
-scheme $framework_name \
-destination "generic/platform=iOS" \
-archivePath $iOS_device_archive_path \
SKIP_INSTALL=NO

# 创建 xcframework
xcodebuild -create-xcframework \
-framework $simulator_archive_path/Products/Library/Frameworks/$framework_name.framework \
-framework $iOS_device_archive_path/Products/Library/Frameworks/$framework_name.framework \
-output $output_path/$framework_name.xcframework

# 打包完成后,存档就失去作用,只作为中间打包过程使用。
rm -r $simulator_archive_path $iOS_device_archive_path

# 打开 XCFramework 所在的目录
open $output_path

可以直接将脚本内容放入Xcode的脚本中,注释掉项目名的设置,直接运行含有脚本的 Target 就行。
而我的脚本是以sh文件的形式放在项目根目录中的,如果你也是这样,直接使用命令运行即可,无需修改内容。

$ cd <DemoFramework 的项目路径>
$ sh DemoOutputXCFramework.sh

运行成功,会得到这样的文件结构。

.
└── DemoFramework.xcframework
    ├── Info.plist
    ├── ios-arm64
    └── ios-arm64_x86_64-simulator

这就是创建在用户目录下的 XCFramework 文件内容**。**

导入项目使用

首先删除左边目录中对于 DemoFramework Target 的引用。

然后,直接将生成的 DemoFramework.xcframework 拖入 TARGETS – DemoTestFramework – General选项卡 – Framework, Libraries, and Embedded Content 中,如下图所示。

截屏2023-06-09 23.00.58.png

选择模拟器或真机,都Run一下,和预期一样,屏幕显示 “Hello, Swift6.0!”字样。
这样我们就为项目添加好了 XCFramework,而且模拟器和真机都可以运行。?

有pod 依赖的情况

上边的操作,都是基于无三方依赖的情况,如果我们的 Framework 中,添加了 Pods 依赖的话,情况又不太一样。

我们先在项目中添加 Pod依赖,在例子中,是加入了 SnapKit 这个布局库,过程省略,说起依赖,其实cocopods的简单操作也是个不错的主题,以后有时间可以总结一下。

由于采用了pods依赖,那么我们在 xcodebuild 命令中,需要加一条 -workspace $workspace_name, 因为 pod项目运行的是 DemoFramework.xcworkspace, 我们实际 build的对象是指定的 workspace。脚本如下:

#!/bin/sh

# 如果脚本放进Xcode的run script中运行,可以不设置这个PROJECT_NAME,

# 因为它同时也是 Xcode 项目的全局变量,用于获取项目名。

PROJECT_NAME=DemoFramework



# 我们framework的名字是和项目名一样的,如果不一样的的话,可以单独设置。

framework_name=$PROJECT_NAME



# +++ 加入pods以后,指定 build 的 workspace
workspace_name="${PROJECT_NAME}.xcworkspace"


# 导出xcframework的路径
output_path=$HOME/${framework_name}_XCFramework

# 模拟器的存档位置
simulator_archive_path=$output_path/simulator.xcarchive
# 真机的存档位置
iOS_device_archive_path=$output_path/iOS.xcarchive

# 删除旧版,然后创建新版
rm -r $output_path
mkdir $output_path

# +++ 加入pods以后,打包模拟器
xcodebuild archive \
-workspace $workspace_name \
-scheme $framework_name \
-destination "generic/platform=iOS Simulator" \
-archivePath $simulator_archive_path \
SKIP_INSTALL=NO

# +++ 加入pods以后,打包真机
xcodebuild archive \
-workspace $workspace_name \
-scheme $framework_name \
-destination "generic/platform=iOS" \
-archivePath $iOS_device_archive_path \
SKIP_INSTALL=NO

# 创建 xcframework
xcodebuild -create-xcframework \
-framework $simulator_archive_path/Products/Library/Frameworks/$framework_name.framework \
-framework $iOS_device_archive_path/Products/Library/Frameworks/$framework_name.framework \
-output $output_path/$framework_name.xcframework

# 打包完成后,存档就失去作用,只作为中间打包过程使用。
rm -r $simulator_archive_path $iOS_device_archive_path

# 打开 XCFramework 所在的目录
open $output_path

如果是以脚本文件的形式放在项目根目录下,运行方式和上边没有pods依赖的方法一样。
得到的 XCFramework目录也是相同的。这部分上边已有详述。

然后我们加入项目 DemoFramework,使用真机运行一下,结果如预期。

但是在模拟器运行的时候,我遇到一个错误。

arm64-apple-ios-simulator.private 报错

/Users/youwei/Library/Developer/Xcode/DerivedData/DemoTestFramework-fiviywlmfwujstdvutfebnogtjuh/Build/Products/Debug-iphonesimulator/DemoFramework.framework/Modules/DemoFramework.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface:6:8 
Could not find module 'SnapKit' for target 'arm64-apple-ios-simulator'; 
found: x86_64-apple-ios-simulator, at: /Users/youwei/Library/Developer/Xcode/DerivedData/DemoTestFramework-fiviywlmfwujstdvutfebnogtjuh/Build/Products/Debug-iphonesimulator/SnapKit/SnapKit.framework/Modules/SnapKit.swiftmodule

解决的方法,就是在项目中,对于模拟器的 build setting,排除 arm64架构即可。

截屏2023-06-11 17.29.15.png

在项目的 Build Settings – Excluded Architectures – Any iOS Simulator SDK – arm64

这是因为创建 XCFramework 时加入了arm64架构,本身这个应该是属于真机的。

# youwei @ 192 in ~/DemoFramework_XCFramework/DemoFramework.xcframework [17:45:05] C:1
$ lipo -info ios-arm64_x86_64-simulator/DemoFramework.framework/DemoFramework
Architectures in the fat file: ios-arm64_x86_64-simulator/DemoFramework.framework/DemoFra

模拟器 run 一下,好的,已经成功了。?

总结

XCFramework 是苹果出的新的二进制打包方式,感觉可以替代以前Framework打包合并平台架构的方法,可以同时支持多个平台,甚至还有 watch OS和 MacOS,而且打包过程简单,在日常工作中,掌握其使用还是有必要的。

最后,如果大家喜欢这篇文章的话,记得收藏,点赞,转发?!

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYshO4jd' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片