2009-06-30 7 views
139

Ho una classe Film, ognuna delle quali memorizza un ID univoco. In C#, Java ecc. Posso definire un currentID int statico e ogni volta che imposto l'ID posso aumentare l'currentID e la modifica avviene a livello di classe e non a livello di oggetto. Questo può essere fatto nell'obiettivo C? Ho trovato molto difficile trovare una risposta per questo.Objective C Static Class Variabili di livello

risposta

28

Sul file .m, è possibile dichiarare una variabile come statica:

static ClassName *variableName = nil; 

Quindi è possibile inizializzare il tuo metodo di +(void)initialize.

Si prega di notare che questa è una variabile statica pianura C e non è statico in Java o C# senso prendere in considerazione, ma produrrà risultati simili.

+3

correggi: '+ (void) initialize' è il metodo – monkeydom

11

Come ha detto pgb, non ci sono "variabili di classe", solo "variabili di istanza". Il modo obiettivo-c di fare variabili di classe è una variabile globale statica all'interno del file .m della classe. Lo "statico" assicura che la variabile non possa essere usata al di fuori di quel file (cioè non può essere esterna).

16

Nel file .m, dichiarare una variabile globale del file:

static int currentID = 1; 

poi nella vostra routine init, refernce che:

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

o se ha bisogno di cambiare in un altro momento (ad esempio nel metodo openConnection), quindi incrementalo lì. Ricorda che non è thread-safe così com'è, dovrai fare syncronization (o meglio ancora, usare un atomic add) se ci possono essere problemi di threading.

155

Descrizione del problema:

  1. Volete che il vostro ClasseA di avere una variabile di classe ClassB.
  2. Si sta utilizzando Objective-C come linguaggio di programmazione.
  3. Objective-C non supporta le variabili di classe come fa C++.

una alternativa:

simulare un comportamento variabile di classe usando Objective-C dispone

  1. Declare/definire una variabile statica all'interno del classA.m quindi sarà accessibile solo per i i metodi classA (e tutto ciò che inserisci in classA.m).

  2. sovrascrivere il NSObject inizializzare metodo di classe per inizializzare una sola volta la variabile statica con un'istanza di ClassB.

  3. Vi starete chiedendo, perché dovrei sovrascrivere il metodo di inizializzazione NSObject. La documentazione di Apple su questo metodo ha la risposta: "Il runtime invia initialize a ogni classe in un programma esattamente una volta appena prima che la classe, o qualsiasi classe che ne erediti, sia inviata il suo primo messaggio all'interno del programma. potrebbe mai essere invocato se la classe non viene utilizzata.) ".

  4. Sei libero di usare la variabile statica all'interno di qualsiasi metodo di classe/istanza ClassA.

campione Codice:

di file: 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 

Riferimenti:

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

Puoi avere una variabile statica di Type ClassA in classA.m? – goatlinks

+0

@goatlinks - Sì. – DougW

+6

questa potrebbe essere una domanda stupida, ma per quanto riguarda il rilascio di detta memoria? non ha importanza perché deve vivere fino a quando l'app è in esecuzione? – samiq

26

A partire da Xcode 8, è possibile definire le proprietà della classe in Obj-C. Questo è stato aggiunto per interoperare con le proprietà statiche di Swift.

Objective-C supporta ora le proprietà di classe, che interagiscono con le proprietà di tipo Swift. Sono dichiarati come: @property (class) NSString * someStringProperty ;. Non sono mai sintetizzati. (23891898)

Ecco un esempio

@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 

Poi si può accedere in questo modo:

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

Ecco un interessante explanatory post ho usato come riferimento per modificare questa vecchia risposta.


2011 Risposta: (non utilizzare questo, è terribile)

Se davvero non si vuole dichiarare una variabile globale, c'è un'altra opzione, forse non molto ortodosso: -), ma funziona ... È possibile dichiarare un metodo "get & set" in questo modo, con una variabile statica all'interno:

+ (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; 
} 

Quindi, se avete bisogno di ottenere il valore, basta chiamare:

NSString *testVal = [MyClass testHolder:nil] 

E poi, quando si vuole impostare:

[MyClass testHolder:testVal] 

Nel caso in cui si desidera essere in grado di impostare questo pseudo-statica-var a zero, è possibile dichiarare testHolder come questo:

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

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

    return test; 
} 

E due metodi pratici:

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

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

Speranza che aiuta! In bocca al lupo.

+0

Fresco, ma non è realmente una variabile globale perché non è possibile accedervi da altri file '.m', e penso che sia perfetto per essere" globale "all'interno del file' Class.m'. – ma11hew28

3

qui sarebbe un'opzione:

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

Nota che questo metodo sarà l'unico metodo per accedere id, in modo da avere per aggiornare in qualche modo in questo codice.

0

u è possibile rinominare la classe come classeA.mm e aggiungere funzionalità C++ in esso.

2

(in senso stretto non è una risposta alla domanda, ma nella mia esperienza che possono rivelarsi utili quando alla ricerca di variabili di classe)

Un metodo di classe spesso può giocare molti dei ruoli una variabile di classe farebbe in altre lingue (es cambiato configurazione durante le prove):

@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 

Ora, un oggetto della classe MyCls chiamate Resource:changeSomething: con la stringa @"Something general" su una chiamata a doTheThing:, ma un oggetto deriva dalla MySpecialCase con la stringa @"Something specific" .

0

Un'altra possibilità sarebbe quella di avere un piccolo sottoclasse NSNumber singleton.

Problemi correlati