文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Swift Package 技巧及混编兼容问题详解

2023-03-13 17:42

关注

创建 Package

mkdir somePath
cd somePath
swift package init (--type library/executable/empty/system module)

其中,type 的四种类型分别对应:

一般情况下默认即可

创建 package 之后,还可以使用 swift package generate-xcodeproj 创建一个Xcode项目来编译和调试代码

使用 Package

在 Xcode 菜单栏中,选择 file -> add packages

image-20220109204812598.png

可以指定 package 的版本规则

维护 Package

版本控制

在 package 路径下,使用 git init 来创建一个仓库。之后上传至远端即可

本地调试修改

对于通过 cocoapods 引入的库,如果想在本地修改该库并提交的话,需要在 PodFile 里面把路径改成本地的,然后再 pod install 一下,比较麻烦

但是修改 swift package 引入的库就很方便了,直接把 package 的文件目录拖到工程目录下即可。修改好提交到远端之后,右键 delete -> remove reference (move to trash 会删掉本地文件)

然后 file -> packages -> update to latest,即可更新到最新的版本

Package 之间的依赖

在每个 swift package 的目录下都有个 Package.swift 文件。内容如下:

// swift-tools-version:5.5
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
    name: "some name",
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "some name",
            targets: ["some name"]),
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: , from: "1.0.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.
        .target(
            name: "some name",
            dependencies: []),
        .testTarget(
            name: "some name",
            dependencies: ["some name"]),
    ]
)

其中的字段分别表示:

相较于 cocoapods,swift package 还是更加方便点的,而且是苹果自家的产品。但是目前很多三方库都在 cocoapods 上,swift package 的大面积普及还需要一段时间

混编问题

target 拆分

Apple 官方文档里说:

Targets can contain Swift, Objective-C/C++, or C/C++ code, but an individual target can’t mix Swift with C-family languages. For example, a Swift package can have two targets, one that contains Objective-C, Objective-C++, and C code, and a second one that contains Swift code.

也就是说,SPM 是支持 objc 以及 C 系代码的。但是同一个 target 里面只能有一种语言,Swift 文件不能和 objc 文件放到一个 target 里。

如果我们想要在一个 SPM 仓库里面同时放置两种语言的代码的话,就需要将仓库拆分为两个 target:

let package = Package(
    name: "MyModule",
    platforms: [.iOS(.v11),
                .macOS(.v11)],
    products: [
        // Products define the executables and libraries a package produces, and make them visible to other packages.
        .library(
            name: "MyModule",
            targets: ["MyModule", "MyModule_Objc"])
    ],
    dependencies: [
        // Dependencies declare other packages that this package depends on.
        // .package(url: , from: "1.0.0"),
    ],
    targets: [
        // Targets are the basic building blocks of a package. A target can define a module or a test suite.
        // Targets can depend on other targets in this package, and on products in packages this package depends on.
        .target(
            name: "MyModule_Objc",
            dependencies: [],
            publicHeadersPath: "include",
            cSettings: [.headerSearchPath(".")],
            cxxSettings: [.headerSearchPath(".")]
        ),
        .target(
            name: "MyModule",
            dependencies: ["MyModule_Objc"],
            path: "Sources/MyModule",
            swiftSettings: [.define("SPM_MODE")]
        ),
        .testTarget(
            name: "MyModuleTests",
            dependencies: ["MyModule"]),
    ]
)

其中,仓库文件结构应该为:

- MyModule
  |
  |-README.md
  |
  |-Package.swift
  |
  |-Sources
    |
    |-MyModule
    | |
    | |- MyPackage.swift  
    |
    |-MyModule_Objc
      |
      |-Include
      | |
      | |- MyObjCClass.h
      |
      |- MyObjCClass.m

Sources 文件夹拆分为两个子文件夹,分别是两个 target 的路径。Swift target 依赖 objc 的 target, objc 的 target 可以设置公开 header 的路径。

这样,objc 以及 C/C++ 这些 C 系的文件都放在 MyModule_Objc 文件夹下,Swift 文件放到 MyModule 文件夹下,就可以在同一个 SPM 仓库下实现混编了。

引用以及和 cocoapods 的兼容问题

在上面的 package 设置里面可以看到一行预处理宏的定义:

swiftSettings: [.define("SPM_MODE")]

这个设置是用来标识当前库是通过 SPM 方式引入的。根据上文,SPM 模式下,当前库的 Swift 和 objc 是两个 target。因此,同一个库的 Swift 文件想要调用 objc 文件的话,必须引入 objc 的 target:

import MyModule_Objc
// your code...

但是,我们的库一般情况下还是要支持 cocoapods 的。在 cocoapods 模式下,同一个仓库的 Swift 和 objc 文件是不需要拆分为两个 target 的,pod 是通过桥接文件等来实现两者之间相互调用的。

那么问题就来了,当使用 cocoapods 引入当前库时,import MyModule_Objc 是肯定会报错的,因为 pod 并不会生成 MyModule_Objc

这时候,我们在 package 文件里预先定义的宏就派上用场了:

#if SPM_MODE
import FoundationX_Objc
#endif

只有在 SPM 模式下,才会 import MyModule_Objc,这样就解决了与 cocoapods 的兼容问题。

以上就是Swift Package 技巧及混编兼容问题详解的详细内容,更多关于Swift Package混编兼容的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯