Swift optional Array property is immutable? Swift optional Array property is immutable? arrays arrays

Swift optional Array property is immutable?


For the sake of having my code on SO rather than Pastebin, here's my observation. This looks like some kind of bug or unexpected behaviour when using an optional array in a Swift class derived from an Objective C class. If you use a plain Swift class, this works as expected:

class Foo {    var weekSelections: Array<Bool>!    func test() {        weekSelections = Array<Bool>(count: 10, repeatedValue: false)        weekSelections[0] = true;        println(weekSelections[0]) // Prints "true"    }}var foo = Foo()foo.test()

However, if you derive Foo from NSObject:

import Foundationclass Foo : NSObject { // This derivation is the only difference from the code above    var weekSelections: Array<Bool>!    func test() {        weekSelections = Array<Bool>(count: 10, repeatedValue: false)        weekSelections[0] = true;        println(weekSelections[0]) // Prints "false"    }}var foo = Foo()foo.test()

Even in this case, if you do your weekSelections initialisation in an initialiser, then it works:

class Foo : NSObject {    var weekSelections: Array<Bool>!    init() {        weekSelections = Array<Bool>(count: 10, repeatedValue: false)        weekSelections[0] = true;        println(weekSelections[0]) // Prints "true"    }}var foo = Foo()

Personally, I'd say that this is a bug. I can't see anything in any documentation that would explain the difference in behaviour when derived from NSObject.

I also can't see anything that says that optional array properties would be immutable. This would be especially strange when you consider that "immutable" arrays are actually mutable in Swift, i.e. this:

// Use "let" to declare an "immutable" arraylet weekSelections = Array<Bool>(count: 10, repeatedValue: false)weekSelections[0] = true;println(weekSelections[0]); // Prints "true"; arrays are never really "immutable" in Swift

...works fine, and is currently documented as being valid, even if it seems a bit odd.

Personally, I'd use whatever workaround you can and raise a bug with Apple, to see what light they can shed.


Not an explanation, but a workaround. The issue isn't with the count:repeatedValue initializer, but rather with the array being assigned to an optional variable. From what I can tell optional arrays can only use accessor methods and not mutator methods--effectively they're immutable. Temporarily assigning _weekSelections to a non-optional variable before attempting to change its contents (and assigning back to _weekSelections when done) will work. Please note that this seems to create a new array (with the same elements) on assignments, so there may be memory issues to consider if the array is very big. Of course, simply using a non-optional variable in the first place will also work.

As for why optional arrays aren't mutable, that may be a bug or there may be some esoteric reason for it I'm not fathoming. Anyone else have a plausible-sounding theory?