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

Swift中如何不使用debugDescription获取Published<String>的值?

解决@Published变量的下标访问与值获取问题

核心改进方案

  • 抛弃解析debugDescription的不可靠方式,直接利用Published作为@propertyWrapper的标准API——wrappedValue属性获取实际值
  • 优化下标逻辑,支持直接传入原始属性名(如"str"),无需手动拼接编译器生成的下划线前缀("_str")

修改后的完整代码

import Foundation
import Combine

protocol PropertyReflectable {}

extension PropertyReflectable {
    subscript(key: String) -> Any? {
        // 优先查找非@Published属性
        if let value = Mirror(reflecting: self).children.first({ $0.label == key })?.value {
            return value
        }
        // 自动拼接下划线前缀,查找@Published生成的存储属性
        let publishedKey = "_\(key)"
        return Mirror(reflecting: self).children.first({ $0.label == publishedKey })?.value
    }
}

class Foo : PropertyReflectable {
    @Published var str: String = "bar"
    var str2: String = "bar2"
}

// 直接通过wrappedValue获取Published包装的实际值
func getStringValue(_ obj: Combine.Published<String>?) -> String? {
    return obj?.wrappedValue
}

let f = Foo()

// 现在可以直接用原始属性名"str"访问
let str = getStringValue(f["str"] as? Published<String>)
print("got str: \(str!)")
// 输出: got str: bar

let str2 = f["str2"] as! String
print("got non-published string easily: \(str2)")
// 输出: got non-published string easily: bar2

细节说明

  1. wrappedValue的可靠性:@Published是官方定义的@propertyWrapper,所有符合规范的包装器都会公开wrappedValue属性来暴露被包装的实际值,这是官方支持的稳定访问方式,完全不会受debugDescription格式变更的影响。

  2. 下标逻辑优化:原代码需要手动传入下划线前缀的属性名,修改后的下标会先尝试原始属性名,失败后自动拼接下划线查找编译器生成的@Published存储属性,使用时更符合直觉。

  3. 类型安全升级(可选):如果需要更严格的类型安全,可以添加泛型版本的下标,避免频繁类型转换:

extension PropertyReflectable {
    subscript<T>(key: String) -> T? {
        // 直接获取非@Published属性
        if let value = Mirror(reflecting: self).children.first({ $0.label == key })?.value as? T {
            return value
        }
        // 获取@Published属性并自动解包wrappedValue
        let publishedKey = "_\(key)"
        if let publishedValue = Mirror(reflecting: self).children.first({ $0.label == publishedKey })?.value as? Published<T> {
            return publishedValue.wrappedValue
        }
        return nil
    }
}

使用泛型下标时无需额外的getStringValue函数:

let str = f["str"] as String?
print("got str: \(str!)")
let str2 = f["str2"] as String?
print("got non-published string easily: \(str2!)")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 05:20:27