Swift Macro中自定义协议的声明位置及@ServiceProvidable实现问询
Swift Macro自定义协议的存放位置与实现方案
先说核心结论:自定义协议(比如你例子里的ServiceProvidable)必须放在主应用项目(或者主项目能访问的公共模块)里,绝对不能放在Macro Package中。
为什么不能放Macro Package?
Macro Package是编译期的工具代码,它的作用只是生成代码,不会被打包进最终App。而且主项目是依赖Macro Package的,反向依赖不成立——如果协议放在Macro Package里,主项目编译时根本找不到这个协议的定义,宏生成的extension ViewControllerWrapper: ServiceProvidable代码会直接报错。
具体实现步骤
1. 先在主项目定义所有需要的协议和类型
把ServiceProvidable、ServiceProviderProtocol、ServiceProvider这些都写在主项目里(或者抽成主项目依赖的Core公共模块),因为宏生成的代码要直接引用它们:
// 主项目/Core模块中定义 protocol ServiceProviderProtocol { // 这里写服务提供者需要的方法/属性 } class ServiceProvider: ServiceProviderProtocol { // 实现协议逻辑 } protocol ServiceProvidable { var service: ServiceProviderProtocol { get } }
2. 在Macro Package中实现@ServiceProvidable宏
Macro里只需要负责生成遵循协议的扩展代码就行,不用关心协议的具体实现,只要保证生成的代码能在主项目中编译通过:
// Macro Package中的宏实现 import SwiftSyntax import SwiftSyntaxMacros import SwiftSyntaxBuilder public struct ServiceProvidableMacro: MemberMacro { public static func expansion( of node: AttributeSyntax, providingMembersOf declaration: some DeclGroupSyntax, in context: some MacroExpansionContext ) throws -> [DeclSyntax] { // 生成对应类的扩展代码 return [ """ extension \(declaration.name): ServiceProvidable { var service: ServiceProviderProtocol { guard let serviceProvider = (UIApplication.shared.delegate as? AppDelegate)?.serviceProvider else { return ServiceProvider() } return serviceProvider } } """ ] } } // 注册宏 @main struct ServiceProvidableMacroPlugin: CompilerPlugin { let providingMacros: [Macro.Type] = [ ServiceProvidableMacro.self ] }
3. 在主项目中使用宏
主项目添加Macro Package依赖后,直接给目标类标记宏即可:
@ServiceProvidable class ViewControllerWrapper { // 类的原有代码 }
额外注意点
- 宏生成代码里引用的
AppDelegate、UIApplication这些,都是主项目里的类型,只要主项目能访问到就没问题。 - 如果后续要重构,把协议和服务类抽成公共模块,只要主项目和Macro Package都依赖这个公共模块就行——Macro只需要知道这些类型的名称,不需要知道具体实现逻辑。
内容的提问来源于stack exchange,提问作者SOWOL KIM
相关产品推荐
相关产品推荐

