Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/apache-kafka/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 5.1@PropertyRapper-&x27;自我';在初始化所有存储的属性之前在属性访问中使用_Swift_Swiftui_Swift5.1 - Fatal编程技术网

Swift 5.1@PropertyRapper-&x27;自我';在初始化所有存储的属性之前在属性访问中使用

Swift 5.1@PropertyRapper-&x27;自我';在初始化所有存储的属性之前在属性访问中使用,swift,swiftui,swift5.1,Swift,Swiftui,Swift5.1,我试图使用Swift 5.1属性包装器,但每次我认为我有一个很酷的用例,我最终遇到了一个问题,我不能在视图模型的初始值设定项中使用它们 举一个非常简单的例子 类无问题{ var foo=“ABC” 让大写:字符串 init(依赖项:AppDependencies){ self.upperCased=foo.upperCased() } } @propertyWrapper 结构盒{ 私有变量框:值 init(wrappedValue:Value){ box=wrappedValue } var

我试图使用Swift 5.1属性包装器,但每次我认为我有一个很酷的用例,我最终遇到了一个问题,我不能在视图模型的初始值设定项中使用它们

举一个非常简单的例子

类无问题{
var foo=“ABC”
让大写:字符串
init(依赖项:AppDependencies){
self.upperCased=foo.upperCased()
}
}
@propertyWrapper
结构盒{
私有变量框:值
init(wrappedValue:Value){
box=wrappedValue
}
var wrappedValue:Value{
获取{box}
设置{box=newValue}
}
}
OhNoes类{
@框var foo=“ABC”
让大写:字符串
init(依赖项:AppDependencies){
self.upperCased=foo.upperCased()
}
}
NoProblem
中,一切正常。但是在
OhNoes
中,我得到了这个错误:
在初始化所有存储的属性之前,在属性访问“foo”中使用了“self”

当然,这是一个极其简化的示例,但在为可观察属性执行
@Property
包装时,或者像in这样的
@Injected
包装时,我会遇到同样的问题

不幸的是,让它成为一个lay属性也不会起作用:
带有包装器的属性'foo'也不能是懒惰的


这在SwiftUI中也是一个相当大的问题,请参见以下示例:

类应用商店:observeObject{
让foo=“foo”
}
结构ContentView:View{
@EnvironmentObject私有变量存储:AppStore
私有let foo:String
init(){
foo=store.foo//错误:在初始化所有存储属性之前使用了“self”
}
var body:一些观点{
文本(“你好,世界”)
}
}
编辑: 实际上,更好的解决方法是直接使用
\u foo.wrappedValue.uppercased()
而不是
foo.uppercased()

这也解决了双重初始化的另一个问题

深入思考这一点,这绝对是预期的行为

如果我理解正确的话,在OhNoes中,foo只是以下的缩写:

var foo: String {
  get {
    return self._foo.wrappedValue
  }
  set {
    self._foo.wrappedValue = newValue
  }
}
所以这是不可能以任何其他方式起作用的


我面临着与您相同的问题,我实际上认为这是某种错误/不必要的行为

无论如何,我最好的约会方式是:

@propertyWrapper
结构盒{
私有变量框:值
init(wrappedValue:Value){
box=wrappedValue
}
var wrappedValue:Value{
获取{box}
设置{box=newValue}
}
}
OhNoes类{
@框变量foo:String
让大写:字符串
init(){
let box=box(包装价值:“ABC”)
_foo=box
self.upperCased=box.wrappedValue.upperCased()
}
}
这很好(我的意思是,它没有副作用,但很难看)

这个解决方案的问题是,如果属性包装器有一个空的初始值设定项
init()
,或者如果wrappedValue是
可选的
,那么它实际上不起作用(没有副作用)

例如,如果您尝试使用下面的代码,您将意识到该框初始化了两次:一次在成员变量的定义中,一次在OhNoes的init中,并将替换前者


@propertyWrapper
struct Box<Value> {
  private var box: Value?

  init(wrappedValue: Value?) { // Actually called twice in this case
    box = wrappedValue 
  }

  var wrappedValue: Value? {
    get { box }
    set { box = newValue }
  }
}

class OhNoes {
  @Box var foo : String?
  let upperCased: String?

  init() {
    let box = Box(wrappedValue: "ABC")
    _foo = box
    self.upperCased = box.wrappedValue?.uppercased()
  }
}

@房地产经纪人
结构盒{
私有变量框:值?
init(wrappedValue:Value?{//在本例中实际调用了两次
box=wrappedValue
}
var wrappedValue:值{
获取{box}
设置{box=newValue}
}
}
OhNoes类{
@框变量foo:字符串?
让大写:字符串?
init(){
let box=box(包装价值:“ABC”)
_foo=box
self.upperCased=box.wrappedValue?.upperCased()
}
}
我认为这绝对是我们不应该有的(或者至少我们应该能够选择退出这种行为)。不管怎样,我认为这与他们在

当属性包装类型具有无参数init()时,属性 将通过init()隐式初始化使用该包装类型的


PS:你找到其他方法了吗?

最无摩擦的解决方法是使
大写
a
var
而不是
let
。好的,这可能不可取,但至少意味着您可以保留所有代码并立即使用生成的OhNoes实例:

struct AppDependencies {}
@propertyWrapper struct Box<T> {
    private var boxed: T
    init(wrappedValue: T) {
        boxed = wrappedValue
    }
    var wrappedValue: T {
        get { boxed }
        set { boxed = newValue }
    }
}
class OhNoes {
    @Box var foo = "abc"
    var upperCased: String = "" // this is the only real change
    init(dependencies: AppDependencies) {
        self.upperCased = foo.uppercased()
    }
}
struct-AppDependencies{}
@PropertyRapper结构框{
已装箱的专用变量:T
init(wrappedValue:T){
装箱=包装价值
}
var wrappedValue:T{
得到{装箱}
集合{boxed=newValue}
}
}
OhNoes类{
@框var foo=“abc”
var upperCased:String=”“//这是唯一真正的更改
init(依赖项:AppDependencies){
self.upperCased=foo.upperCased()
}
}

如果你真的不喜欢,那么直接参考另一个答案所建议的
\u foo.wrappedValue

在初始化
大写字母之前,你试图访问
self.foo
。这与属性包装器无关。@ClausJørgensen好吧,正如您在
NoProblem
示例中所看到的,当您不使用属性包装器时,同样的方法也可以正常工作。@MumtazHussain这是不可能的。当然,我可以将
upperCased
设置为lazy变量,但它会抱怨
lazy属性必须有一个初始值设定项。这在现实世界的例子中并不总是一个选项。“你的整个方法就是这里的错误所在”谢谢你。同样,这是一个极其简化的示例,仅用于显示编译器错误。为什么它在使用属性包装器时会抱怨,而在不使用属性包装器时却没有完成呢?这就是问题所在。正如我所说,当尝试对可观察属性或注入属性或其他任何内容使用属性包装器时,也会出现同样的问题。添加了两个示例。不,事实上,这在SwiftUI中也是一个真正的问题,请参见我编辑的问题f