如何在Swift中打印变量名?

e4eetjau  于 6个月前  发布在  Swift
关注(0)|答案(1)|浏览(81)

我经常发现自己输入像print("myVar: \(myVar)")这样的调试打印,当我想打印几个这样的变量时,编写它变得乏味。
我想写一个函数(如果是内置的,就使用它),它只需要我输入一次名字,比如printVar(myVar),如果myVar的值是20,它就会打印myVar: 20
所以我的问题是:

  • 你知道有一个内置的Swift函数已经提供了这样的功能吗?我是一个经验丰富的Swift开发人员,我从来没有听说过这样的事情,我也搜索了文档,谷歌和StackOverflow,都没有用-不,dump()不做这项工作
  • 否则,你知道如何获取字符串形式的变量 name 吗?
  • 镜像或KeyPaths都不合适,它们只处理声明类型的属性名,而不是变量名。我也不想改变我的代码架构来添加日志,所以为此目的声明一个结构不是一个有效的答案。
  • 我也搜索了宏,但我对它们的可能性只有最少的了解。

如果我有这个,我甚至可以写一个变元函数,然后只需输入一个简洁的

printVars(myVar, myOtherVar, myThirdVar)

字符串
得到一个漂亮的日志,这将是一个真正节省时间:

myVar: 20
myOtherVar: MyEnum.myCase
myThirdVar: "Arthur"

i86rm4rw

i86rm4rw1#

如果你不介意使用宏,你可以写一个独立的表达式宏,如下所示:

public struct PrintWithVariableName: ExpressionMacro {
    public static func expansion(
        of node: some FreestandingMacroExpansionSyntax,
        in context: some MacroExpansionContext
    ) throws -> ExprSyntax {
        let argExpressions = node.argumentList.map(\.expression)
        let printArgs = LabeledExprListSyntax {
            for expression in argExpressions {
                LabeledExprSyntax(
                    expression: StringLiteralExprSyntax(content: expression.trimmedDescription + ":")
                )
                LabeledExprSyntax(expression: expression)
            }
        }
        return "print(\(printArgs))"
    }

    /*
    // an alternative implementation that expands to a closure that is invoked immediately,
    // containing a print call for each expression, so that they are printed on separate lines
    public static func expansion(
        of node: some FreestandingMacroExpansionSyntax,
        in context: some MacroExpansionContext
    ) throws -> ExprSyntax {
        let argExpressions = node.argumentList.map(\.expression)
        let block = CodeBlockItemListSyntax {
            for expression in argExpressions {
                "print(\(literal: expression.trimmedDescription + ":"), \(expression))"
            }
        }
        return """
        {
            \(block)
        }()
        """
    }
    */
}

字符串
将其添加到providingMacros列表中,并像这样声明:

@freestanding(expression)
public macro printWithNames(_ args: Any...) = 
    #externalMacro(module: "...", type: "PrintWithVariableName")


使用方法:

#printWithNames(x, y)
// expands to:
print("x:", x, "y:", y)

相关问题