Swift:通过引用传递数组?

问题描述 投票:0回答:10

我想通过引用将我的 Swift

Array
account.chats
传递给
chatsViewController.chats
(这样当我向
account.chats
添加聊天时,
chatsViewController.chats
仍然指向
account.chats
)。也就是说,我不希望 Swift 在
account.chats
的长度发生变化时分离两个数组。

arrays swift pass-by-reference
10个回答
159
投票

对于函数参数运算符,我们使用:

let
(这是默认操作符,所以我们可以省略let)来使参数常量(这意味着我们甚至无法修改本地副本);

var
使其可变(我们可以在本地修改它,但不会影响已传递给函数的外部变量);和

inout
使其成为输入输出参数。 In-out 实际上意味着通过引用而不是值传递变量。它不仅需要通过引用接受值,还需要通过引用传递它,所以用
&
-
foo(&myVar)
而不是仅仅
foo(myVar)

来传递它

所以这样做:

var arr = [1, 2, 3]

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

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

确切地说,它不仅仅是一个引用,而是外部变量的真正别名,因此您可以对任何变量类型执行这样的技巧,例如使用整数(您可以为其分配新值),尽管它可能不是这是一个很好的实践,像这样修改原始数据类型可能会令人困惑。


88
投票
Swift 中的结构体是按值传递的,但您可以使用

inout

 修饰符来修改数组(请参阅下面的答案)。类通过引用传递。 Swift 中的 
Array
Dictionary
 是作为结构体实现的。 


30
投票
自己定义一个

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
BoxedArray
 的分配将通过引用进行,它是一个类,因此通过 
Array
 接口对存储属性的更改将对所有引用可见。 


19
投票
对于 Swift 版本 3-4 (XCode 8-9),请使用

var arr = [1, 2, 3] func addItem(_ localArr: inout [Int]) { localArr.append(4) } addItem(&arr) print(arr)
    

3
投票
类似的东西

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

???


3
投票
另一种选择是让数组的使用者根据需要向所有者询问。例如,类似以下内容:

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 类中随意修改数组。请注意,如果您还想从视图控制器类修改数组,这对您没有帮助。


1
投票
使用

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]
    

1
投票
使用

NSMutableArray

NSArray
,它们是类

这样你就不需要实现任何包装器并且可以使用桥接中的构建

open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration
    

0
投票
将帐户对象而不是聊天传递给 chatsViewController


-1
投票
根据 GoZoner 的

BoxedArray

 答案,我创建了下面对我有用的课程。  我喜欢将数组作为引用自由传递(就像我使用的其他语言一样)。

class MArray<T> : MutableCollection { var array : Array<T> = Array() var count: Int { return array.count } // getter (without, index func below will be called repeatedly to determine) func add(_ value: T) { array.append(value) } // MutableCollection requires: subscript (index: Int) -> T { get { return array[index] } set(value) { array[index] = value } } var startIndex: Int { return 0 } var endIndex: Int { return array.count } func index(after i: Int) -> Int { return i+1 } }
    
© www.soinside.com 2019 - 2024. All rights reserved.