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
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.
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).
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.
Problem Beschreibung:
- Sie möchten Ihre KlasseA eine ClassB Klassenvariable haben.
- Sie verwenden Objective-C als Programmiersprache.
- Objective-C unterstützt keine Klassenvariablen wie C++.
Eine Alternative:
Simulieren eine Klassenvariable Verhalten Objective-C mit Funktionen
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).
Überschreiben Sie die NSObject initialize class-Methode, um nur einmal die statische Variable mit einer Instanz von ClassB zu initialisieren.
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.) ".
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:
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.
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
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.
Sie können die Klasse als KlasseA umbenennen.mm und fügen Sie C++ - Funktionen hinzu.
(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"
.
Eine andere Möglichkeit wäre, eine kleine NSNumber
Unterklasse Singleton zu haben.
Bitte korrigieren: '+ (void) initialize' ist die Methode – monkeydom