当前位置: 首页 > 面试题库 >

是什么导致“常量在初始化之前被闭包捕获”错误

游鸣
2023-03-14
问题内容

在下一堂课

class Foo {
   let _defaultValue = "N/A"
   let value: String

   init (dict: NSDictionary) {
       self.value = dict["bar"] as? String! ?? _defaultValue
   }
}

编译器失败并显示以下消息 constant 'self.value' captured by a closure before being initialized

据我所知,没有运算符读取`self.value。该消息似乎有些混乱。

我不小心想到了一种解决方法。我应该说这让我更加困惑:

class Foo {
       let value: String

       init (dict: NSDictionary) {
           let _defaultValue = "N/A"
           self.value = dict["bar"] as? String! ?? _defaultValue
       }
    }

_defaultValue在构造函数中声明和初始化它可以使代码编译。

如果有人可以解释为什么在第一种情况下会发生错误,而在第二种情况下编译器会更快乐,那么这将是一个巨大的帮助。


问题答案:

该错误信息的原因是nil-coalescing运算符定义为

public func ??<T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T

并对第二个参数执行“自动关闭”(以实现短路行为)。所以

self.value = dict["bar"] as? String ?? _defaultValue

由编译器转换为

self.value = dict["bar"] as? String ?? { self._defaultValue }()

编译器在这里抱怨,因为self在完全初始化之前就被捕获了。(错误消息在Swift 2和Swift 3之间略有不同)。

可能的解决方法 您可以先将属性分配给局部变量:

init(dict: NSDictionary){
    let defValue = _defaultValue
    self.value = dict["bar"] as? String! ?? defValue
}

或者,您可以将其设为该类的静态属性:

class Foo {
    static let _defaultValue = "N/A"
    let value: String

    init(dict: NSDictionary) {
        self.value = dict["bar"] as? String ?? Foo._defaultValue
    }
}

或替换??为if语句:

class Foo {
    let _defaultValue = "N/A"
    let value: String

    init (dict: NSDictionary) {
        if let value = dict["bar"] as? String {
            self.value = value
        } else {
            self.value = _defaultValue
        }
    }
}

附录: 相关资源:

  • 在Swift论坛中的初始化程序中,自我自动闭合。
  • SR-944在初始化所有属性的错误报告之前,不能在&&的RHS中使用“自我”。

引用错误报告:

Jordan Rose:这是正确的,因为&&是使用@autoclosure实现的,但是肯定不是最优的。



 类似资料:
  • 问题内容: 好了,那么,从这里开始,这里是我的代码: 因此出现错误,因为我试图在API调用中初始化temp。我知道这不是最可靠的方法,但我正在尝试首先使其起作用。 第一个错误是: 在初始化所有成员之前,闭包捕获了“自我” 在线上 我的第二个错误: 从初始化程序返回而不初始化所有存储的属性 在倒数第二 现在,显然我没有初始化正确。但是,我找不到执行最终目标的正确方法。也许我这样做完全错误? 问题答案

  • *编辑:好的,在修复了try catch错误后,我在< code>catch {..打印时。*,基本上,当我说我想再玩一次时,它会继续游戏,但它也会打印第一个< code>catch,然后在第23行要求输入。 嗨,这是我的第一篇文章,所以如果我在论坛上的代码格式错误,我会编辑它。 现在我正在用java eclipse编写一个游戏,其中cpu生成一个数字,用户必须猜测它。我大部分时间都在使用扫描仪类

  • 我有以下代码: 它从“VM参数”中读取并分配给变量。 由于静态最终变量仅在类加载时初始化,因此如何在有人忘记传递参数的情况下捕获异常。 目前,当我使用“property\u file\u location”变量时,在以下情况下会遇到异常: 若值存在,并且位置错误,则会出现FileNotFound异常 如果未正确初始化(值为null),则抛出NullPointerException 我只需要在初始化

  • 问题内容: 我有以下这段代码: 现在在控制台中,构造函数要在的构造函数之前执行。 我想知道为什么会这样。 问题答案: 这是因为在编译时,编译器会将在声明位置完成的每个初始化都移到类的每个构造函数中。因此,类的构造函数可以有效地编译为: 因此,显然构造函数是在类的语句之前执行的。同样,如果您的类中还有其他构造函数,则初始化将移至所有它们。 让我们看一个简单类的字节码: 编译该类,并执行命令- 。您将

  • 问题内容: 我正在努力理解为什么我在使用Swift的iOS项目中遇到此编译器错误。如果我创建以下类: 我在“初始化前使用了变量’self.c’” 这一行上收到编译器错误。 起初我以为这是因为编译器无法验证该方法是否无法访问,但是后来我尝试将init方法混入一点: 这次的错误是“在初始化之前使用了变量’self.b’”(在同一行上)。这表明编译器 是 能够检查其性能的方法访问,所以据我可以看到应该有

  • 问题内容: 当我尝试在实例初始值设定项块内直接打印x,而在块末尾之前为x赋值时,就会出现问题: 情况1 这给出了编译时错误,指出变量x可能尚未初始化。 情况二 我不是直接打印,而是调用一个函数来打印: 这样可以正确编译并提供输出 两种情况在概念上有什么区别? 问题答案: 在JLS中,第8.3.3节。字段初始化期间的正向引用,它指出在以下情况下存在编译时错误: 有时会限制使用声明之后以文本形式出现的