Swift Struct with Lazy,私有属性符合Protocol

Aar*_*man 11 struct protocols lazy-evaluation swift

首先,我有一个协议,只定义了一些readonly属性,例如:

protocol Example {
  var var1:String { get }
  var varArray:[String] { get }
}
Run Code Online (Sandbox Code Playgroud)

然后我想创建一个符合该协议的结构.我遇到的问题是,我有两个相互矛盾的要求:

  1. 属性需要延迟生成.
  2. 属性是相关的,需要一起生成.

我似乎找不到办法做到这一点.我最接近的是这样的:

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
  }
}
Run Code Online (Sandbox Code Playgroud)

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

有谁知道我可以实现目标的方式?从技术上讲,data变量是可变的,但永远不会改变.我不能使用let,lazy所以我无法指定一旦生成后该值永远不会改变.我需要生成值,因为struct是在主线程上创建的,但是值将由后一个进程完全在后台线程上生成.

更新

因此我向我指出,我可以mutating在协议和结构中制作getter .这是有效的,除了我现在有一个问题,我不能在任何其他结构(我是)中使用此结构.所以最后,我把问题推到另一个结构中,我不想让它变成可变的.

例如:

struct Container {
  let astruct:AStruct
  let callback:() -> ()
}
Run Code Online (Sandbox Code Playgroud)

我无法访问AStructfrom中的变量Container因为Container是不可变的并且成员变量AStruct是变异的.试图访问它们给了我之前提到的相同的错误消息.

更改要使用的容器var而不是let产生相同的错误:

struct Container {
  var astruct:AStruct
  let callback:() -> ()
}
Run Code Online (Sandbox Code Playgroud)

如果我在处理类中设置一个接收Container到进程的函数:

func processContainer(cont:Container){
  self.doSomething(cont.astruct.var1)
}
Run Code Online (Sandbox Code Playgroud)

我得到同样的错误:Immutable value of type 'AStruct' only has mutating members names 'sql'.

Air*_*ity 18

因为访问惰性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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,你现在会发现Swift抱怨你不符合Example,因为它get var1没有被标记为变异.所以你必须改变它以匹配:

protocol Example {
    var var1:String { mutating get }
    var varArray:[String] { mutating get }
}
Run Code Online (Sandbox Code Playgroud)