Swift: передать массив по ссылке?
Я хочу передать мой Swift Arrayaccount.chats to chatsViewController.chats по ссылке (так что когда я добавляю чат в account.chats,chatsViewController.chats указан account.chats). Т. е., я не хочу, чтобы Swift разделял два массива, когда длина account.chats изменения.
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. Назначение aBoxedArrayбудет по ссылке, это класс, и, таким образом, изменения в сохраненном свойстве, через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