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

Swift Dictionary非下标Getter实现:自定义下标重写规避递归问题

问题

我正尝试为自定义Dictionary类型重写默认下标方法,要求特定键不能存储特定类型的值,因此需要在下标setter中控制值的允许/拒绝。(这可能属于XY Problem,我也关注替代方案,但当前问题仍需解答)

下标扩展的setter部分运行正常,使用updateValue(_:forKey:)替代下标setter避免了无限递归。代码如下:

struct MyData {
    var isBadData: Bool
}

extension Dictionary where Key == String, Value == MyData {
    
    subscript(key: Key) -> Value? {
        // 省略getter会报错:Subscript with a setter must also have a getter
        get {
            return self[key] // 警告:函数调用会导致无限递归
            // 问题:是否存在非下标getter替代方案?
        }
        set(newValue) {
            if let newValue, newValue.isBadData {
                return // 不向字典中添加坏数据
            } else if let newValue {
                //self[key] = newValue // 警告:函数调用会导致无限递归
                updateValue(newValue, forKey: key) // 非下标setter替代方案可行
            } else {
                removeValue(forKey: key)
            }
        }
    }
}

但对于getter,我不知道如何不递归调用下标getter来获取字典中的值。NSDictionary有value(forKey:)方法,但Swift Dictionary文档中似乎没有类似的非下标替代方法。如何不使用下标获取Dictionary的值?或者有没有办法调用下标原实现的super方法?

解决方案

绕开递归的Getter实现

可以使用first(where:)方法遍历字典匹配键值,避免调用自定义下标:

get {
    return first(where: { $0.key == key })?.value
}

这种方式通过遍历查找值,小字典场景下性能足够,但大字典的效率会低于原生下标。

更稳妥的替代方案(解决XY Problem)

重写系统Dictionary的下标容易引发递归、依赖底层实现等问题,更推荐封装自定义结构体包裹字典,完全控制存取逻辑:

struct FilteredDictionary {
    private var storage: [String: MyData] = [:]
    
    subscript(key: String) -> MyData? {
        get {
            return storage[key]
        }
        set(newValue) {
            guard let newValue = newValue else {
                storage.removeValue(forKey: key)
                return
            }
            if !newValue.isBadData {
                storage[key] = newValue
            }
        }
    }
    
    // 按需添加字典常用方法,比如:
    var keys: Dictionary<String, MyData>.Keys { storage.keys }
    var values: Dictionary<String, MyData>.Values { storage.values }
    var count: Int { storage.count }
}

这种方式逻辑清晰,不存在递归风险,还能根据需求扩展更多自定义功能,是生产环境的优先选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 12:52:27