当前位置: 首页 > article >正文

Swift 宏(Macro)入门趣谈(四)

在这里插入图片描述

概述

苹果在去年 WWDC 23 中就为 Swift 语言新增了“其利断金”的重要小伙伴 Swift 宏(Swift Macro)。为此,苹果特地用 2 段视频(入门和进阶)颇为隆重的介绍了它。

在这里插入图片描述

那么到底 Swift 宏是什么?有什么用?它和 C/C++ 语言中的宏又有什么异同呢?本系列博文将会尝试为小伙伴们揭开 Swift 宏的神秘面纱。

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

  • 概述
  • 5. 书归正传:略显复杂的解决方案
    • 5.1 定义宏接口
    • 5.2 初步实现宏主体
    • 5.3 补全客户端中宏的使用代码
  • 总结

相信学完本系列博文后,Swift Macro 会从大家心中的“阳春白雪”变为“阳阿薤露”,小伙伴们必可以将它们运用的“如臂使指”。

那还等什么呢?Let‘s go!!!😉


5. 书归正传:略显复杂的解决方案

首先对于我们的需求,必须先决定到底应该用使用哪种类型的宏。要在 7 种宏角色里选出一个合适的貌似有些头大呢。

回到博文开头 sortItemsBy 方法的实现中再回顾一下:

func sortItemsBy<Value: Comparable>(keyPath: KeyPath<Item, Value>, sortOrder: SortOrder = .forward) throws -> [Item] {
    items.sorted(using: SortDescriptor(keyPath, order: sortOrder))
}

可以看到我们的需求其实很简单:就是根据现有排序方法自动生成一个实参 KeyPath 中为可选 Value(KeyPath<Item, Value?>)类型的新方法。

注意,我们实际的意图是用宏在原有方法上自动生成一个新方法,并同时保留原有方法。

所以很显然,使用附属宏中的 peer 子类型最为切题和恰当:

在这里插入图片描述

在给自定义宏定下一个基调之后,我们现在可以着手来实现它啦!


注意,不是说只能用 @attached(peer) 宏才能实现我们这一功能,用其它种类的宏也是可以办到的,只不过可能方式和难易不同而已。


5.1 定义宏接口

首先,我们需要完成宏接口的定义:

@attached(peer, names: arbitrary)
public macro nilable() = #externalMacro(module: "MyMacroMacros", type: "NilableMacro")

在上面的代码中,我们将 @attached(peer) 宏生成的方法进一步声明为任意(arbitrary)类型。

从上面宏接口的定义还可以知道,我们的自定义宏的(调用)名称为 @nilable。


注意,在 Swift Macros 升级后的内部实现里我们已不能在全局方法上应用 arbitrary 类型了,具体细节请小伙伴们移步如下链接观赏进一步内容:

  • [Update] Restrictions on Arbitrary Names at Global Scope in SE-0389 and SE-0397

从上面接口代码还可以获悉一个非常重要的信息:我们实际是将 @nilable 宏的具体实现放在了 MyMacroMacros 模块中的 NilableMacro 类型里。

5.2 初步实现宏主体

回到 MyMacroMacro.swift 文件中,如约新增一个 NilableMacro 结构。现在它什么也不能做,只是直接抛出了一个错误:

public struct NilableMacro: PeerMacro {
    
    public static func expansion(of node: AttributeSyntax, providingPeersOf declaration: some DeclSyntaxProtocol, in context: some MacroExpansionContext) throws -> [DeclSyntax] {
        throw MacroExpansionErrorMessage("待实现!")
    }
}

这样做的用意是:不要纠结宏展开的具体细节,而是先从全局层面入手搭建整体框架。

5.3 补全客户端中宏的使用代码

接下来进入 main.swift 文件里,为我们的 @nilable 宏增加调用测试代码:

struct Model {
    let items: [Item]
    
    @nilable
    func sortItemsBy<Value: Comparable>(keyPath: KeyPath<Item, Value>, sortOrder: SortOrder = .forward) throws -> [Item] {
        items.sorted(using: SortDescriptor(keyPath, order: sortOrder))
    }
}

运行可以看到,编译器会直接抛出我们之前在 NilableMacro 展开方法里定义的错误:

在这里插入图片描述

这说明我们自定义宏的接口与宏实现已成功“珠联璧合”,Very Nice!

在最后一篇博文中,我们将完成 @nilable 宏的全部实现,收尾整个系列文章,不见不散哦。

总结

在本篇博文中,我们讨论了如何利用之前所学一步一步描绘出我们自定义宏的蓝图:包括定义宏接口、初步构造宏主体以及补全客户端中宏的测试用例。

感谢观赏,下一篇再见喽!😎


http://www.kler.cn/a/401667.html

相关文章:

  • Android集成FCM(Firebace Cloud Messaging )
  • 为何数据库推荐将IPv4地址存储为32位整数而非字符串?
  • thinkphp6 入门(2)--视图、渲染html页面、赋值
  • 学习日志012--python中多进程,多线程
  • 自动化运维-检测Linux服务器CPU、内存、负载、IO读写、机房带宽和服务器类型等信息脚本
  • Java——并发工具类库线程安全问题
  • 数据结构(一)链表
  • 【Unity基础】对比Unity中两种粒子系统
  • ubuntu系统中使用docker-compose安装部署docker集群(本地)
  • 聚焦 NLP 和生成式 AI 的创新与未来 基础前置知识点
  • 多目标优化算法:多目标鳗鱼和石斑鱼优化算法(MOEGO)求解ZDT1、ZDT2、ZDT3、ZDT4、ZDT6,提供完整MATLAB代码
  • vue2+a-table——实现框选选中功能——js技能提升
  • 探索PyMuPDF:Python中的强大PDF处理库
  • 结构体位段+联合和枚举
  • Object.prototype.hasOwnProperty.call(item, key) 作用与用途
  • 2.5D视觉——Aruco码定位检测
  • 前端软件开发质量管控之应用质量 - 关于E2E测试的对象目的及不同方案特性对比(一)
  • ifuse不能挂载App Store下载的包ERROR: InstallationLookupFailed
  • 有关django、python版本、sqlite3版本冲突问题
  • Brave127编译指南 Linux篇-环境配置(五)
  • Python+7z.exe实现自动化压缩与解压
  • 【代码随想录|回溯算法排列问题】
  • 微信小程序-prettier 格式化
  • java实现贪心算法
  • SAM-Med2D 训练完成后boxes_prompt没有生成mask的问题
  • 首次实现!在Docker容器中运行macOS项目,自动化下载与Web体验