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).