You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过全局编译时标记控制Swift宏条件显示/隐藏@available(*, deprecated)

实现条件性为结构体属性添加@available注解的Swift宏

要实现这个根据全局编译标记动态给结构体所有属性添加@available(*, deprecated)的宏,你可以按照以下步骤操作:

  • 定义全局编译标记
    首先在项目中设置一个自定义编译标记,比如DEPRECATE_ALL_PROPERTIES。在Xcode中可以通过Build Settings > Swift Compiler - Custom Flags > Other Swift Flags添加-D DEPRECATE_ALL_PROPERTIES来启用这个标记,移除则表示禁用。

  • 创建成员宏实现
    创建一个遵循MemberMacro协议的宏,在宏的扩展逻辑里根据编译标记判断是否为每个属性添加@available注解:

    import SwiftSyntax
    import SwiftSyntaxMacros
    import SwiftSyntaxBuilder
    
    public struct DeprecateAllPropertiesMacro: MemberMacro {
        public static func expansion(
            of node: AttributeSyntax,
            providingMembersOf declaration: some DeclGroupSyntax,
            in context: some MacroExpansionContext
        ) throws -> [DeclSyntax] {
            // 遍历结构体的所有成员属性
            let modifiedMembers = declaration.members.compactMap { member -> DeclSyntax? in
                guard let variableDecl = member.decl.as(VariableDeclSyntax.self),
                      variableDecl.bindings.count == 1,
                      variableDecl.bindings.first?.pattern.as(IdentifierPatternSyntax.self) != nil else {
                    // 只处理存储属性,跳过计算属性或其他成员
                    return member.decl
                }
                
                #if DEPRECATE_ALL_PROPERTIES
                // 标记启用时,为属性添加@available注解
                return DeclSyntax(
                    """
                    @available(*, deprecated)
                    \(variableDecl)
                    """
                )
                #else
                // 标记禁用时,返回原属性
                return member.decl
                #endif
            }
            
            return modifiedMembers
        }
    }
    
    // 宏的注册
    public struct DeprecateAllPropertiesMacroPlugin: MacroPlugin {
        public static let providingMacros: [String: Macro.Type] = [
            "MyMacro": DeprecateAllPropertiesMacro.self
        ]
    }
    
  • 使用宏
    按照你期望的方式使用宏:

    @MyMacro()
    struct X {
        var a: String
        var b: Int
    }
    

效果验证

  • 标记启用时,宏展开后代码为:

    struct X {
        @available(*, deprecated) var a: String
        @available(*, deprecated) var b: Int
    }
    
  • 标记禁用时,宏展开后代码与原结构体一致:

    struct X {
        var a: String
        var b: Int
    }
    

注意:这个宏只会处理结构体的存储属性,如果需要支持类的属性,只需要在宏的逻辑里兼容ClassDeclSyntax即可,当前实现默认只处理结构体成员。

内容的提问来源于stack exchange,提问作者bAthi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 23:30:57