2014-06-25 5 views
8

Ich konstruiere ein Array von Booleans, um den Zustand der Abschnitte in einer UICollectionView zu speichern. Es ist eine Variable als eine Eigenschaft meiner UIViewController gespeichert:Swift optionale Array-Eigenschaft ist unveränderlich?

var _weekSelections : Array<Bool>! 

Dann wird in Abhängigkeit von Loadview genannt(), I das Array konstruieren und einen Wert an den ersten Index zuzuordnen:

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

Der Wert am Index 0 bleibt falsch! Das Array ist aufgebaut und hat mehrere Elemente, aber jede Zuweisung, die ich an einen Index mache, hat keine Auswirkungen auf den Wert, der in diesem Index gespeichert ist, auch wenn ich den Wert in der nächsten Codezeile überprüfe. Ich weiß, dass Swift eine Kopie eines Arrays erstellt, wenn ich eine Aktion ausführe, die seine Länge ändern kann, aber ich denke nicht, dass dies ein Fall ist, in dem eine Kopie erstellt würde. Der einzige Weg, ich jeden Wert bekommen kann, ist, zu ändern, wenn ich eine Kopie manuell erstellen wie folgt:

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

Bin ich etwas offensichtlich fehle oder könnte dies ein seltsamer Fehler sein?

+1

Interessant. Ich kann das reproduzieren, aber wenn ich den Code zu einem 'init()' Aufruf von 'loadView()' verschiebe, funktioniert es. Ich versuche immer noch herauszufinden, was vor sich geht. –

+0

Es passiert mit allen Arten von Arrays, zumindest wenn global gespeichert und in loadView() oder einem Nachkommen. Ich konnte nichts in der Dokumentation finden, das unterschiedliches Änderungsverhalten für global vs. lokal gespeicherte Arrays angibt, und wenn das, was Sie sagen, wahr ist, dann muss es etwas anderes sein. –

+1

Hier ist etwas seltsam: Ich kann eine minimale Swift-Klasse auf einem Spielplatz machen, wo dein Code gut funktioniert. Und wenn ich sage, dass er von NSObject erbt, kann ich dein Problem damit reproduzieren. Das ist die einzige Veränderung. Ich habe eine Reproduktion bis zu etwa 12 Zeilen Code ... Repro: http://pastebin.com/2Xc1qrHQ –

Antwort

2

Um meinen Code auf SO statt Pastebin zu haben, hier ist meine Beobachtung. Das sieht wie eine Art Bug oder unerwartetes Verhalten aus, wenn ein optionales Array in einer Swift-Klasse verwendet wird, die von einer Objective C-Klasse abgeleitet ist. Wenn Sie eine einfache Swift-Klasse verwenden, funktioniert das wie erwartet:

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

Wenn Sie jedoch Foo von NSObject ableiten:

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

Auch in diesem Fall, wenn Sie Ihre weekSelections Initialisierung in einem initialiser , dann funktioniert es:

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

Persönlich würde ich sagen, dass dies ein Fehler ist. Ich kann nichts in irgendeiner Dokumentation sehen, die den Unterschied im Verhalten erklärt, wenn es von NSObject abgeleitet wird.

Ich kann auch nichts sehen, das sagt, dass optionale Array-Eigenschaften unveränderlich sein würden. Dies wäre besonders seltsam, wenn man bedenkt, dass „unveränderlich“ Arrays in Swift tatsächlich wandelbar ist, das heißt das:

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

... funktioniert gut und wird zur Zeit dokumentiert als gültig, auch wenn es ein wenig seltsam scheint .

Persönlich würde ich jede mögliche Problemumgehung verwenden und einen Fehler mit Apple auslösen, um zu sehen, welches Licht sie vergießen können.

0

Keine Erklärung, aber ein Workaround. Das Problem tritt nicht mit dem Initialisierer count:repeatedValue auf, sondern mit dem Array, das einer optionalen Variablen zugewiesen wird. Von dem, was ich sagen kann, können optionale Arrays nur Accessor-Methoden und keine Mutator-Methoden verwenden - effektiv sind sie unveränderlich. Vorübergehend wirdeiner nicht-optionalen Variablen zugewiesen, bevor versucht wird, den Inhalt zu ändern (und zurück zuweisen, wenn das erledigt ist). Bitte beachten Sie, dass dies bei Zuweisungen ein neues Array (mit den gleichen Elementen) zu erstellen scheint, so dass Speicherprobleme auftreten können, wenn das Array sehr groß ist. Natürlich funktioniert auch die einfache Verwendung einer nicht-optionalen Variable an erster Stelle.

Warum optionale Arrays sind nicht veränderbar, das kann ein Fehler sein oder es gibt vielleicht einen esoterischen Grund dafür Ich bin nicht ergründen. Hat noch jemand eine plausibel klingende Theorie?

+0

Es ist informativ, dass dies ein Problem mit optionalen Variablen ist, aber die von Ihnen beschriebene Problemumgehung ist die, die ich bereits in der Frage eingeschlossen habe. Wie bei der Verwendung einer nicht-optionalen Variable, könnte ich das tun, aber dann wäre ich gezwungen, es entweder statisch oder während der Objektinitialisierung zu initialisieren, und ich weiß nicht, wie groß es sein wird, bis ich _weekCount mit geladenen Daten berechnen werde. Ich bevorzuge es zu warten und die Anzahl zu verwenden: repeatedValue: Initialisierer. –

+0

@EricGratta: Dann bearbeiten Sie den Betreff der Frage, um anzuzeigen, dass Sie verstehen, dass das Problem ** nicht mit dem Initialisierer ** zusammenhängt. Du gibst definitiv diesen Eindruck. –

+0

Ich wusste nicht, dass es bis jetzt kein Problem war! –