【问题标题】:Can't initialize a struct with a default value无法使用默认值初始化结构
【发布时间】:2015-03-08 04:55:39
【问题描述】:
struct Struct1 {
  let myLet = "my let"
  let myLet2: Bool
  let myLet3: String
}

let s1 = Struct1(myLet2: false, myLet3: "My url123")

错误是:参数myLet 缺少参数。这是为什么?它有一个默认值。

【问题讨论】:

    标签: ios macos swift


    【解决方案1】:

    Swift 5.1

    var 标记的变量在构造函数中是可选的,将使用它们的默认值。示例:

    struct Struct {
      var param1: Int = 0
      let param2: Bool
    }
    
    let s1 = Struct(param2: false)           // param1 = 0, param2 = false
    let s2 = Struct(param1: 1, param2: true) // param1 = 1, param2 = true
    

    对于旧版本的 Swift (:

    默认初始化对于结构来说是全有或全无。要么为所有属性定义默认值,然后得到一个自动生成的初始化器Struct1() 加上一个带有所有属性的初始化器,或者你只得到一个带有所有属性的初始化器,包括任何碰巧具有设置默认值的初始化器。您将不得不实现一个自定义初始化程序。

    struct Struct1 {
        let myLet = "my let"
        let myLet2: Bool
        let myLet3: String
    
        init(myLet2: Bool, myLet3: String) {
            self.myLet2 = myLet2
            self.myLet3 = myLet3
        }
    }
    

    【讨论】:

    • 我不确定我是否理解,如何自动获取 Struct1() 初始化器以及具有所有属性的初始化器?
    • 在 Swift 5.1 中不再是这种情况,在初始化结构时不需要为具有默认值的结构属性提供值 - github.com/apple/swift-evolution/blob/master/proposals/…
    【解决方案2】:

    Swift 5.1:struct 成员初始化行为在 Swift 5.1(Xcode 11 附带)中发生了变化,表现得更加符合您的预期:

    struct Struct1 {
      var myVar = "my var"
      let myLet2: Bool
      let myLet3: String
    }
    
    // Swift 5.1 generates a memberwise init as: 
    // init(myVar: String = "my var", myLet2: Bool, myLet3: String)
    

    所以下面的代码现在可以在 Swift 5.1 中运行:

    let s1 = Struct1(myLet2: false, myLet3: "My url123") 
    let s2 = Struct1(myVar: "var1", myLet2: false, myLet3: "My url123")
    

    更多详情见相关Swift evolution proposal

    【讨论】:

    • 太棒了!这真是太痛苦了,尤其是如果您的结构具有很长的属性列表!
    • 你的例子是错误的。为了让编译器使用默认值合成 init,您必须将这些值声明为 var。否则这些值是不可变的,一旦你用赋值 let myLet = "my let" 初始化它们,你就不能再修改它们了。
    • @superpuccio 我的错误我已经编辑了我的答案,将结构中的默认值从 let 更改为 var - 感谢您指出我的错误。
    • 这是 Swift 5.1 中的绝妙方式。感谢尼克分享它。
    • "你的例子是错误的。为了让编译器用默认值合成 init,你必须将这些值声明为 var。否则这些值是不可变的,一旦你用赋值初始化它们 let myLet = "my let" 你不能再修改它们了。" 这真的很糟糕:(。现在如果你想使用那个快捷语法,你必须在你的结构上有一个可变属性。我希望他们有一些额外的语法所以你可以得到相同的行为,但需要一个 let。
    【解决方案3】:

    在 Swift 4 中

    struct Struct1 {
        let myLet: String?
        let myLet2: Bool
        let myLet3: String 
        init(myLet: String? = nil, myLet2: Bool, myLet3: String) {
            self.myLet = myLet
            self.myLet2 = myLet2
            self.myLet3 = myLet3
        }
    }
    

    【讨论】:

    • 这与 Swift 4 无关。从 Swift 1.0 开始可以在初始化器中声明默认值
    • 为了清楚起见,请备注为该示例编写的 swift 版本
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 2017-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多