Answers:
Swift中的结构按值传递,但是您可以使用inout
修饰符来修改数组(请参见下面的答案)。类通过引用传递。Array
和Dictionary
在Swift中实现为结构。
NSArray
因为NSArray
和Swift数组在语义上有细微的差别(例如引用类型),这可能会导致您遇到更多错误。
inout
与Structs一起使用怎么办?
对于函数参数运算符,我们使用:
let(它是默认运算符,因此我们可以省略let)来使参数恒定(这意味着我们甚至不能修改本地副本);
var使其可变(我们可以在本地对其进行修改,但不会影响已传递给函数的外部变量);和
inout使其成为in-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]
确切地说,它不仅是引用,而且是外部变量的真实别名,因此您可以对任何变量类型(例如,使用整数(可以为其分配新值))进行这种技巧,尽管它可能不是好的做法,这样修改原始数据类型可能会造成混淆。
inout
位置已更改,即func addItem(localArr: inout [Int])
var
对于功能参数属性不再可用。
给自己定义一个 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
接口对存储属性的更改将对所有引用可见。
String
的子类型,Any
那么也存在可憎之处。import Foundation
String
AnyObject
就像是
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年开始的,所以以前可能有所不同吗?
另一种选择是让阵列的使用者根据需要向所有者询问。例如,类似以下内容的东西:
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类中随意修改数组。请注意,如果您还想从视图控制器类中修改数组,那么这对您没有帮助。
使用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]
inout
更好,因为它可以节省电池。我要说的是,此解决方案的可读性,不变性和线程安全性普遍更好,并且inout仅应在用例需要的情况下用作优化。
account
了一个全局变量并定义了as 的chats
属性。ChatsViewController
var chats: [Chat] { return account.chats }