Swift 中 @preconcurrency 修饰符使用浅谈

在这里插入图片描述

概述

Swift 6.0 与我们越来越近了,如何将旧范儿的并发代码装换为严格遵守 Swift 6.0 并发模型( Strict Concurrency)的新代码,这往往使得秃头码农们又要多抓掉几根头发了。

在这里插入图片描述

所以,为了最大限度的保持新旧两个并发世界暂时的“和平共处”,苹果特地推出了 @preconcurrency 修饰符让我们能得以优雅的“樽前月下”。

在本篇博文中,您将学到如下内容:

  • 概述
  • 1. @preconcurrency 是干啥用的?
  • 2. 导入中的 @preconcurrency
  • 3. 类型修饰中的 @preconcurrency
  • 4. 一些使用提示
  • 总结

闲言少叙,让我们马上开始 Swift 并发大冒险吧!

Let‘s go!!!😉


1. @preconcurrency 是干啥用的?

从 Swift 5.6(正式支持 @preconcurrency 的第一个 Swift 编译器版本)开始,苹果为 Swift 语言引入了@preconcurrency 修饰符。

当项目使用严格并发检查模式(strict concurrency checks)时我们可以使用它来让大量产生的编译器警告和错误“通通闭嘴”。

在这里插入图片描述

@preconcurrency 修饰符可以应用在以下 4 种语境中:

  • functions
  • types
  • protocols
  • imports

那么接下来就让我们在这些语境中挑一些比较典型的使用情况和大家一起聊聊,以便充分了解 @preconcurrency 是如何帮助我们在启用严格并发检查时规避一些“细枝末节”的,即使暂时我们还不能更新所有的依赖项。

2. 导入中的 @preconcurrency

在我们导入第三方模块时,有时编译器会“贴心”的做出如下提示:

import MyModule

在这里插入图片描述

这个“错误”告诉我们:我们正在导入一个似乎还没有完全遵守现代并发规则的模块。由于这可能不是小伙伴们能够掌控的模块,于是乎 Xcode 提供了“消除”来自该模块严格并发警告和错误的能力。

在这里插入图片描述

我们可以通过在导入语句中添加 @preconcurrency 修饰符来达成此目的:

@preconcurrency import MyModule

通过这样一番操作,Xcode 将明了与来自 MyModule 类型相关的任何警告都应该被“抑制”。

如果 MyModule 不是我们自己的模块(没有源代码),那么消除该警告是非常有意义的,因为无论如何我们都无法修复它们。

值得注意的是:这样做不会“抑制”与 MyModule 中可发送(Sendable)或最新现代并发代码相关的警告。

因此,如果我们在用 @preconcurrency 标记的模块上看到与并发相关的警告时,大家一定希望随后能够在适当的时候修复这些警告,因为此时我们有点像“掩耳盗铃”的撸码者。

3. 类型修饰中的 @preconcurrency

另一种可能的情况是,我们正在处理一个采用 Swift 新并发模式的模块,并且已经修复了警告。

如果是这样的话,我们可能需要在一些声明中添加 @preconcurrency 修饰符,以确保依赖于我们模块的代码不会失去兼容性(“被打断”)。

这意味着采用 Swift 新并发检查会导致我们的模块 ABI 接口发生变化,如果旧代码不遵循 Swift 新并发范式,那么它们可能无法使用你无与伦比的模块。

如果小伙伴们正处于这种情况,我们可能已经转换了一些旧代码:

public class CatalogViewModel {
  public private(set) var books: [Book] = []

  public init() {}

  func loadBooks() {
    // 加载书籍
  }
}

到如下新代码:

@MainActor
public final class CatalogViewModel {
  public private(set) var books: [Book] = []

  public init() {}

  public func loadBooks() {
    // 加载书籍
  }
}

此时,倘若我们编写了一些使用 CatalogViewModel 类的并发代码,它们可能看起来有点像这样:

class TestClass {
  func run() {
    let obj = CatalogViewModel()
    obj.loadBooks()
  }
}

遗憾的是,上面的代码会被编译器“大爆粗口”:

Call to main actor-isolated initializer ‘init()’ in a synchronous nonisolated context.
Call to main actor-isolated instance method ‘loadBooks()’ in a synchronous nonisolated context.

这是因为将 @MainActor 添加到模块中的类中会使我们无法使用视图模型(View Model),除非我们自己将指令流分发到主线程上去。

为了与 CatalogViewModel 顺畅交互,我们需要更新项目以使用 @MainActor。不过,这通常会滚雪球般地导致越来越多的代码被修改,这会使我们模块中的更改严重的“物是人非”,讨厌的不要不要的。

这时,一种解决之道就是可以将 @preconcurrency 应用到我们的视图模型上,以允许尚未更新的代码与我们的视图模式达成“良好的共识”,就好像它从未被用 @MainActor 修饰过一样:

@preconcurrency @MainActor 
public final class CatalogViewModel {
  public private(set) var books: [Book] = []

  public init() {}

  public func loadBooks() {
    // 加载书籍
  }
}

注意:以上仅适用于未启用严格新并发检查的项目哦。


在为我们整个类应用 @preconcurrency 修饰后,编译器将该类的并发检查设置为最小(minimal)的等级,就好像 @MainActor 修饰不存在一样。如果使用严格的并发检查,编译器仍然会由于没有将 CatalogViewModel 与 @MainActor 一起使用而发出错误。

4. 一些使用提示

综上所示,我们使用 @preconcurrency 修饰符可以将旧模块导入到新代码中,并允许在旧项目中使用新代码。随着 Swift 6 的发布临近,这是一个逐步采用严格并发的好开头。

当我们导入尚未更新以实现严格并发的模块时,向导入语句中添加@preconcurrency 是非常有用滴。

另外,在注释为 @Sendable、@MainActor 或以其它方式更新的声明中添加@preconcurrency 修饰符,使其无法在非并发代码中使用,这对库作者来说也具有非同一般的意义。

现在,我们彻底搞懂了 @preconcurrency 的作用,大家的新并发功力愈发的炉火纯青了!小伙伴们还不赶紧给自已一个大大的赞吧!

总结

在本篇博文中,我们介绍了 Swift 语言中 @preconcurrency 修饰符的作用,以及它在一些应用语境中“雪中送炭”的具体示例。

感谢观赏,再会!😎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/675019.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Paddle实现单目标检测

单目标检测 单目标检测(Single Object Detection)是人工智能领域中的一个重要研究方向,旨在通过计算机视觉技术,识别和定位图像中的特定目标物体。单目标检测可以应用于各种场景,如智能监控、自动驾驶、医疗影像分析等…

玩转Linux进度条

准备工作&#xff1a; 一.关于缓冲区 首先&#xff0c;咱们先来一段有意思的代码&#xff1a; #include<stdio.h> #include<unistd.h> int main() {printf("you can see me");sleep(5);} 你可以在你的本地运行一下&#xff0c;这里我告诉大家运行结果…

android睡眠分期图

一、效果图 做医疗类项目&#xff0c;经常会遇到做各种图表&#xff0c;本文做的睡眠分期图。 二、代码 引入用到的库 api joda-time:joda-time:2.10.1 调用代码 /*** 睡眠* 分期*/private SleepChartAdapter mAdapter;private SleepChartAttrs mAttrs;private List<SleepI…

d2-crud-plus 使用小技巧(六)—— 表单下拉选择 行样式 溢出时显示异常优化

问题 vue2 elementUI d2-crud-plus&#xff0c;数据类型为select时&#xff0c;行样式显示为tag样式&#xff0c;但是如果选择内容过长就会出现下面这种bug&#xff0c;显然用户体验不够友好。 期望 代码 js export const crudOptions (vm) > {return {...columns:…

成功解决“ModuleNotFoundError: No Module Named Pycocotools”错误的全面指南

成功解决“ModuleNotFoundError: No Module Named Pycocotools”错误的全面指南 在Python的数据科学、计算机视觉和机器学习项目中&#xff0c;经常需要用到各种工具和库来加速开发过程。其中&#xff0c;pycocotools 是一个专门用于处理 COCO 数据集的库&#xff0c;它提供了多…

2024年Google算法更新打击低质量(如AI生成)内容后,英文SEO优化人员该如何调整谷歌SEO优化策略?

3月5日&#xff0c;谷歌发布了2024年的首次算法更新。与以往更新不同&#xff0c;本次更新更加复杂&#xff0c;这次更新旨在提高搜索结果的质量和相关性&#xff0c;可能对外贸网站排名和流量产生显著影响。也将产生更大的网站数据波动。但在担心自己的网站数据受到影响之前&a…

Django 里的增删改查

下面是步骤 先更新 urls.py 来添加新的url from django.contrib import admin from django.urls import path from app01 import viewsurlpatterns [path(demo/, views.demo), ]在 models.py 里创建表 from django.db import models# Create your models here. class UserI…

毫米级精度3D人脸扫描设备,助推打造元宇宙虚拟分身

在元宇宙中&#xff0c;虚拟分身对应的是一个三维模型&#xff0c;数字化的过程则是三维重建过程&#xff0c;通过3D人脸扫描可以通过多相机同步采集人脸部&#xff0c;可快速、准确地重建出真人地脸部模型及贴图&#xff0c;通过3D人脸扫描设备可快速重建出高逼真的虚拟分身。…

BioTech - 使用 Kubeflow 多机多卡 运行 高精度蛋白质结构的迭代预测

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/139418138 核心逻辑,参考:使用 循环(Recycle)迭代的蛋白质结构预测 获取 高精度结构 Kubeflow 是一个开源的 Kubernetes 原生框架,专注于简化、可移植和可…

【反悔贪心】算法讲解

目录 cf865D 环形喂猪 建筑抢修 cf865D 思路&#xff1a; 我们贪心的原则是尽可能的多卖&#xff0c;而且尽可能的卖的多。 整体的贪心思路就是能卖就卖&#xff0c;卖完后放入堆中&#xff08;以便反悔&#xff09;&#xff0c;先不考虑能卖多少&#xff0c;因为堆是按照价…

02--nginx代理缓存

前言&#xff1a;比较常用的用法反向代理&#xff0c;和缓存的一些操作&#xff0c;用虚拟环境复刻出来&#xff0c;里面参数不用详细记录&#xff0c;用作复习&#xff0c;使用时直接查找即可。环境搭建过程参考前一篇文章nginx基础。 1、基础环境 IP角色作用192.168.189.143…

AWR设置工程仿真频率、原理图仿真频率、默认单位

AWR设置工程仿真频率、原理图仿真频率、默认单位 生活不易&#xff0c;喵喵叹气。马上就要上班了&#xff0c;公司的ADS的版权紧缺&#xff0c;主要用的软件都是NI 的AWR&#xff0c;只能趁着现在没事做先学习一下子了&#xff0c;希望不要裁我。 最近稍微学习了一下AWR这个软…

参加质量源于设计QbD培训能学到什么

近年来&#xff0c;产品质量已经成为了企业能否立足市场的关键。因此&#xff0c;质量源于设计&#xff08;QbD&#xff09;的理念应运而生&#xff0c;它强调在产品开发初期就注重质量设计&#xff0c;以最大限度地降低潜在风险&#xff0c;提高产品的稳定性和可靠性。参加质量…

诺亚财富——财富管理行业的进化逻辑

詹姆斯•卡斯的著作《有限与无限的游戏》中&#xff0c;传递出这样一种观点&#xff1a; “有限的游戏&#xff0c;其目的在于赢得胜利&#xff1b;无限的游戏&#xff0c;却旨在让游戏永远进行下去。有限的游戏在边界内玩&#xff0c;无限的游戏玩的就是边界。” 在商业社会…

我的app开始养活我了

大家在日常使用各类 app 时应该会发现&#xff0c;进入 app 会有个开屏广告&#xff0c;在使用 app 中&#xff0c;时不时的也会有广告被我们刷到。 这时候如果我们看完了这个广告&#xff0c;或者点击了这个广告的话&#xff0c;app商家就会获得这个广告的佣金。 这个佣金就是…

用WebStorm和VS Code断点调试Vue

大家好&#xff0c;我是咕噜铁蛋&#xff01;。今天&#xff0c;我想和大家分享一下如何在WebStorm和VS Code这两款流行的开发工具中&#xff0c;使用断点调试Vue.js项目。Vue.js作为前端三大框架之一&#xff0c;以其轻量级和组件化的特性&#xff0c;受到了广大开发者的喜爱。…

18、matlab信号生成与预处理--剔除异常值:hampel()函数

1、语法 说明&#xff1a;对输入向量x应用Hampel滤波器来检测和去除异常值。 1&#xff09;y hampel(x) 参数&#xff1a;x&#xff1a;输入信号 y:预处理的输出信号 对于x的每个样本&#xff0c;函数计算由样本及其周围的六个样本组成的窗口的中位数&#xff0c;每边三…

Linux下的Git应用及配置

1、卸载 2、安装 3、创建并初始化 4、配置 &#xff08;附加删除语句&#xff09; 5、查看&#xff08;tree .git/&#xff09; 6、增加和提交 7、打印日志 8、验证已操作工作

LeetCode刷题:反转链表

leetCode真题 206. 反转链表 属于基础简单题目 常见的做法有递归和while循环 递归 // 1. 递归参数和返回值public static ListNode reverseList(ListNode head) {// 1. 递归终止条件if (head null || head.next null) {return head;}// 递归逻辑ListNode last reverseL…

安全攻防知识——CTF之MISC

前言&#xff1a; 本周技术分享将介绍安全攻防知识中的MISC部分。MISC&#xff0c;中文即杂项&#xff0c;包括隐写、数据还原、脑洞、社会工程、压缩包解密、流量分析取证、与信息安全相关的大数据等。让我们一起来了解更多吧&#xff01; 一&#xff09;文件结构简介 1.常见…