首先,我有一个协议(protocol),仅定义了几个只读属性,例如:

protocol Example {
  var var1:String { get }
  var varArray:[String] { get }
}

然后,我想创建一个符合该协议(protocol)的结构。我遇到的问题是,我有两个相互矛盾的要求:
  • 需要延迟生成属性。
  • 这些属性是相关的,需要一起生成。

  • 我似乎找不到解决办法。我最接近的是这样的:
    struct AStruct : Example {
      private lazy var data:(var1:String, varArray:[String]) = {
        var stringValue:String = ""
        var stringArray:[String] = []
        //Generate data
        return (stringValue, stringArray)
      }()
    
      var var1:String {
        return self.data.var1
      }
    
      var varArray:[String] {
        return self.data.varArray
      }
    }
    

    问题是,我得到了错误:Immutable value of type 'AStruct' only has mutating members named 'data'

    有人知道我可以实现目标的方式吗?从技术上讲,data变量是可变的,但永远不会更改。我不能将letlazy一起使用,因此无法指定该值一旦生成就永远不会更改。我需要生成值,因为该结构是在主线程上创建的,但是这些值将由另一个进程在后台线程上生成。

    更新

    因此,向我指出,我可以在协议(protocol)和结构中都将getters设置为mutating。那行得通,除了我现在有一个问题,就是我不能在其他任何结构中使用这个结构(我是)。因此,最后,我将问题推到了另一个结构中,我不希望该结构是易变的。

    前任:
    struct Container {
      let astruct:AStruct
      let callback:() -> ()
    }
    

    我无法从AStruct访问Container中的变量,因为Container是不可变的,并且AStruct的成员变量正在变异。尝试访问它们会给我与我之前提到的相同的错误消息。

    将容器更改为使用var而不是let会产生相同的错误:
    struct Container {
      var astruct:AStruct
      let callback:() -> ()
    }
    

    如果我在处理类中设置了一个函数,该函数接收一个Container进行处理:
    func processContainer(cont:Container){
      self.doSomething(cont.astruct.var1)
    }
    

    我收到相同的错误:Immutable value of type 'AStruct' only has mutating members names 'sql'

    最佳答案

    由于访问懒惰的data变量会使AStruct发生变化,因此对它的任何访问都必须标记为也使该结构发生变化。所以你需要写:

    struct AStruct : Example {
        // ...
        var var1: String {
            // must declare get explicitly, and make it mutating:
            mutating get {
                // act of looking at data mutates AStruct (by possibly initializing data)
                return self.data.var1
            }
        }
    
        var varArray:[String] {
            mutating get {
                return self.data.varArray
            }
        }
    }
    

    但是,您现在会发现Swift提示您不符合Example,因为它的get var1没有被标记为变异。因此,您必须对其进行更改以匹配:
    protocol Example {
        var var1:String { mutating get }
        var varArray:[String] { mutating get }
    }
    

    10-08 05:25