Storing array references in fast

I want to pass an array to an object and keep a reference to this array. I want to be able to modify this array inside this object and make sure that it changes everywhere.

Here is what I am trying to execute (how the code does not work)

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 

My data is still

A) An array (by default) is passed in a weird way. This is the link until you change the length of the array. As soon as you change the length, it will be copied and changed. As a result, if I add or remove anything from it in the object, it will not be displayed outside

B) I can use inout for function parameter. This will allow me to change it inside this function. However, as soon as I try to assign it to some member of the object, I am again struck by A)

C) I can wrap an array in some container class. This is probably the cleanest way. However, I serialize / deserialize these objects, and I would prefer not to put them in a Container (because I have to work around some things to serialize and deserialize and send them to the server).

Is there anything else? Am I missing any Swift construct that allows me to do this?

+6
source share
4 answers

For this you will have to use NSArray or NSMutableArray, because Swift Arrays are value types, so any assignment will make a copy.

+4
source

You can use Swift (very unconvincing) UnsafeMutablePointer .

Since (from your post) references to behavior in arrays cannot be really reliable, instead, save the UnsafeMutablePointer companion for the internal array of class foo , as well as any "external" arrays that you want attached to foo , in the sense that they are both are pointers to the same address in memory.

 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) 

Pointers can be dangerous, though (hence the name of the fit type), and, again, very careless. Anyway...

 /* 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 

Now, what happens when either a or foo goes out of scope, will it violate a variable that is not out of scope, or will Swift contain some smart reference counting that implements a memory address is still in use? I have not researched this, but I am not shy about doing it.

+1
source

Of the fast programming language ,

Structures are always copied when they are passed around in your code, and do not use reference counting.

If you look at the contents of an array variable, you will see that append really works:

  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)")

produces

  self.foo: [1, 2, 3, 4, 5]
 a: [1, 2, 3, 4]

You took a copy , not a link to .

0
source

a is declared a constant, therefore, cannot be changed. If you plan to change the contents of a, declare it as a variable. i.e.,

 var a = [1,2,3,4] 
0
source

All Articles