0

I have some arrays:

var arrayOne = [String]()
var arrayTwo = [String]()
var arrayThree = [String]()

Then I write a function. I give a number, it returns my one of these arrays:

func get_array(aNumber:Int) -> NSArray {
   var arr = self.arrayOne //default
   if aNumber == 1 {
        arr = self.arrayOne
   } else if aNumber == 2 {
       arr = self.arrayTwo
   } else if aNumber == 3 {
       arr = self.arrayThree
   }
   return arr!
}

Then for instance I do:

var myArray = get_array(2)
myArray.append("hello")
NSLog("myArray: %@", myArray) // Ok, myArray was modified!!

NSLog("arrayTwo: %@", arrayTwo) // **Shit, arrayTwo was not modified!!** I was expecting myArray to be pointing to arrayTwo, so they are the same object

How can do this???

Martin
  • 16,093
  • 1
  • 29
  • 48
jobima
  • 5,790
  • 1
  • 20
  • 18

2 Answers2

0

Swift arrays are value types. It means that

let array2 = array1

makes a copy of array1. So when you access array2 it is not the same array anymore as array1, it is another object with the same content.

This is different from NSArray and NSMutableArray which are a reference type: when you do

let nsarray2 = nsarray1

this time nsarray2 is a reference to nsarray1 and they are actually the same object.

Eric Aya
  • 69,473
  • 35
  • 181
  • 253
  • I understand. But why in the world they changed the behavior?? NSDictionary and NSArray worked like a charm. Are they going to be available for long? Or are they deprecated and I should move to Array and Dictionary? – jobima Jul 13 '15 at 08:18
0

In Swift Arrays are value types so they get copied if you assign, return or pass as parameter.

To make this work as expected you have to make a wrapper (class):

class ArrayWrapper<T> {
    var array: [T]
    init(_ array: [T] = []) {
        self.array = array
    }
}

var arrayOne = ArrayWrapper<String>()
var arrayTwo = ArrayWrapper<String>()
var arrayThree = ArrayWrapper<String>()

func get_array(aNumber:Int) -> ArrayWrapper<String> {
   var arr = self.arrayOne //default
   if aNumber == 1 {
        arr = self.arrayOne
   } else if aNumber == 2 {
       arr = self.arrayTwo
   } else if aNumber == 3 {
       arr = self.arrayThree
   }
   return arr
}

// in case of your function I would suggest to use switch instead:
func getArray(aNumber:Int) -> ArrayWrapper<String> {
   switch aNumber {
   case 1: return self.arrayOne
   case 2: return self.arrayTwo
   case 3: return self.arrayThree
   default: return self.arrayOne
   }
}

// so you modify the Array as following:
var myArray = get_array(2)
myArray.array.append("hello")
Qbyte
  • 12,753
  • 4
  • 41
  • 57