Swift Package Manager 的里程碑

Easter79
• 阅读 648

作者:四娘,iOS 开发,目前就职于格隆汇,对 Swift 和编译器相关领域感兴趣

Session:

https://developer.apple.com/videos/play/wwdc2020/10147/

https://developer.apple.com/videos/play/wwdc2020/10169/

虽然 Swift Package Manager 发布到现在已经四年了,但采用率一直很低,无法完全替代 Cocoapods,不过今年情况将会有所改善,SwiftPM 今年迎来两个非常重要的功能:

  1. 二进制依赖分发

  2. 资源文件

二进制依赖

在去年 Xcode 11 集成了 SwiftPM 的功能,让我们可以以源码形式分发 Library,并且也引入了 XCFramework 来分发闭源 Library。

今年 Xcode 12 将会把它们结合到一起,提供二进制依赖库的支持,在下面的章节里我们将会介绍如何集成,分发和制作二进制依赖。

集成

包含了二进制文件的 Swift Package 在集成时不需要任何特殊的设置,它们也是一个普通的 Package.product,像之前一样在 target 的 dependencies 里通过名字指定即可:

let package = Package(     name: "package",     products: [         .executable(name: "package", targets: ["package"])     ],     dependencies: [         .package("https://github.com/JohnnyAppleased2020/BinaryEmoji", from: "1.0.0")     ],     targets: [         .target(name: "package", dependencies: ["Emoji"])     ] )

分发

需要注意,二进制依赖在 Swift 5.3 及以上才能使用:

// swift-tools-version: 5.3

Swift 5.3 里新增了一种新的 Target 类型 binaryTarget 来指定打包好的二进制文件:

let package = Package(     name: "Emoji",     products: [         .library(name: "Emoji", targets: ["Emoji"]),     ],     targets: [         .binaryTarget(             name: "Emoji",             url: "https://example.com/emoji/Emoji-1.0.0.xcframework.zip",             checksum: "6d9888a1a27418674b4d7c31732f6d60e60734ceb11a0ce9b54d1871918d9c194"         )     ] )

在分发二进制依赖时需要注意几点:

  • 目前只支持苹果平台,为了实现的便捷复用了已有的 XCFramework 格式,它支持动态和静态链接,并且可以同时支持多个平台。

  • 支持本地路径或者 https 链接。

  • 在使用本地路径时指向的可以是 XCFramework 的路径或者是 XCFramework 压缩后的 zip 文件,而 https 链接则只能指向 zip 文件。

制作

目前 XCFramework 的制作必须依托于 xcodebuild,所以需要先使用 swift package generate-xcodeproj 生成 Xcode 项目文件,然后:

  1. 在 Build Settings 里将  Build Libraries for Distribution 选项改为  YES

  2. 使用  xcodebuild archive 打包 framework 文件。

  3. 使用  xcodebuild -create-xcframework 将各个平台的 framework 文件合并为 xcframework。

更具体的细节可以查看 Binary Frameworks in Swift - WWDC2019[1]。

资源文件

今年的 Xcode 12 我们可以给 Swift Package 添加图片,storyboard 以及其它资源文件,同时也可以本地化这些资源文件。并且资源文件的添加使用的是现有的 API,所以也兼容之前版本的操作系统。

添加资源文件

SwiftPM 会根据文件的拓展名来进行处理,有一部分文件的使用目的非常明确,Xcode 会自动帮我们处理,只要添加到目录里即可:

Swift Package Manager 的里程碑

但有一部分文件它们的使用目的并不明确,例如 shell 脚本,文件夹,它们可能并不需要打包到 Package 里,此时我们就需要手动声明这些文件的处理规则:

Swift Package Manager 的里程碑

接下来让我们通过一个例子来了解具体的操作,重新回顾一下 Swift Package 的目录结构,我们会在 Sources 文件夹里看到与 target 同名的目录,目录里会存放着这个 target 的所有代码文件:

Swift Package Manager 的里程碑

更具体的规则大家可以查看 Adopting Swift Packages in Xcode - WWDC19[2]。

接着我们来看 GameLogic 目录的结构,下面我们可以看到 storyboard 和 xcassets 不需要做任何的额外声明,直接添加到对应的目录里即可。

但 Internal Notes.txt 有些特别,它只是开发过程中使用的文档,我们不希望它也被打包到 Package 里,此时我们可以通过 excludes 参数进行指定:

Swift Package Manager 的里程碑

如果我们要添加一些运行时需要的资源文件,就可以通过 resources 参数进行指定,大部分资源文件都可以使用 process 指定,此时它们会根据对应的平台和打包方式自动进行处理:

Swift Package Manager 的里程碑

有时我们需要目录在打包到 Package 之后也能保持它的结构,那么此时就可以使用 copy 选项:

Swift Package Manager 的里程碑

Swift Package Manager 的里程碑

.process 选项会使用 SwiftPM 预设的规则自动进行处理:

  • 不需要特殊处理的话绝大部分场景都推荐使用它。

  • 如果没有对应的规则处理的话,就会回退到  .copy

  • 这个选项会递归应用到目录下的所有文件。

.copy 没有规则,只是单纯的复制:

  • 可以用来覆盖预设的规则。

  • 目录的复制会递归进行(深复制)。

Swift Package Manager 的里程碑

访问资源文件

资源文件的访问会沿用现有的 Foundation.Bundle,这意味着 macOS 和 Linux 都可以共享同一套代码。

SwiftPM 会给所有带资源文件的 Target 自动合成当前 Bundle 的声明:

  • Swift:  Bundle.module

  • Objective-C:  SWIFTPM_MODULE_BUNDLE

访问资源文件:

`// Swift
let image = UIImage(named: "Logo", in: Bundle.module)

// Objective-C
UIImage *image = [UIImage imageNamed:@"Logo" inBundle:SWIFTPM_MODULE_BUNDLE];
`

需要注意⚠️,Bundle.module 会被声明为 internal:

extension Bundle {     internal var module: Bundle { get } }

如果要让外部也能访问 Package 内的资源文件,推荐框架作者提供类型安全的外部接口。

本地化

Package 内的资源文件也支持本地化,我们需要在 Package.swift 声明默认的语言 defaultLocalization

let package = Package(     name: "DiceUI",     defaultLocalization: "en",     ... )

存放资源的目录名称需要使用对应的 Language ID + Locale ID + .lproj,例如 en.lproj

Language and Locale ID - developer.apple.com[3]

本地化的资源通常是:

  • .strings 文件

  • .stringDicts 文件

  • 自定义资源文件

Swift Package Manager 的里程碑

推荐阅读

✨ 让 Objective-C 框架与 Swift 友好共存的秘籍

✨ 十年过去了,Swift 发展的怎么样了?

了解 Swift 中的数值计算

在 Swift 里安全管理指针

Swift 的不安全

关注我们

我们是「老司机技术周报」,每周会发布一份关于 iOS 的周报,也会定期分享一些和 iOS 相关的技术。欢迎关注。

Swift Package Manager 的里程碑

另外,老司机技术周报周边商店 正式上线,欢迎大家前往订购~

支持作者

这篇文章的内容来自于 《WWDC20 内参》。在这里给大家推荐一下这个专栏,专栏目前已经创作了 102 篇文章,只需要 29.9 元。点击【阅读原文】,就可以购买继续阅读 ~

WWDC 内参 系列是由老司机周报、知识小集合以及 SwiftGG 几个技术组织发起的。已经做了几年了,口碑一直不错。 主要是针对每年的 WWDC 的内容,做一次精选,并号召一群一线互联网的 iOS 开发者,结合自己的实际开发经验、苹果文档和视频内容做二次创作。

参考资料

[1]

Binary Frameworks in Swift - WWDC2019: https://developer.apple.com/videos/play/wwdc2019/416/

[2]

Adopting Swift Packages in Xcode - WWDC19: https://developer.apple.com/videos/play/wwdc2019/408/

[3]

Language and Locale ID - developer.apple.com: https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPInternational/LanguageandLocaleIDs/LanguageandLocaleIDs.html

本文分享自微信公众号 - 老司机技术周报(LSJCoding)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Wesley13 Wesley13
2年前
Java获得今日零时零分零秒的时间(Date型)
publicDatezeroTime()throwsParseException{    DatetimenewDate();    SimpleDateFormatsimpnewSimpleDateFormat("yyyyMMdd00:00:00");    SimpleDateFormatsimp2newS
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k