Per creare una classe che sia raggiungibile da ogni parte del nostro codice, abbiamo due alternative: realizzare una classe statica con metodi e attributi statici, oppure implementare il pattern del Singleton.
Preferisco generalmente la seconda scelta più orientata ad un design pulito del nostro codice e rimanendo legato alla programmazione ad oggetti.
Per creare una classe statica, con attributi e metodi statici definiamo l’interfaccia:
1 2 3 4 | @interface MyStaticClass : NSObject + (int)getIntMethod; + (void)setIntMethod:(int)value; @end |
e poi implementiamola:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #import "MyStaticClass.h" @implementation MyStaticClass static int staticValue = 1; + (int)getIntMethod { return staticValue; } + (void)setIntMethod:(int)value { staticValue = value; } + (id)alloc { [NSException raise:@"Non può essere istanziata format:@"Static class 'ClassName' non può essere instanziato"]; return nil; } @end |
importante l’override dell’alloc per non permettere alla classe di essere istanziata.
Per un approccio più elegante e sicuramente più riusabile, implementiamo invece il Design Pattern del Singleton:
1 2 3 4 5 6 7 8 9 | @interface MySingleton : NSObject { } -(int)getIntMethod; -(void)setIntMethod:(int)value; + (MySingleton *) m_MySingleton; @end |
Implementiamo la nostra interfaccia:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | #import "MySingleton.h" @implementation MySingleton static MySingleton *m_MySingleton =nil; static int staticValue = 1; + (MySingleton *) m_MySingleton { if (m_MySingleton == nil) { //creo l'istanza m_MySingleton = [[super allocWithZone:NULL] init]; } return m_MySingleton; } - (int)getIntMethod { return staticValue; } - (void)setIntMethod:(int)value { staticValue = value; } + (id)allocWithZone:(NSZone *)zone { //sincronizzo in modo da rendere la fase di allocazione ThreadSafe //in modo da gestire più thread che richiedono contemporaneamente il Singleton @synchronized(self) { if (m_MySingleton == nil) { m_MySingleton = [super allocWithZone:zone]; return m_MySingleton; } } return nil; } - (id)copyWithZone:(NSZone *)zone { //non e' possibile clonarlo e quindi ritorna sempre la stessa istanza. return self; } - (id)retain { return self; } - (NSUInteger)retainCount { //in questo modo il suo refCount non scenderà mai a zero. return NSUIntegerMax; } - (void) release { //non fa nulla. } - (id)autorelease { return self; } @end |
Piccola correzione. I metodi nel singleton ovviamente non devono essere statici (tranne il metodo che permette l’accesso all’istanza).