web-dev-qa-db-ja.com

Swift:配列を参照渡ししますか?

Swift Arrayaccount.chatsを参照によりchatsViewController.chatsに渡したい(したがって、account.chatsにチャットを追加しても、chatsViewController.chatsはまだaccount.chatsを指している)。つまり、account.chatsの長さが変更されたときに、Swiftで2つの配列を分離したくないのです。

110
ma11hew28

Swiftの構造体は値で渡されますが、inout修飾子を使用して配列を変更できます(以下の回答を参照)。クラスは参照渡しされます。 SwiftのArrayおよびDictionaryは、構造体として実装されます。

60
Kaan Dedeoglu

関数パラメーター演算子には、次を使用します。

let(デフォルトの演算子なので、let)パラメータを定数にする(ローカルコピーでも変更できないことを意味します)。

var変数にする(ローカルで変更できますが、関数に渡された外部変数には影響しません) ;そして

inoutin-outパラメーターにします。インアウトとは、実際には値ではなく参照によって変数を渡すことを意味します。また、参照による値の受け入れだけでなく、参照による値の受け渡しも必要なので、-foo(&myVar)だけでなく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]

正確には、それは単なる参照ではなく、外部変数の実際のエイリアスであるため、整数などの任意の変数タイプでこのようなトリックを行うことができます(新しい値を割り当てることができます)良い習慣であり、このようなプリミティブデータ型を変更するのは混乱するかもしれません。

128
Gene Karasev

Arrayインターフェイスを実装するBoxedArray<T>を自分で定義しますが、すべての機能を保存されたプロパティに委任します。など

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

  // ...

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

BoxedArrayを使用する任意の場所でArrayを使用します。 BoxedArrayの割り当ては参照によるものであり、クラスであるため、Arrayインターフェイスを介して格納されたプロパティに加えられた変更は、すべての参照に表示されます。

21
GoZoner

Swiftバージョン3〜4(XCode 8〜9)の場合は、

var arr = [1, 2, 3]

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

addItem(&arr)
print(arr)
16
user6798251

何かのようなもの

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

???

3

もう1つのオプションは、必要に応じてアレイのコンシューマーに所有者に依頼することです。たとえば、次の行に沿ったもの:

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クラス内で好きなだけ配列を変更できます。 View Controllerクラスから配列も変更する場合、これは役に立ちません。

2
elRobbo

inoutを使用することは1つの解決策ですが、配列は値型であるため、私にとってはあまり気になりません。私は個人的に、変異したコピーを返すことを好みます。

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]
0
ToddH

NSMutableArrayまたはNSArrayを使用します。これらはクラスです

このように、ラッパーを実装する必要はなく、ブリッジングでビルドを使用できます

open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration
0
Peter Lapisu