11 Stimmen

Wie kann ich ein NSArray als globale Konstante verwenden?

Ich verwende einen Satz von Constant.m Dateien, eine pro Ziel, um bestimmte Dinge für jedes Ziel zu definieren. Zum Beispiel:

// Constants.h
extern NSString * const kDatabaseFileName;
//Constants.m
NSString * const kDatabaseFileName = @"target_one.sqlite";

Ich möchte auch ein NSArray für jedes meiner Ziele definieren:

NSArray * const kLabelNames = [[NSArray alloc] initWithObjects:
    @"nameLabel", @"addressLabel", nil];

Aber das ergibt "Fehler: Initialisierungselement ist nicht konstant". Die Verwendung von 'arrayWithObjects` funktioniert auch nicht. Liegt das daran, dass die Strings in meinem Array keine Konstanten sind?

Wie kann ich ein Array als globale Konstante einrichten? Danke!

0 Stimmen

29voto

jlehr Punkte 15365

In Objective-C können Objekte nur im Heap zugewiesen werden, daher gibt es keine Möglichkeit, ein NSArray im statischen Speicher zu erstellen. Allerdings können Sie ein C-Array von Zeigern auf NSString-Konstanten wie folgt erstellen...

NSString * const kLabelNames[] = {
    @"Foo", @"Bar", @"Baz"
};

...und dann kann man Klassenmethoden wie diese schreiben...

+ (NSArray *)labelNames
{
    static NSArray *names;
    if (names == nil) {
        names = [[NSArray alloc] initWithObjects:kLabelNames count:3];
    }
    return names;
}

Editar

Beachten Sie, dass es mit der Einführung neuer Technologien wie ARC, Grand Central Dispatch und der neuen Literal-Syntax für Arrays nun einen einfacheren Weg gibt, etwas Ähnliches zu erreichen. Beachten Sie, dass das folgende Beispiel auch eine größere Thread-Sicherheit bietet, obwohl das ursprüngliche Beispiel eine @synchronized Block oder einen der anderen Mechanismen, um ähnliche Ergebnisse zu erzielen.

+ (NSArray *)labelNames
{
    static NSArray *names;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        names = @[@"Foo", @"Bar", @"Baz"];
    });

    return names;
}

Das obige Beispiel beantwortet die ursprüngliche Frage jedoch nicht vollständig. Wenn ein globales Konstanten-Array wirklich benötigt wird, könnte das vorangegangene Beispiel ähnlich wie die ursprüngliche Antwort umgeschrieben werden, wobei immer noch die Vorteile von GCD genutzt werden:

NSString * const kLabelNames[] = {
    @"Foo", @"Bar", @"Baz"
};

+ (NSArray *)labelNames
{
    static NSArray *names;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        names = [NSArray arrayWithObjects:kLabelNames count:3];
    });

    return names;
}

1 Stimmen

Für den Fall, dass Sie diese Anzahl:3 durch einen dynamischen Wert ersetzen wollen, können Sie die gute alte C-Methode verwenden, um die Größe des Arrays zu ermitteln. count: sizeof(kLabelNames) / sizeof(kLabelNames[0])

7voto

AmitP Punkte 5193

Hier ist ein viel einfacherer Ansatz:

Deklarieren Sie NSString mit durch Komma getrennten Elementen (oder einem beliebigen Begrenzungszeichen)

NSString *const kLabelNames = @"Foo,Bar,Baz";

Konvertieren Sie dann in NSArray, wenn Sie es brauchen:

NSArray *namesArray = [kLabelNames componentsSeparatedByString:@","];

6voto

Wenn Sie einen Satz von Konstanten benötigen, der NS-Typen enthält, sollten Sie sie alle in einem Singleton unterbringen.

Sie könnten eine einzige Header-Datei und mehrere Implementierungsdateien (eine pro Ziel) haben. Solange alle diese Dateien die in der Header-Datei deklarierte Klasse implementieren, sollte alles in Ordnung sein.

5voto

veegee Punkte 349

Verwenden Sie ein Makro:

#define SOME_ARRAY (@[@"blah", @"asdf", @"qwerty"])

2voto

TechZen Punkte 64117

Sie sollten eine Klasse erstellen, die die Konstanten in Klassenmethoden enthält. Dann können Sie die Klasse zu einem beliebigen Ziel hinzufügen und die Methoden aufrufen, um Konstanten in Objekten wie Arrays zu erhalten. Variieren Sie die Klasse oder die Implementierung der Klasse, um die Rückgabe der Konstanten zu ändern.

Wenn Sie sie häufig verwenden, können Sie ein Protokoll erstellen, in dem die Methodennamen definiert sind. Dann tauschen Sie die Klasse, die das Protokoll implementiert, in jedem Ziel aus, so dass derselbe Code je nach Bedarf unterschiedliche Werte zurückgibt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X