【问题标题】:Pass anonymous array as paramter in Swift在 Swift 中传递匿名数组作为参数
【发布时间】:2018-12-02 23:57:36
【问题描述】:

我的应用程序中有一个简单的类:

class MyClass{
    var Name: String
    var Foo1: Bar
    var Foo2: Bar?
    //var Foos: [Bar]
}

Foo1 永远不会是 nil,Foo2 是可选的,所以它可能是 nil。

我宁愿拥有一个列表属性 Foos: [Bar],而不是像下面这样的 init,它可能包含 1 或 2 个元素。

init(_ Name: String, _ Foo1: Bar, _ Foo2: Bar?){
    self.Name = Name
    self.Foo1 = Foo1
    self.Foo2 = Foo2
}

在 C# 中,我会写类似 MyClass m = new MyClass("m", New List<Bar>{Bar1, Bar2})MyClass m = new MyClass("m", New List<Bar>{Bar1, null}) 的东西。我宁愿将MyClass 中的一个属性作为列表,而不是两个单独的字段,其中一个字段可能为零。

我试过这个初始化器:

init(_ Name: String, _ Foos: [Bar]) {
    self.Name = Name
    self.Foos = Foos
}

但是当我尝试将匿名列表传递给初始化程序时,我收到以下警告:

let m = MyClass("m", [Bar]().append(B1))

不能对不可变值使用变异成员:函数调用返回不可变值

如何将填充的匿名列表传递给 Swift 中的初始化程序,就像我在 C# 中所做的那样?

【问题讨论】:

    标签: swift initialization optional-parameters


    【解决方案1】:

    试试这个代码

    struct Bar { }
    
    class MyClass {
        var name: String
        var foos: [Bar?]
    
        init(name: String, foos: [Bar?]) {
            self.name = name
            self.foos = foos
        }
    }
    
    let bar0 = Bar()
    let bar1: Bar? = nil
    let object = MyClass(name: "String", foos: [bar0, bar1])
    

    希望你明白了。并详细了解它在 Swift 中的工作原理

    【讨论】:

      【解决方案2】:

      最具挑战性的要求,accepted answer 也无法满足:

      我宁愿拥有一个列表属性 Foos: [Bar],而不是像下面这样的 init,它可能包含 1 或 2 个元素。

      处理此问题的一种方法可能是自定义运行时错误。

      enum BarWrapperError: Error {
          case emptyList
      }
      

      要传递列表并检查它是否至少包含一个元素,可以引入另一种类型

      struct BarWrapper {
          init(bars: [Bar]) throws {
              guard bars.count > 0 else {
                  throw BarWrapperError.emptyList
              }
              self.bars = bars
          }
      
          let bars: [Bar]
          var firstBar: Bar {
              return bars[0]
          }
          var otherBars:[Bar] {
              return Array(bars[1 ..< bars.count])
          }
      }
      

      BarWrapper 用柱形列表初始化。如果此列表为空,则会抛出错误。

      您的 MyClass 现在看起来像:

      class MyClass {
          let name: String
          let firstBar: Bar
          let otherBars: [Bar]
      
          init(name: String, barWrapper: BarWrapper) {
              self.name = name
              self.firstBar = barWrapper.firstBar
              self.otherBars = barWrapper.otherBars
          }
      }
      

      如果你关心错误并想继续执行,你可以这样使用

      do {
          let bar0 = Bar()
          let bar1 = Bar()
          let barWrapper = try BarWrapper(bars: [bar0, bar1])
          let object = MyClass(name: "String", barWrapper: barWrapper)
          print(object.otherBars)
      } catch BarWrapperError.emptyList {
          print("empty bar list")
      }
      

      如果您想在列表为空时让应用程序崩溃,您可以将其缩短为

      let bar0 = Bar()
      let bar1 = Bar()
      let barWrapper = try! BarWrapper(bars: [bar0, bar1])
      let object = MyClass(name: "String", barWrapper: barWrapper)
      print(object.otherBars)
      

      通过使用try!

      你也可以这样做

      let bar0 = Bar()
      let bar1 = Bar()
      if let barWrapper = try? BarWrapper(bars: [bar0, bar1]) {
          let object = MyClass(name: "String", barWrapper: barWrapper)
          print(object.otherBars)
      }
      

      如果您不需要错误处理,并且如果未创建 MyClass 实例,您的应用仍可运行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-11-23
        • 2011-05-11
        • 1970-01-01
        • 2012-09-10
        • 1970-01-01
        • 1970-01-01
        • 2010-11-11
        相关资源
        最近更新 更多