0

Any idea why this code is not working?

var apples = [String]()
var oranges = [String]()
var bananas = [String]()

var optionArrays : [String : [String]] = [
    "apple" : apples,
    "orange" : oranges,
    "banana" : bananas
]

optionArrays["apple"]!.append("Macintosh")
optionArrays["apple"]!.count // 1

apples.count // 0 -> Why isn't there already one apple?
apples.append("Golden Delicious")
apples.count // 1

For some reason the optionArrays["apple"] seems to be working, but no the actual apples array. Shouldn't this work?

3
  • You never assigned something to the apples array. You did it for the optionsArrays. Commented Feb 13, 2017 at 7:43
  • @GuyDaher is there anyway to do what I am trying to accomplish? Commented Feb 13, 2017 at 7:48
  • Basically I want to populate a variable array, if that makes any sense. Commented Feb 13, 2017 at 7:49

2 Answers 2

3

Arrays are value types in swift. When you put them into dictionaries:

var optionArrays : [String : [String]] = [
    "apple" : apples,
    "orange" : oranges,
    "banana" : bananas
]

Copies of the actual apples, oranges and bananas arrays are created and put into the dictionary. When you modify the dictionary:

optionArrays["apple"]!.append("Macintosh")

you only modify the copy of apples that is in the dictionary.

A workaround is to assign all the copies of the arrays to the actual arrays whenever the dictionary is modfied:

var optionArrays : [String : [String]] = [
    "apple" : apples,
    "orange" : oranges,
    "banana" : bananas
    ] {
didSet {
    apples = optionArrays["apple"]!
    oranges = optionArrays["orange"]!
    bananas = optionArrays["banana"]!
}
}

Another workaround is to create a reference type wrapper for Array:

class RefArray<T> { // you can consider conforming to ExpressibleByArrayLiteral
    var innerArray = [T]()
}

var apples = RefArray<String>()
var oranges = RefArray<String>()
var bananas = RefArray<String>()

var optionArrays : [String : RefArray<String>] = [
    "apple" : apples,
    "orange" : oranges,
    "banana" : bananas
    ]

optionArrays["apple"]!.innerArray.append("Macintosh")
optionArrays["apple"]!.innerArray.count // 1

apples.innerArray.count
Sign up to request clarification or add additional context in comments.

1 Comment

thank you, your first work around worked great! Using the didSet event is exactly what I needed! Thank you so much, I've been scratching my head all day on this!
0

It like that because Swift array is value type not reference type

var apples = [String]()
var oranges = [String]()
var bananas = [String]()

var optionArrays : [String : [String]] = [
    "apple" : apples,
    "orange" : oranges,
    "banana" : bananas
]

print("Initial values")
print(apples)

[]

print(optionArrays)

["apple": [], "orange": [], "banana": []]

optionArrays["apple"]!.append("Macintosh")
optionArrays["apple"]!.count // 1

print("Values after update optionArrays")
print(apples)

[]

print(optionArrays)

["apple": ["Macintosh"], "orange": [], "banana": []]

You will see here that apples array is not updated just an optionArrays is updated. Because swift's array is not reference typr it is value typr so apples will copied to an optionArrays array, so optionArrays will update separately. and also apples will update separately.

So apples.count will be 0

Now try update apple array values apples.append("Golden Delicious") apples.count // 1

But now optionArrays value remain same as before

print(optionArrays)

["apple": ["Macintosh"], "orange": [], "banana": []] optionArrays["apple"]

print(apples)

["Golden Delicious"]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.