我想通过引用传递我的 Swift Array
account.chats
到 chatsViewController.chats
(这样当我向 account.chats
添加一个聊天时,chatsViewController.chats
仍然指向 account.chats
)。也就是说,当 account.chats
的长度发生变化时,我不希望 Swift 将这两个数组分开。
我想通过引用传递我的 Swift Array
account.chats
到 chatsViewController.chats
(这样当我向 account.chats
添加一个聊天时,chatsViewController.chats
仍然指向 account.chats
)。也就是说,当 account.chats
的长度发生变化时,我不希望 Swift 将这两个数组分开。
let
(默认的运算符,因此可以省略let
)将参数设置为常量(这意味着我们甚至不能修改本地副本);var
将其设置为变量(我们可以在本地修改它,但不会影响传递给函数的外部变量);以及inout
将其设置为输入输出参数。 输入输出即实际上通过引用而非值传递变量。 它不仅需要通过引用接受值,还需要通过引用传递值,因此使用&
进行传递 - 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]
确切地说,它不仅仅是一个引用,而是外部变量的真实别名,因此您可以对任何变量类型使用这种技巧,例如整数(可以分配新值),尽管这可能不是一个好习惯并且修改原始数据类型可能会很困惑。
var
不再可用作函数参数属性。 - elquimista在Swift中,结构体是按值传递的,但您可以使用inout
修饰符来修改数组(请参见下面的答案)。类是按引用传递的。在Swift中,Array
和Dictionary
是作为结构体实现的。
NSArray
,因为它和 Swift 数组有微妙的语义差异(例如引用类型),这可能会导致更多的错误。 - eonilinout
会怎样? - Alston定义一个名为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 }
}
}
您可以在任何需要使用Array
的地方使用BoxedArray
。赋值BoxedArray
将通过引用进行,因为它是一个类,因此通过Array
接口对存储属性的更改将对所有引用可见。
String
是Any
的子类型,但如果你import Foundation
,那么String
就成为AnyObject
的子类型。 - GoZoner对于Swift 3-4版本(XCode 8-9),请使用
var arr = [1, 2, 3]
func addItem(_ localArr: inout [Int]) {
localArr.append(4)
}
addItem(&arr)
print(arr)
另一种选择是让数组的使用者根据需要向所有者请求。例如,可以采用以下方式:
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类内部尽情修改数组。请注意,如果您还想从视图控制器类中修改数组,则这并没有帮助到您。
类似以下这样的内容
var a : Int[] = []
func test(inout b : Int[]) {
b += [1,2,3,4,5]
}
test(&a)
println(a)
???
func test(b: inout [Int])
... 或许这是旧语法;我只在2016年开始接触Swift,而这个答案是来自2014年,所以也许当时的情况不同了? - Ray Toal使用 inout
是一种解决方案,但是对我来说并不感觉很符合 Swift 的风格,因为数组是值类型。在样式上,我个人更喜欢返回一个已经改变的副本:
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]
inout
普遍更好,因为它可以节省电池电量。对此,我要说这种解决方案的可读性、不可变性和线程安全性是普遍更好的,而inout只应在那些使用情况需要时作为优化来使用。 - ToddHNSMutableArray
或者NSArray
类,这样你就不需要实现任何包装器并且可以使用内置的桥接。open class NSArray : NSObject, NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration
基于 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
}
}
account
作为全局变量,并将ChatsViewController
的chats
属性定义为:var chats: [Chat] { return account.chats }
。 - ma11hew28var chats:[Chat] {get {return account.chats} set {account.chats = newValue}}
- jk7