2014-06-25 5 views
8

Я создаю массив булевых элементов для хранения состояния разделов в UICollectionView. Это переменная хранится как свойство моего UIViewController:Быстрое необязательное свойство Array является неизменным?

var _weekSelections : Array<Bool>! 

Тогда, в функции, вызываемой loadView(), я построить массив и присвоить значение первого индекса:

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

Значение в индексе 0 остается ложным! Массив построен и имеет несколько элементов, но любое присваивание, которое я делаю для индекса, не влияет на значение, хранящееся в этом индексе, даже если я проверю значение в самой следующей строке кода. Я знаю, что Swift создает копию массива, если я выполняю действие, которое может изменить его длину, но я не думаю, что это случай, когда бы я сделал копию. Единственный способ, которым я могу получить любое значение, чтобы изменить это, если я вручную создать копию следующим образом:

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

я упускаю что-то очевидно, или это могло быть странно ошибка?

+1

Интересно. Я могу воспроизвести это, но если я переведу код на вызов 'init()' из 'loadView()', он будет работать. Все еще пытаюсь понять, что происходит. –

+0

Это происходит со всеми типами массивов, по крайней мере, при хранении в глобальном масштабе и в loadView() или потомке. Я не мог найти что-либо в документации, определяющей поведение разных модификаций для глобальных массивов и локально хранимых массивов, и если то, что вы говорите, является истинным, то это должно быть что-то другое. –

+1

Вот что-то странное: я могу создать минимальный класс Swift на игровой площадке, где ваш код отлично работает. И тогда, если я скажу, что он наследует от NSObject, я могу воспроизвести вашу проблему с ним. Это единственное изменение. У меня есть воспроизведение примерно до 12 строк кода ... Repro: http://pastebin.com/2Xc1qrHQ –

ответ

2

Для того, чтобы мой код на SO, а не Pastebin, вот мое наблюдение. Это выглядит как ошибка или неожиданное поведение при использовании необязательного массива в классе Swift, производном от класса Objective C. Если вы используете обычный Swift класса, это работает, как ожидалось:

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

Однако, если вы черпаете Foo из 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() 

Даже в этом случае, если вы делаете вашу weekSelections инициализацию в Инициализаторе , то он работает:

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

Лично я бы сказал, что это ошибка. Я не вижу ничего в документации, которая бы объясняла разницу в поведении, полученную из NSObject.

Я также не вижу ничего, что говорит о том, что необязательные свойства массива будут неизменными. Это было бы особенно странно, если учесть, что «незыблемые» массивы на самом деле являются изменяемыми в Swift, то есть это:

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

... работает отлично, и в настоящее время документировано как действительным, даже если это кажется немного странным ,

Лично я использую любое обходное решение, которое вы можете, и поднимите ошибку с Apple, чтобы увидеть, какой свет они могут потерять.

0

Не объяснение, но обходной путь. Проблема заключается не в инициализаторе count:repeatedValue, а в том, что массив присваивается необязательной переменной. Из того, что я могу сказать, дополнительные массивы могут использовать только методы доступа, а не методы мутаторов - эффективно они неизменяемы. Временно присваивая _weekSelections необязательной переменной, прежде чем пытаться изменить его содержимое (и назначить обратно _weekSelections, когда это будет сделано). Обратите внимание, что это похоже на создание нового массива (с теми же элементами) при назначении, поэтому могут возникнуть проблемы с памятью, если учесть, что массив очень большой. Конечно, просто использование необязательной переменной в первую очередь будет работать.

Что касается того, почему дополнительные массивы не изменяются, это может быть ошибка, или может быть какая-то эзотерическая причина для этого. Я не понимаю. У кого-нибудь еще есть правдоподобная теория?

+0

Информативно, что это проблема с необязательными переменными, но обходной путь, описанный вами, является тем, который я уже включил в вопрос. Что касается использования необязательной переменной, я мог бы это сделать, но тогда мне пришлось бы инициализировать ее как статически, так и во время инициализации объекта, и я не знаю, насколько она будет большой, пока я не вычислил _weekCount с загруженными данными. Я предпочитаю ждать и использовать счетчик: repeatValue: initializer. –

+0

@EricGratta: измените тему вопроса, указав, что вы понимаете, что проблема ** не является ** с инициализатором. Вы определенно произносите это впечатление. –

+0

Я не знал, что это не проблема, пока только сейчас! –

Смежные вопросы