I have a class City and the list of cities are stored inside a Plist file. I want to load the cities from the file just once, and to have access to the NSArray of cities from a shared instance.
What I want*
I want to have this behavior
/* here if the array cities is nil just load it from plist if not use the existent array */
City* myCity = [City getCityById:@"1"];
Also
/* inside instance method initWithId I should have access to the loaded array of
cities or load it one time */
City *aCity = [[City alloc]initWithId:@"4"]
What I have tried:
City.h
@interface City : NSObject
@property NSInteger cityId; // instance variable
@property (strong, nonatomic) NSString *name; // instance variable
@property (strong, nonatomic) CLLocation *location; // instance variable
@property (strong, nonatomic) NSArray *cities; // want it to act like a Class variable
-(id) initWithDictionary: (NSDictionary *) dictionay; // instance method
-(id) initWithCityId: (NSDictionary *) cityId; // instance method
+(instancetype)sharedInstance; // Singleton object
+(City*) getCityById:(NSString*) id; // the file need to be loaded!
@end
City.m
@implementation City
// This method load all cities from a plist file
-(void)loadCitiesFromPlist
{
NSMutableArray *citiesArray = [NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cities" ofType:@"plist"]];
self.cities = citiesArray;
}
+ (instancetype) sharedInstance
{
// structure used to test whether the block has completed or not
static dispatch_once_t p = 0;
// initialize sharedObject as nil (first call only)
__strong static id _sharedObject = nil;
// executes a block object once and only once for the lifetime of an application
dispatch_once(&p, ^{
_sharedObject = [[self alloc] init];
[_sharedObject loadCitiesFromPlist];
});
// returns the same object each time
return _sharedObject;
}
+(City*) getCityById:(NSString*)id
{
// can't access the cities array
}
@end
Problem :
- Can't access the cities variable from Class methods ( may be store it as static variable ?)
- If I will use declare getCityById as a instance method, I will load the plist file before search for city because I am not sure that the file has been loaded before.
Note: The instantiation of the object City will happen many times, as I have users and each user belong to a city, but in the same time I want to have a shared instance (Singleton) to manage the load of the file JUST ONE TIME and to handle the class methods that uses the array of cities like getCityById
and getIdOfCityByName