我想将数组传递给对象并存储对此数组的引用。我希望能够在此对象中修改此数组,并确保在其他任何位置修改它。
这是我想要完成的(代码如何工作)
class Foo {
var foo : Array<Int>
init(foo: Array<Int>) {
self.foo = foo
}
func modify() {
foo.append(5)
}
}
var a = [1,2,3,4]
let bar = Foo(a)
bar.modify()
print(a) // My goal is that it will print 1,2,3,4,5
到目前为止我的发现
A)数组(默认情况下)以奇怪的方式传递。在修改数组长度之前,它是一个引用。一旦修改了长度,它就会被复制和修改。因此,如果我在对象中添加或删除任何内容,则无法在外部看到
B)我可以在函数参数上使用inout
。这将允许我在此功能中修改它。但是,只要我尝试将其分配给某个对象成员,我再次被A)
C)我可以在一些Container类中包装一个数组。这可能是最干净的方式。但是,我序列化/反序列化这些对象,我宁愿不把它放在Container中(因为我必须解决一些事情以进行序列化和反序列化并将其发送到服务器)。
还有别的吗?我错过了一些允许我这样做的Swift构造吗?
答案 0 :(得分:4)
你必须为此使用NSArray或NSMutableArray,因为Swift Arrays是值类型,所以任何赋值都会复制。
答案 1 :(得分:2)
你可以使用Swifts(非常不敏感)UnsafeMutablePointer
。
由于(从你的帖子)对数组的行为引用看起来真的不可信,而是保留一个UnsafeMutablePointer
伴侣到类内部数组foo
以及任何“外部”数组你希望绑定到foo
,因为它们都只是指向内存中相同地址的指针。
class Foo {
var foo : [Int]
var pInner: UnsafeMutablePointer<Int>
init(foo: [Int]) {
pInner = UnsafeMutablePointer(foo)
self.foo = Array(UnsafeBufferPointer(start: pInner, count: foo.count))
}
func modify(inout pOuter: UnsafeMutablePointer<Int>) {
foo.append(5) // <-- foo gets new memory adress
pInner = UnsafeMutablePointer(foo)
pOuter = pInner
}
}
var a = [1,2,3,4] // first alloc in memory
var pOuter: UnsafeMutablePointer<Int> = UnsafeMutablePointer(a)
var bar = Foo(foo: a) // 'bar.foo' now at same address as 'a'
print(bar.foo) // [1,2,3,4]
bar.modify(&pOuter) // -> [1,2,3,4,5]
a = Array(UnsafeBufferPointer(start: pOuter, count: bar.foo.count))
/* Same pointer adress, OK! */
print(bar.pInner)
print(pOuter)
/* Naturally same value (same address in memory) */
print(bar.foo)
print(a)
虽然指针可能很危险(因此适合的类型名称),而且非常不敏捷。总之...
/* When you're done: clear pointers. Usually when using
pointers like these you should take care to .destroy
and .dealloc, but here your pointers are just companions
to an Array property (which has a pointer an reference
counter itself), and the latter will take care of the
objects in memory when it goes out of scope. */
bar.pInner = nil
pOuter = nil
现在,当a
或foo
超出范围时会发生什么,它会破坏不在范围之外的变量,还是Swift包含一些实现内存地址的聪明引用计数还在使用?我没有对此进行调查,但可以随意放纵自己。
答案 2 :(得分:0)
来自the Swift Programming Language,
Structures are always copied when they are passed around in your code, and do not use reference counting.
如果检查数组变量的内容,您将看到确实附加有效:
class Foo { var foo : Array init(_ foo: Array) { self.foo = foo } func modify() { foo.append(5) } func printFoo() { print("self.foo: \(foo)") } } let a = [1,2,3,4] let bar = Foo(a) bar.modify() bar.printFoo() print("a: \(a)")
产生
self.foo: [1, 2, 3, 4, 5] a: [1, 2, 3, 4]
您已经 的副本,而不是对的引用。
答案 3 :(得分:0)
a被声明为常量因此无法修改。如果您计划修改a的内容,请将其声明为变量。即,
var a = [1,2,3,4]
答案 4 :(得分:0)
我还没有测试过,但是,因为您使用的是一个类来包装数组,所以我看不出为什么下面的方法不起作用。
class Foo {
var foo : Array<Int>
init(foo: inout Array<Int>) {
self.foo = foo
}
func modify() {
foo.append(5)
}
}
let a = [1,2,3,4]
let bar = Foo(&a)
bar.modify()
print("a: \(a)") // a: [1,2,3,4,5]