Flutter 正在迁移到 Swift Package Manager ,未来会弃用 CocoaPods 吗?
什么是 Swift Package Manager ?其实 Swift Package Manager (SwiftPM) 出现已经挺长一段时间了,我记得第一次听说 SwiftPM 的时候,应该还是在 2016 年,那时候 Swift 3 刚发布,不过正式出场应该还是在 2018 年的 Apple 的 WWDC 上。
但是其实这么多年过去了,在社区接触上,其实感觉 SwiftPM 的铺开程度还是比较局限,我觉得这也和 Swift 本身的推广效果有关系, 在 stackoverflow 2024 的数据报告里可以看到, Swift 目前的地位还是略显尴尬。
那为什么在已经有成熟 CocoaPods 的情况下,Apple 还要多搞一个 Swift Package Manager ?其实我理解核心还是推广 Swift ,毕竟用 Swift 写 SwiftPM 来管理 Swift Package ,一听就很合理。
就像 Android,在有 Groovy/Gradle 的情况下,开始推广用 Kotlin 的 kts 来写构建脚本 ,Kotlin First ,很合理。
当然,Swift Package 本身能更好的做一些拓展和封装,发布也更方便,并且和 Xcode 集成更舒适,作为「迟来」的亲儿子,肯定还是具有一些优势。
SwiftPM 作为 Swift 工具链中的一部分,同时也包含在 Xcode 中,所以使用 Swift 比起 CocoaPods ,不需要额外的第三方环境 。
Swift Package 不使用 .xcodeproj
或 .xcworkspace
,而是依赖其文件夹结构,并使用 Package.swift 进行配置,结构也更简单,例如:
-
// swift-tools-version:5.3 :必须存在的版本信息
-
name: 库名称
-
products: 库编译后对象,生成可执行文件或者 Library
-
dependencies: 依赖的库,依赖库的 URL 和版本等,还可以依赖本地库如
.package(path:)
-
targets: 包的基本构建目标,target 可以定义模块或测试模块,另外 target 可以依赖于该包中的其他 target 和 Package 依赖的 Library,也可以多 target 。
// swift-tools-version:5.3
import PackageDescriptionlet package = Package(name: "MyLibrary",platforms: [.macOS(.v10_14), .iOS(.v13), .tvOS(.v13)],products: [// Products define the executables and libraries a package produces, and make them visible to other packages..library(name: "MyLibrary",targets: ["MyLibrary", "SomeRemoteBinaryPackage", "SomeLocalBinaryPackage"])],dependencies: [// Dependencies declare other packages that this package depends on.],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: "MyLibrary",exclude: ["instructions.md"],resources: [.process("text.txt"),.process("example.png"),.copy("settings.plist")]),.binaryTarget(name: "SomeRemoteBinaryPackage",url: "https://url/to/some/remote/binary/package.zip",checksum: "The checksum of the XCFramework inside the ZIP archive."),.binaryTarget(name: "SomeLocalBinaryPackage",path: "path/to/some.xcframework").testTarget(name: "MyLibraryTests",dependencies: ["MyLibrary"]),]
)
是不是结构也很简单?
其实采用 SwiftPM 还有其他好处,那就是可视化支持,例如在 add Package 的时候,可以看到官方支持的一些 Packages 的情况和依赖方式。
另外一些第三方包,例如 firebase ,可以把库的 https 的 git 链接放到搜索框,就可以在 Xcode 看到和添加对应的第三方依赖情况,至于你问我为什么用这么抽象的方式?因为我也不知道图 2 的方式为什么会无法正常被添加。
那 SwiftPM 有什么缺点吗?其实还是有的,除了社区 Package 对比 CocoaPods 少太多之外,目前就是单个 target 不能将 Swift 和 C 系列语言混合使用,也就是 target 可以包含 Swift、Objective-C/C++ 或 C/C++ 代码,但单个 target 不能将 Swift 与 C 系列语言混合使用 。
是的,其实在 Swift Package Manager 里可以单独使用 OC,所以你旧的 OC Package 也可以迁移到 SwiftPM ,只要选择符合规格就行,例如需要 header 的 publicHeadersPath
指定,不配置时,默认是目录下的 include
路径。
所以如果存在混编,SwiftPM 肯定会是多 target 依赖,这时候如果你的库想要支持 CocoaPods 和 SwiftPM 双平台发布,如果是存在那么你可以需要对整个项目的结果和引用方式做一些调整,甚至添加一些
swiftSettings: [.define("IS_SwiftPM")]
这样的宏配置,然后在代码里通过#if IS_SwiftPM
的方式去对如 import 等操作做区分。
其实我个人也不喜欢混编,因为这样可能会带来一些很奇葩的场景,例如:
- Library B 使用 OC 写的,依赖了 Swift 写的 Library A
- 然后 Library C 用 Swift 写的,又依赖了 OC 写的 Library B
- 在 CocoaPods 场景下,混编都折腾出不少问题,例如曾经的《Flutter iOS OC 混编 Swift 遭遇动态库和静态库问题填坑》
但是现实历史场景下,混编又是很常见的需求,所以目前也存在 swiftlang#5919 在讨论的 support for targets with mixed language sources ,只是还没落地就是:
例如 React Native ,因为不支持混编的原因,在 SwiftPM 的推进上很慢,另外也有人给 CocoaPods 提了 PR#743,希望通过在 CocoaPods 增加
SwiftPM_dependency
的做法来让 CocoaPods 支持 SwiftPM ,不过目前 SwiftPM 貌似还不支持运行预处理命令,所以没办法对纯 C++ 包进行一些预处理。
甚至对于 RN 没支持 SwiftPM 这件事情下,也有一些人颇有微词,但是其实迁移到 SwiftPM 本身的成本确实不低,特别是对于 RN 本身来说。
在知道了 Swift Package Manager 的一些简单情况后,而回到本文主题上,既然迁移成本那么高,为什么 Flutter 还要迁移到 SwiftPM ?
Flutter 其实很早就在将自己的 Package 下的插件迁移到 Swift 上,而目前也在开始推进 SwiftPM 的迁移,这对于 Flutter 来说,好处就是:
-
Flutter 的 Plugin 可以更贴近 Swift 生态
-
简化 Flutter 安装环境,Xcode 本身就是包含 SwiftPM,如果 Flutter 的项目使用 SwiftPM,则完全无需安装 Ruby 和 CocoaPods 等环境(从 Flutter Team 提到的这里预期, Flutter 未来计划弃用 CocoaPods 的可能性很大)
而从目前的官方 Package 上看,#146922 上需要迁移支持的 Package 大部分都已经迁移完毕,剩下的主要文档和脚本部分的支持。
从 Flutter 官方的角度,它肯定希望 Flutter CLI 可以在升级后自动将项目迁移到 SwiftPM 支持,而目前关于 SwiftPM 相关部分尝试,还需要在 main 分支下进行预览。
目前看来, SwiftPM 对于项目工程的修改,很大程度是比较不可逆,所以如果 Flutter CLI 无法一键升级的情况下,自己手动调整也挺麻烦的 ,更多可见:https://docs.flutter.dev/packages-and-plugins/swift-package-manager/for-app-developers
不过官方的迁移速度不是重点,重点还是 pub 上将近 10,000 多个 iOS 和 macOS 插件,他们是否能顺序迁移到 SwiftPM ,才是这次迁移里的核心重点。
要之前,Apple 今年开春的 Privacy Manifest 问题就已经把社区插件搞了一遍,而 SwiftPM 对比 Privacy Manifest 得难度只会更高。
那为什么说 Flutter 最终会会选择弃用 CocoaPods,前面介绍过,兼容两者可能带来一些昂贵的额外维护成本,并且相比较于 CocoaPods,Flutter Team 目前更看好 Swift 和 SwiftPM 。
所以基本可以看到,目前 Flutter 的整体都在往 SwiftPM 迁移,但是维护两套依赖管理方案肯定不是明智之举,具体原因我们前面也聊过,所以从我个人角度看,按照 Flutter 的尿性,只要 SwiftPM 正式落地,弃用 CocoaPods 的通知也就不远了。
不过也不用担心,从目前看来,SwiftPM 的落地还有挺长一段时间要走,例如 Add to App 场景的支持就是一个问题,因为 SwiftPM 没有像 CocoaPods 那样将包转换为 xcframework 的方法,同时 SwiftPM 需要知道在哪里找到框架,不然它就无法正常解析。
所以如果你还没使用或者迁移到 SwiftPM, 可以考虑先了解或者尝试下,整体体验式其实 SwiftPM 确实比如 CocoaPods 优秀,并且更轻巧简便,所以我个人还是希望 SwiftPM 可以在 Flutter 上早日落地,毕竟讨厌 OC 和 CocoaPods 不是很正常吗?
相关文章:

Flutter 正在迁移到 Swift Package Manager ,未来会弃用 CocoaPods 吗?
什么是 Swift Package Manager ?其实 Swift Package Manager (SwiftPM) 出现已经挺长一段时间了,我记得第一次听说 SwiftPM 的时候,应该还是在 2016 年,那时候 Swift 3 刚发布,不过正式出场应该还是在 2018 年的 Apple…...

PDF——分割pdf的10个工具
PDF分割器是一种可用于将PDF文档分割成更小的文档甚至单个页面的工具。分割 PDF 文档的主要原因是为了更容易共享。 但该过程的成功取决于您用于拆分 PDF 的工具。较简单的工具仅提供几个选项,可能并不适合所有类型的文档。我们将在本文中列出的 10 个最佳 PDF 分割…...

深入解析 Nginx 反向代理:配置、优化与故障排除
深入解析 Nginx 反向代理:配置、优化与故障排除 Nginx 是一个高性能的 HTTP 和反向代理服务器,它以其高并发和高可扩展性在业界享有盛誉。反向代理是 Nginx 的重要功能之一,通过反向代理可以实现负载均衡、安全代理、缓存等多种用途。本篇文…...

深度学习入门(一):感知机与输入数据
单层感知机与多层感知机 单层感知机(Single-Layer Perceptron)和多层感知机(Multi-Layer Perceptron,简称MLP)是神经网络的基本形式,用于执行各种机器学习任务,包括分类和回归。它们都基于早期…...

kubernetes 集群组件介绍
kubernetes 集群组件介绍 Kubernetes 架构 在Kubernetes(k8s)集群中,主节点(Master Node)和工作节点(Worker Node)都运行特定的软件组件,它们共同管理和运行容器化的应用程序。以下…...

Java | Leetcode Java题解之第327题区间和的个数
题目: 题解: class Solution {public int countRangeSum(int[] nums, int lower, int upper) {long sum 0;long[] preSum new long[nums.length 1];for (int i 0; i < nums.length; i) {sum nums[i];preSum[i 1] sum;}BalancedTree treap ne…...

开发一个MutatingWebhook
介绍 Webhook就是一种HTTP回调,用于在某种情况下执行某些动作,Webhook不是K8S独有的,很多场景下都可以进行Webhook,比如在提交完代码后调用一个Webhook自动构建docker镜像 准入 Webhook 是一种用于接收准入请求并对其进行处理的…...

【leetcode详解】另一棵树的子树 (C++递归:思路精析 过程反思)
思路详解: 总体框架: 对root树进行先序遍历,如果当前结点(记为cur)的值和subRoot的根节点值相等时,就开始判断 以cur为根节点的树 和 子树 是否结构一样? 如何判断两棵树是否结构完全相同? …...

物联网遇到人工智能,极快的加速物联网时代
近些年物联网已成为众多科技企业的战略目标,如智能家居等,在未来,手机、传感器等智能设备都走进了生活当中,据数据显示已经有80%以上的的智能手机配备了人工智能。人工智能也不陌生,自动驾驶、人脸识别这些应用场景都是…...

Vue3+Ts项目中经常遇到导入组件,vscode报无法找到模块xxx,xxx隐式拥有 “any“ 类型解决办法~
1、报错截图: 2、解决办法:在确保路径正确的情况下,你会在 src 目录下找到一个名为 env.d.ts 的文件(或者类似的名称)。在这个文件中,你可以声明 .vue 文件的模块类型。例如:(这告诉 TypeScript…...

郑州轻工业大学zzulioj1151~1159合集
郑州轻工业大学zzulioj1151~1159合集 郑州轻工业大学zzulioj1151~1159合集 1150数数多少个整数1151大整数加法题目描述1152: 二分搜索1153简易版最长序列题目描述1154: 校门外的树1155字符串比较 多实例题目描述1156单数变复数题目描述1157连续的n个1题目描述1158又是排序&…...

开发框架DevExpress XAF v24.2产品路线图预览——增强跨平台性
DevExpress XAF是一款强大的现代应用程序框架,允许同时开发ASP.NET和WinForms。XAF采用模块化设计,开发人员可以选择内建模块,也可以自行创建,从而以更快的速度和比开发人员当前更强有力的方式创建应用程序。 DevExpress XAF是一…...

程序员短视频上瘾综合症
一、是你疯了还是面试官疯了? 最近有两个学员咨询问题,把我给整得苦笑不得。大家来看看,你有没有同样的症状。 第一个学员说去一家公司面试,第一轮面试聊得挺好的。第二轮面试自我感觉良好,但是被面试官给Diss…...

image.convert()函数转换格式及显示图像的RGB三通道图像
引 言 视觉任务处理的图片按照图像通道深度分为单通道图像和多通道图像。单通道图像有grayscale灰度图、binary二值图、PNG图,多通道图像有三通道24位真彩色RGB图,8位伪彩色图像,YCbCr图像等。本文先介绍各种格式图像的特点,随后讲…...

C语言 ——— 在控制台实现扫雷游戏(一次展开一片,递归实现)
前言 两个数组,一个用来显示在控制台上,一个用来存放雷 两个数组的实际大小为11 * 11 ,而为了方便排查雷的个数,实际使用范围是9 * 9 test.c #include"mine_sweeping.h"void game() {// 存放雷char mine[ROWS][COL…...

el7升级Apache模块编译
1.背景 接续https://blog.csdn.net/nanhai_happy/article/details/140566070,由于升级升级Apache过程中,发现需要使用的mod_wsgi、mod_systemd和mod_cgi模块缺失,故接着解决继续编译生成。 2. 编译mod_cgi、mod_system 2.1 安装依赖 yum …...

Linux系统下的日志管理与ELK Stack实践
关于“Linux系统下的日志管理与ELK Stack实践”,这个主题涵盖了如何在Linux环境中高效地收集、解析、存储及分析日志,以及如何利用ELK Stack(Elasticsearch、Logstash、Kibana)这套工具来实现日志的集中管理和可视化。下面我会简要…...

C++入门基础知识
在之前我们学习了C语言和初阶数据结构的相关知识,现在已经有了一定的代码能力和对数据结构也有了基础的认识,接下来我们将进入到新的专题当中,这个专题就是C。在C中我们需要花费更大的精力和更长的时间去学习这门建立在C语言基础之上的计算机…...

Python爬虫技术 第28节 数据可视化
Python 爬虫设计结合数据可视化是一个非常强大的组合,可以用来分析和展示从网络获取的数据。以下是如何设计一个 Python 爬虫并结合数据可视化的详细步骤: 步骤 1: 确定数据源和目标 首先,确定你想要爬取的数据源和目标。例如,你…...

react中的装饰器
一、初见react装饰器 初初接触react,发现一些神秘符号和语法,觉得很神奇。类似这样: import React, { PureComponent, Fragment } from react; import {Form} from antd;Form.create() class UpdateForm extends PureComponent {。。。 }哇…...

Elasticsearch:用例、架构和 6 个最佳实践
1. 什么是 Elasticsearch? Elasticsearch 是一个开源分布式搜索和分析引擎,专为处理大量数据而设计。它建立在 Apache Lucene 之上,并由Elastic 支持。Elasticsearch 用于近乎实时地存储、搜索和分析结构化和非结构化数据。 Elasticsearch 的…...

tcp常用网络接口 linux环境
TCP(传输控制协议)网络通信是常见的网络应用形式,它提供了面向连接的、可靠的数据传输服务。TCP通信常用的接口主要包括以下几个方面: 常用接口 1. socket() int socket(int domain, int type, int protocol); 功能࿱…...

第10节课:JavaScript基础——网页交互的魔法
目录 JavaScript的作用JavaScript的基本语法基本语法规则变量、数据类型和运算符变量数据类型运算符 实践:使用JavaScript增强网页功能结语 JavaScript是一种高级的、解释型的编程语言,它使得网页能够从静态文档转变为具有动态交互性的应用程序。本节课将…...

springboot+vue+mybatis汽车租赁管理+PPT+论文+讲解+售后
汽车租赁系统是针对目前汽车租赁管理的实际需求,从实际工作出发,对过去的汽车租赁管理系统存在的问题进行分析,完善客户的使用体会。采用计算机系统来管理信息,取代人工管理模式,查询便利,信息准确率高&…...

.NET C# 将文件夹压缩至 zip
.NET C# 将文件夹压缩至 zip 文章目录 .NET C# 将文件夹压缩至 zip1 使用 System.IO.Compression1.1 环境1.2 压缩文件夹1.2.1 简单压缩1.2.2 复杂压缩 1.3 解压缩1.3.1 简单解压缩1.3.2 复杂解压缩 2 使用 SharpZipLib2.1 环境2.2 压缩文件夹2.3 解压缩 3 压缩效果简单测试 1 …...

软考基本介绍
一,基本了解 计算机技术与软件专业技术资格(水平)考试(简称软件考试)为国家级考试。 考试设置了27个专业资格,涵盖5个专业领域, 3个级别层次(初级、中级、高级)。 中国计算机技术职业…...

【Vue】vue3 中使用 ResizeObserver 监听元素的尺寸宽度变化
要监听 div 宽度的变化,可以使用 ResizeObserver 接口。ResizeObserver 允许你观察一个或多个元素的尺寸变化,并在发生变化时执行回调函数。这种方法比使用 MutationObserver 更专注于尺寸变化,且不受元素属性变化的影响。 使用 ResizeObserv…...

信息安全专业好吗?
22 届的 211 信安毕业生,目前在读研(虽然已经和安全没关系),整体来看大部分高校的信安都是作为计算机的附属专业存在的,除了极具特色的几个高校,例如山大的密码学,广州大学某院士加持的网络安全…...

梧桐数据库(WuTongDB):数据库中元数据表的常见信息
元数据表是数据库系统中用于存储和管理元数据的表。这些表提供关于数据库对象(如表、列、索引、视图、存储过程等)的详细信息。以下是元数据表的一些常见类型及其详细解释: 常见元数据表类型 表信息表 表名:TABLES描述࿱…...

在 Linux 9 上安装 Oracle 19c:克服兼容性问题 (INS-08101)
Oracle 数据库 19c 的基础版本 (19.3) 发布的时候还没有 Linux 9 ,因此在Linux 9上面安装Oracle 19c会遇到很多兼容性问题。本文将探讨如何解决这些问题。 安装步骤 设置环境变量以绕过操作系统检查: Oracle 19.3 安装程序无法识别 Linux 9。 [WARNIN…...