Передать анонимный массив как параметр в Swift - PullRequest
0 голосов
/ 03 декабря 2018

В моем приложении есть простой класс:

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

Foo1 никогда не равен нулю, а Foo2 является необязательным, поэтому он может быть равен нулю.

Вместо инициализации, подобной приведенной ниже, я бы предпочел иметь свойство списка Foos: [Bar], которое может содержать 1 или 2 элемента.

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

В C # Iнаписал бы что-то вроде 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 #?

Ответы [ 2 ]

0 голосов
/ 03 декабря 2018

Самое сложное требование, которое также не удовлетворяется принятым ответом :

Вместо инициализации, подобной приведенной ниже, я бы предпочел иметьсвойство списка Foos: [Bar], которое может содержать 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 не создан.

0 голосов
/ 03 декабря 2018

Попробуйте этот код

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

...