Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift optional Array property is immutable?

I am constructing an array of booleans to store the state of the sections in a UICollectionView. It is a variable stored as a property of my UIViewController:

var _weekSelections : Array<Bool>!

Then, in a function called by loadView(), I construct the array and assign a value to the first index:

_weekSelections = Array<Bool>(count:_weekCount, repeatedValue:false)
_weekSelections[0] = true

The value at index 0 remains false! The array is constructed, and has multiple elements, but any assignment that I make to an index does not affect the value stored at that index, even if I check the value on the very next line of code. I know that Swift makes a copy of an array if I perform an action that may change its length, but I don't think this is a case where a copy would me made. The only way I can get any value to change is if I manually create a copy as follows:

var copy = _weekSelections
copy[0] = true
_weekSelections = copy

Am I missing something obvious or could this be a strange bug?

like image 684
Eric Gratta Avatar asked Jun 25 '14 14:06

Eric Gratta


People also ask

Are arrays immutable in Swift?

If you assign an array, a set, or a dictionary to a constant, that collection is immutable, and its size and contents can't be changed.

Which property that used to check an array has items in Swift?

To check if an element is in an array in Swift, use the Array. contains() function.

What is difference between array and set in Swift?

Difference between an Array and Set in Swift Array is faster than set in terms of initialization. Set is slower than an array in terms of initialization because it uses a hash process. The array allows storing duplicate elements in it. Set doesn't allow you to store duplicate elements in it.

What is the datatype of array in Swift?

It is important to note that, while creating an empty array, we must specify the data type inside the square bracket [] followed by an initializer syntax () . Here, [Int]() specifies that the empty array can only store integer data elements. Note: In Swift, we can create arrays of any data type like Int , String , etc.


1 Answers

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 Foundation

class 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" array
let 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.

like image 130
Matt Gibson Avatar answered Sep 18 '22 06:09

Matt Gibson