PropertyTracer

用于追踪属性访问的库。

Github issues Github forks Github stars Github top language

可以获取以下信息

警告 它不能正确工作,具体取决于 Swift 优化标志的设置。在默认设置下,只有 Debug 构建版本有效。

目录

用法

单个属性

例如,当我们定义

struct Item {
    @Traced(trace(_:_:))
    var title = "hello"
}

func trace<P, V>(_ access: PropertyAccess<P, V>, _ tracedKeyPath: KeyPath<P, Traced<P, V>>?) {
    print("\n[Access]------------------")
    print("\(access.accessor.description)")
    print("called from: \(access.callStackInfo.demangledSymbolName ?? "unknown")")
    if let parent = access.parent {
        print("parent: \(parent)")
    }
    if let keyPath = access.keyPath {
        print("keyPath: \(keyPath)")
    }
    if let tracedKeyPath {
        print("tracedKeyPath: \(tracedKeyPath)")
    }
    print("----------------------------")
}

假设执行以下操作

let item = Item()
print(item.title)

item.title = "new value"

item.printTitle()

此时,将调用指定的 trace 函数,输出如下

[Access]------------------
getter(String): initial value
called from: PropertyTracerTests.PropertyTracerTests.test() -> ()
----------------------------
initial value

[Access]------------------
setter(String): initial value => new value
called from: PropertyTracerTests.PropertyTracerTests.test() -> ()
----------------------------

[Access]------------------
getter(String): new value
called from: PropertyTracerTests.PropertyTracerTests.Item.printTitle() -> ()
----------------------------
new value

附加信息

也可以设置要在回调中接收的附加信息,如下所示

struct Item {
    // specify parent and variable type
    @Traced<Item, String>(trace(_:_:))
    var title = "initial value"

    init(title: String = "initial value") {
        self.title = title

        // parent object
        _title.parent.value = copiedOwn

        // keyPath
        _title.keyPath.value = \Self.title

        // traced keyPath
        _title.tracedKeyPath.value = \Self._title
    }

    func printTitle() {
        print(title)
    }

    func copiedOwn() -> Self {
        let copied = self
        return self
    }
}

在不追踪的情况下获取/设置值

例如,如果在上面描述的 trace 函数中直接访问父属性会发生什么?

trace 函数中访问属性将导致进一步调用 trace 函数,从而导致无限循环。

因此,有一些方法允许在不追踪的情况下操作值。

停止/重新开始追踪属性

追踪特定类型的所有成员属性

以下定义将导致追踪 Item 类型的所有属性。

它由宏定义,parentkeyPath 会自动设置。

附加了 @NoTraced 属性的属性将被排除在追踪之外。

@PropertyTraced(trace(_:_:))
class ClassType1 {
    static let staticVar = ""
    var value1: String = "こんにちは"
    var value2: Int = 12

    @NoTraced
    var value3: Double = 1.0

    func modify() {
        value1 = "hello"
        value2 *= 2
        value3  = 14
    }
}

func trace(_ access: AnyPropertyAccess, _ tracedKeyPath: AnyKeyPath?) {
    print("\n[Access]------------------")
    print("\(access.accessor.description)")
    print("called from: \(access.callStackInfo.demangledSymbolName ?? "unknown")")
    if let parent = access.parent {
        print("parent: \(parent)")
    }
    if let keyPath = access.keyPath {
        print("keyPath: \(keyPath)")
    }
    if let tracedKeyPath {
        print("tracedKeyPath: \(tracedKeyPath)")
    }
    print("----------------------------")
}

许可证

PropertyTracer 在 MIT 许可证下发布。请参阅 LICENSE