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

Swift如何打印修改结构体属性的所属文件或类名称

实现方案

这里提供两种常用实现方式,你可以根据自己的业务场景选择:

方案1:调用侧零侵入(推荐)

利用Swift的属性观察器+线程调用栈解析,不需要修改任何现有赋值代码,只需要调整People结构体的属性定义即可:

import Foundation

struct People {
    var name: String = "" {
        didSet {
            // 取第2位调用栈符号(第0位是当前didSet本身)
            guard Thread.callStackSymbols.count >= 2 else {
                print("Unknown edited People")
                return
            }
            let stackInfo = Thread.callStackSymbols[1]
            // 解析调用方类名
            let pattern = #"[^ ]+ +[^ ]+ +([^\.]+)\."#
            if let regex = try? NSRegularExpression(pattern: pattern),
               let match = regex.firstMatch(in: stackInfo, range: NSRange(stackInfo.startIndex..., in: stackInfo)),
               let range = Range(match.range(at: 1), in: stackInfo) {
                let callerName = String(stackInfo[range])
                print("\(callerName) edited People")
                return
            }
            // 解析失败时回退输出默认值
            print("Unknown edited People")
        }
    }
}

之后你在任意位置赋值people.name = "Tom"都会自动输出对应调用方的类名。


方案2:精度更高的属性包装器方案

如果需要更精准的自定义输出内容,避免调用栈解析的偶发误差,可以用属性包装器实现:
首先定义属性包装器:

@propertyWrapper
struct EditLog<T> {
    private var storedValue: T
    var wrappedValue: T {
        get { storedValue }
        set {
            // 直接赋值时默认取文件名作为调用方标识
            let fileName = (#file as NSString).lastPathComponent.replacingOccurrences(of: ".swift", with: "")
            print("\(fileName) edited People")
            storedValue = newValue
        }
    }
    
    init(wrappedValue: T) {
        self.storedValue = wrappedValue
    }
    
    /// 传入调用方实例精准输出类名
    mutating func set(_ value: T, caller: Any) {
        storedValue = value
        let callerName = String(describing: type(of: caller))
        print("\(callerName) edited People")
    }
}

调整People结构体定义:

struct People {
    @EditLog var name: String = ""
}

使用方式:

// 在ClassA.swift中调用时
var people = People()
// 方式1:直接赋值,自动输出文件名
people.name = "Tom"
// 方式2:传入self,精确输出类名
people.$name.set("Tom", caller: self)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 23:09:03