objective C 中的单例和静态变量访问
Singelton and Static variable access in objective C
我有一个 class City 并且城市列表存储在 Plist 文件中。我只想从文件中加载城市一次,并从共享实例访问城市的 NSArray。
我想要的*
我想要这种行为
/* here if the array cities is nil just load it from plist if not use the existent array */
City* myCity = [City getCityById:@"1"];
还有
/* 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"]
我试过的:
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
问题:
- 无法从 Class 方法访问 cities 变量(可能将其存储为静态变量?)
- 如果我将 declare getCityById 用作实例方法,我将在搜索城市之前加载 plist 文件,因为我不确定之前是否加载过该文件。
注意:城市对象的实例化会发生很多次,因为我有用户,每个用户都属于一个城市,但同时我想有一个共享实例(Singleton)来管理负载文件一次并处理使用 getCityById
和 getIdOfCityByName
等城市数组的 class 方法
查看 NSObject
中的 +(void)initialize
。 Link
任意Class调用一次。在这里您可以将列表加载到静态数组中并在每个实例中使用它。
或者考虑这样的方法:SO answer
解法:
使用方法 + (void)initialize
: Apple Documentation
我们将变量声明为 static
City.m
#import "City.h"
static NSArray *cities = nil;
@implementation City
+ (void)initialize
{
if (self == [City self])
{
if (!cities)
{
cities = [self loadCitiesFromPlist];
}
}
}
-(id) initWithDictionary: (NSDictionary *) dictionay
{
self = [super init];
// convert the NSDictionary to City object
return self;
}
// This method load all cities from the file
+(NSArray *) loadCitiesFromPlist
{
NSLog(@"loadCitiesFromPlist");
NSMutableArray *citiesArray = [NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cities" ofType:@"plist"]];
NSMutableArray *citiesObjectsArray = [[NSMutableArray alloc] init];
for (NSDictionary *cityDict in citiesArray)
{
[ citiesObjectsArray addObject: [[City alloc]initWithDictionary:cityDict]] ;
}
return citiesObjectsArray;
}
+(City*) getCityById:(NSString *) cityId
{
NSUInteger barIndex = [cities indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
City* city = (City*) obj;
if(city.cityId == [cityId intValue])
{
*stop = YES;
return YES;
}
return NO;
}];
if (barIndex != NSNotFound)
{
return [cities objectAtIndex:barIndex];
}
else
{
return nil;
}
}
+(NSArray*) getAllCitiesNames
{
NSMutableArray *citiesNames =[[NSMutableArray alloc] init];
for(City* city in cities)
{
[citiesNames addObject:city.name];
}
return citiesNames;
}
@end
More Information in this SO answer
我有一个 class City 并且城市列表存储在 Plist 文件中。我只想从文件中加载城市一次,并从共享实例访问城市的 NSArray。
我想要的*
我想要这种行为
/* here if the array cities is nil just load it from plist if not use the existent array */
City* myCity = [City getCityById:@"1"];
还有
/* 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"]
我试过的:
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
问题:
- 无法从 Class 方法访问 cities 变量(可能将其存储为静态变量?)
- 如果我将 declare getCityById 用作实例方法,我将在搜索城市之前加载 plist 文件,因为我不确定之前是否加载过该文件。
注意:城市对象的实例化会发生很多次,因为我有用户,每个用户都属于一个城市,但同时我想有一个共享实例(Singleton)来管理负载文件一次并处理使用 getCityById
和 getIdOfCityByName
查看 NSObject
中的 +(void)initialize
。 Link
任意Class调用一次。在这里您可以将列表加载到静态数组中并在每个实例中使用它。
或者考虑这样的方法:SO answer
解法:
使用方法 + (void)initialize
: Apple Documentation
我们将变量声明为 static
City.m
#import "City.h"
static NSArray *cities = nil;
@implementation City
+ (void)initialize
{
if (self == [City self])
{
if (!cities)
{
cities = [self loadCitiesFromPlist];
}
}
}
-(id) initWithDictionary: (NSDictionary *) dictionay
{
self = [super init];
// convert the NSDictionary to City object
return self;
}
// This method load all cities from the file
+(NSArray *) loadCitiesFromPlist
{
NSLog(@"loadCitiesFromPlist");
NSMutableArray *citiesArray = [NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cities" ofType:@"plist"]];
NSMutableArray *citiesObjectsArray = [[NSMutableArray alloc] init];
for (NSDictionary *cityDict in citiesArray)
{
[ citiesObjectsArray addObject: [[City alloc]initWithDictionary:cityDict]] ;
}
return citiesObjectsArray;
}
+(City*) getCityById:(NSString *) cityId
{
NSUInteger barIndex = [cities indexOfObjectPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
City* city = (City*) obj;
if(city.cityId == [cityId intValue])
{
*stop = YES;
return YES;
}
return NO;
}];
if (barIndex != NSNotFound)
{
return [cities objectAtIndex:barIndex];
}
else
{
return nil;
}
}
+(NSArray*) getAllCitiesNames
{
NSMutableArray *citiesNames =[[NSMutableArray alloc] init];
for(City* city in cities)
{
[citiesNames addObject:city.name];
}
return citiesNames;
}
@end
More Information in this SO answer