2009-06-30 3 views
139

Ich habe eine Klasse Film, von denen jede eine eindeutige ID speichert. In C#, Java usw. kann ich eine statische int currentID definieren und jedes Mal, wenn ich die ID setze, kann ich die currentID erhöhen und die Änderung tritt auf Klassenebene und nicht auf Objektebene auf. Kann dies in Objective C gemacht werden? Ich habe es sehr schwer gefunden, eine Antwort dafür zu finden.Objective C Statische Variablen auf Klassenebene

Antwort

28

Auf .m-Datei können Sie eine Variable als statisch deklarieren:

static ClassName *variableName = nil; 

Dann Sie es auf Ihrem +(void)initialize Methode initialisieren.

Bitte beachten Sie, dass dies eine einfache statische C-Variable ist und nicht im Sinne von Java oder C# statisch ist, sondern ähnliche Ergebnisse liefert.

+3

Bitte korrigieren: '+ (void) initialize' ist die Methode – monkeydom

11

Wie pgb sagte, gibt es keine "Klassenvariablen", nur "Instanzvariablen". Die objektive Methode der Klassenvariablen ist eine statische globale Variable innerhalb der .m-Datei der Klasse. Das "static" stellt sicher, dass die Variable nicht außerhalb dieser Datei verwendet werden kann (d. H. Sie kann nicht extern sein).

16

In .m-Datei, eine Datei globale Variable deklariert:

static int currentID = 1; 

dann in Ihrer init-Routine, refernce dass:

- (id) init 
{ 
    self = [super init]; 
    if (self != nil) { 
     _myID = currentID++; // not thread safe 
    } 
    return self; 
} 

oder wenn es zu einem anderen Zeitpunkt geändert werden muss (B. in Ihrer openConnection-Methode), dann erhöhen Sie es dort. Denken Sie daran, dass es nicht Thread-sicher ist, wie es ist, müssen Sie Synchronisierung (oder noch besser, verwenden Sie eine atomare hinzufügen), wenn es Threading-Probleme sein kann.

155

Problem Beschreibung:

  1. Sie möchten Ihre KlasseA eine ClassB Klassenvariable haben.
  2. Sie verwenden Objective-C als Programmiersprache.
  3. Objective-C unterstützt keine Klassenvariablen wie C++.

Eine Alternative:

Simulieren eine Klassenvariable Verhalten Objective-C mit Funktionen

  1. Declare/Definieren Sie eine statische Variable innerhalb des classA.m so ist es nur zugänglich sein wird, die classA-Methoden (und alles, was Sie in classA.m einfügen).

  2. Überschreiben Sie die NSObject initialize class-Methode, um nur einmal die statische Variable mit einer Instanz von ClassB zu initialisieren.

  3. Sie werden sich wundern, warum sollte ich die NSObject Initialize-Methode überschreiben. Apple Dokumentation über diese Methode hat die Antwort: "Die Laufzeit sendet initialisieren zu jeder Klasse in einem Programm genau ein Mal kurz bevor die Klasse oder jede Klasse, die von ihr erbt, wird ihre erste Nachricht aus dem Programm gesendet. (So die Methode darf niemals aufgerufen werden, wenn die Klasse nicht verwendet wird.) ".

  4. Fühlen Sie sich frei, die statische Variable innerhalb einer ClassA-Klasse/Instanz-Methode zu verwenden.

Codebeispiel:

Datei: classA.m

static ClassB *classVariableName = nil; 

@implementation ClassA 

... 

+(void) initialize 
{ 
    if (! classVariableName) 
     classVariableName = [[ClassB alloc] init]; 
} 

+(void) classMethodName 
{ 
    [classVariableName doSomething]; 
} 

-(void) instanceMethodName 
{ 
    [classVariableName doSomething]; 
} 

... 

@end 

Referenzen:

  1. Class variables explained comparing Objective-C and C++ approaches
+3

Können Sie eine statische Variable vom Typ ClassA in classA.m haben? – goatlinks

+0

@goatlinks - Ja. – DougW

+6

das könnte eine dumme Frage sein, aber was ist mit der Freigabe der besagten Erinnerung? Ist es egal, weil es so lange leben muss, wie die App läuft? – samiq

26

Ab Xcode 8 können Sie Klasseneigenschaften in Obj-C definieren. Dies wurde hinzugefügt, um mit den statischen Eigenschaften von Swift zusammenzuarbeiten.

Objective-C Klasse unterstützt nun die Eigenschaften, die mit Swift-Typ-Eigenschaften kompatibel sind. Sie werden wie folgt deklariert: @property (class) NSString * someStringProperty; Sie werden niemals synthetisiert. (23891898)

Hier ist ein Beispiel

@interface YourClass : NSObject 

@property (class, nonatomic, assign) NSInteger currentId; 

@end 

@implementation YourClass 

static NSInteger _currentId = 0; 

+ (NSInteger)currentId { 
    return _currentId; 
} 

+ (void)setCurrentId:(NSInteger)newValue { 
    _currentId = newValue; 
} 

@end 

Dann können Sie es wie folgt zugreifen:

YourClass.currentId = 1; 
val = YourClass.currentId; 

Hier ist eine sehr interessante explanatory post ich als Referenz verwendet, um dieses alte zu bearbeiten Antworten.


2011 Antwort: (nicht verwenden, es ist schrecklich)

Wenn Sie wirklich wirklich eine globale Variable deklarieren, nicht wollen, gibt es eine weitere Option, vielleicht nicht sehr orthodox: -), aber funktioniert ... Sie können ein „get & set“ Verfahren wie diese, mit einer statischen variablen innerhalb erklären:

+ (NSString*)testHolder:(NSString*)_test { 
    static NSString *test; 

    if(_test != nil) { 
     if(test != nil) 
      [test release]; 
     test = [_test retain]; 
    } 

    // if(test == nil) 
    //  test = @"Initialize the var here if you need to"; 

    return test; 
} 

Also, wenn Sie den Wert erhalten müssen, rufen Sie einfach:

NSString *testVal = [MyClass testHolder:nil] 

Und dann, wenn Sie es einrichten wollen:

[MyClass testHolder:testVal] 

Im Fall, dass Sie diese pseudo-statische-var in der Lage sein wollen, auf Null zu setzen, können Sie testHolder wie dies erklären:

+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test { 
    static NSString *test; 

    if(shouldSet) { 
     if(test != nil) 
      [test release]; 
     test = [_test retain]; 
    } 

    return test; 
} 

und zwei praktische Methoden:

+ (NSString*)test { 
    return [MyClass testHolderSet:NO newValue:nil]; 
} 

+ (void)setTest:(NSString*)_test { 
    [MyClass testHolderSet:YES newValue:_test]; 
} 

Hoffe, es hilft! Viel Glück.

+0

Cool, aber es ist nicht wirklich eine globale Variable, weil auf sie nicht von anderen '.m' Dateien zugegriffen werden kann, und ich denke es ist in Ordnung, wenn sie innerhalb der' Class.m' Datei "global" ist. – ma11hew28

3

Hier wäre eine Option:

+(int)getId{ 
    static int id; 
    //Do anything you need to update the ID here 
    return id; 
} 

Beachten Sie, dass diese Methode die einzige Methode sein ID zugreifen, so dass Sie es irgendwie in diesem Code zu aktualisieren.

0

Sie können die Klasse als KlasseA umbenennen.mm und fügen Sie C++ - Funktionen hinzu.

2

(Strictly keine Antwort auf die Frage zu sprechen, aber nach meiner Erfahrung wahrscheinlich nützlich sein, wenn für Klassenvariablen suchen)

Eine Klassenmethode kann oft in anderen Sprachen eine Klassenvariable viele der Rollen spielen würde (zB geändert Konfiguration während des Tests):

@interface MyCls: NSObject 
+ (NSString*)theNameThing; 
- (void)doTheThing; 
@end 
@implementation 
+ (NSString*)theNameThing { return @"Something general"; } 
- (void)doTheThing { 
    [SomeResource changeSomething:[self.class theNameThing]]; 
} 
@end 

@interface MySpecialCase: MyCls 
@end 
@implementation 
+ (NSString*)theNameThing { return @"Something specific"; } 
@end 

nun ein Objekt der Klasse MyCls Anrufe Resource:changeSomething: mit der Zeichenfolge @"Something general" auf einen Aufruf von doTheThing:, sondern ein Objekt aus MySpecialCase mit der Zeichenfolge abgeleitet @"Something specific" .

0

Eine andere Möglichkeit wäre, eine kleine NSNumber Unterklasse Singleton zu haben.