在 Swift 属性包装器中公开字典

Posted

技术标签:

【中文标题】在 Swift 属性包装器中公开字典【英文标题】:Exposing dictionary in Swift property wrappers 【发布时间】:2020-08-10 18:21:51 【问题描述】:

我有一个不想向用户公开的内部字典。相反,我只使用属性公开某些值,如下所示:

public var artist: String? 
  get 
     return items["artist"]
  
  set 
     items["artist"] = newValue
  


//...so on for another 20 or so items

正如您可以想象的那样,这最终会重复很多次。我在想属性包装器是清理它的好方法 - 但是,不可能将items 直接传递给包装器,因为属性包装器是在init 之前创建的(所以self 将无法访问) .

有没有办法解决这个问题,或者这只是 propertyWrappers 的限制之一?

【问题讨论】:

【参考方案1】:

您可以构建一个通用解决方案。我做了一个,但你可以改进它:

    class PropertyWrapper 
    
    private var items: [String: Any] = ["artist": "some dude"]
    
    enum Key: String 
        case artist
    
    
    func getItem<T: Any>(key: Key) -> T 
        guard let item = items[key.rawValue] as? T else 
            preconditionFailure("wrong type asked for")
        
        return item
    
    
    func setItem(value: Any, key: Key) 
        items[key.rawValue] = value
    


class GetValueClass 
    
    func getValue() 
        let wrapper = PropertyWrapper()
        let value: String = wrapper.getItem(key: .artist)
    


class SetValueClass 
    
    func setValue() 
        let wrapper = PropertyWrapper()
        wrapper.setItem(value: "some", key: .artist)
    

【讨论】:

谢谢!我已经尝试过静态方法(没有提及),这有点问题,因为我可以拥有包含属性的类的多个实例(即多个Foos,每个都有自己的artistalbum,等),并且项目字典中的那些值都将被共享(这可能是不可取的)。 等等,这意味着你有一个类对象的引用,因此你不需要静态的?你可以只做propertyWrapper.getValue() 而不是PropertyWrapper.getValue() 您不使用@propertyWrapper 注释是否有特殊原因?但我认为你对静态的看法是正确的。但是,我相信还有一个问题我们可能需要解决。我们现在可以很好地包装我们的字典项目,但是当我们设置一个项目时,它只会在作为 propertyWrapper 一部分的字典中更新,而不是 foo 本身,这使得我们的更新基本上没有用,因为它们没有反映在“父dict"(如果有道理的话)。

以上是关于在 Swift 属性包装器中公开字典的主要内容,如果未能解决你的问题,请参考以下文章

Swift 属性包装器

Swift 属性包装器

Swift | 属性包装器

FBSDKCoreKit.framework/FBSDKCoreKit:通用包装器中没有匹配的架构

具有内部函数和属性的 Swift 公共协议

Swift @propertyWrapper(属性包装)的使用和本质