Swift: передать массив по ссылке?



Я хочу передать мой Swift Arrayaccount.chats to chatsViewController.chats по ссылке (так что когда я добавляю чат в account.chats,chatsViewController.chats указан account.chats). Т. е., я не хочу, чтобы Swift разделял два массива, когда длина account.chats изменения.

745   8  

8 ответов:

структуры в Swift передаются по значению, но вы можете использовать inout модификатор для изменения массива (см. ответы ниже). Классы передаются по ссылке. Array и Dictionary в Swift реализованы в виде структур.

для оператора параметра функции мы используем:

пусть (оператор это по умолчанию, поэтому мы можем опустить пусть), чтобы параметр константа (это означает, что мы не можем изменить даже локальную копию);

ВАР чтобы сделать его переменным (мы можем изменить его локально, но это не повлияет на внешнюю переменную, которая была передана функции); и

inout чтобы сделать его входным параметром. In-out означает фактически передачу переменной ссылка, а не по значению. И это требует не только принять значение по ссылке, но и передать его по ссылке, поэтому передайте его с & - просто foo(myVar)

Так сделайте это так:

var arr = [1, 2, 3]

func addItem(inout localArr: [Int]) {
    localArr.append(4)
}

addItem(&arr)    
println(arr) // it will print [1, 2, 3, 4]

если быть точным, это не просто ссылка, а реальный псевдоним для внешней переменной, поэтому вы можете сделать такой трюк с любым типом переменной, например с целым числом (вы можете присвоить ему новое значение), хотя это может быть не очень хорошая практика и это может быть запутанным изменить примитивные типы данных, как это.

задайте себе BoxedArray<T> что реализует Array интерфейс, но делегирует все функции хранимого имущества. Как таковой

class BoxedArray<T> : MutableCollection, Reflectable, ... {
  var array : Array<T>

  // ...

  subscript (index: Int) -> T { 
    get { return array[index] }
    set(newValue) { array[index] = newValue }
  }
}

использовать BoxedArray везде, где вы бы использовали Array. Назначение a BoxedArray будет по ссылке, это класс, и, таким образом, изменения в сохраненном свойстве, через Array интерфейс, будет виден для всех ссылок.

для версий Swift 3-4 (XCode 8-9) используйте

var arr = [1, 2, 3]

func addItem(_ localArr: inout [Int]) {
    localArr.append(4)
}

addItem(&arr)
print(arr)

что-то вроде

var a : Int[] = []
func test(inout b : Int[]) {
    b += [1,2,3,4,5]
}
test(&a)
println(a)

???

еще один вариант заключается в том, чтобы потребитель массива запрашивал владельца по мере необходимости. Например, что-то вроде:

class Account {
    var chats : [String]!
    var chatsViewController : ChatsViewController!

    func InitViewController() {
        chatsViewController.getChats = { return self.chats }
    }

}

class ChatsViewController {
    var getChats: (() -> ([String]))!

    func doSomethingWithChats() {
        let chats = getChats()
        // use it as needed
    }
}

затем вы можете изменить массив столько, сколько вам нравится внутри класса Account. Обратите внимание, что это не поможет вам, если вы хотите также изменить массив из класса контроллера.

Swift 3 и Xcode 8:

var myArray = [1, 2, 3]

for (index, value) in myArray.enumerated()  {
    // if you don't need the value you could do: for (index, _) in myArray.enumerated()
    myArray[index].append(4)
}

используя inout это одно решение, но оно не кажется мне очень быстрым, так как массивы являются типами значений. Стилистически я лично предпочитаю возвращать мутировавшую копию:

func doSomething(to arr: [Int]) -> [Int] {
    var arr = arr
    arr.append(3) // or likely some more complex operation
    return arr
}

var ids = [1, 2]
ids = doSomething(to: ids)
print(ids) // [1,2,3]

Comments

    Ничего не найдено.