我创建了一个名为DataManager
的Singleton类。我已经设置了一些缓存。但是,当尝试从DataManager
的另一个实例方法中调用缓存实例方法时,我在行上出现EXC_BAD_ACCESS
错误:
NSMutableArray *stops = [[DataManager sharedInstance] getCacheForKey:@"stops"];
DataManager.h
@interface DataManager : NSObject {
FMDatabase *db;
NSMutableDictionary *cache;
}
+ (DataManager *)sharedInstance;
// ... more methods
- (id)getCacheForKey:(NSString *)key;
- (void)setCacheForKey:(NSString *)key withValue:(id)value;
- (void)clearCache;
DataManager.m
- (NSArray *)getStops:(NSInteger)archived {
NSMutableArray *stops = [[DataManager sharedInstance] getCacheForKey:@"stops"];
if (stops != nil) {
NSLog(@"Stops: %@", stops);
return stops;
}
stops = [NSMutableArray array];
// set stops...
[[DataManager sharedInstance] setCacheForKey:@"stops" withValue:stops];
return stops;
}
从另一个视图控制器调用时似乎发生了。这是第一个视图控制器没有错误,第二个视图控制器,错误。
这是我在Singleton的第一次尝试,所以我确定我犯了一个简单的错误。但我自己也没有看到它。
注意:我尝试[self getCache...]
的结果相同。
这是我的Singleton实现。改编自http://www.galloway.me.uk/tutorials/singleton-classes/
+ (DataManager *)sharedInstance {
@synchronized(self) {
if (!instance) {
instance = [[super allocWithZone:NULL] init];
}
}
return instance;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedInstance] retain];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (unsigned)retainCount {
return UINT_MAX;
}
- (oneway void)release {
// never release
}
- (id)autorelease {
return self;
}
- (id)init {
if (self = [super init]) {
if (db == nil){
BourbonAppDelegate *appDelegate = (BourbonAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate createEditableCopyOfDatabaseIfNeeded];
db = [[FMDatabase alloc] initWithPath:[appDelegate getDBPath]];
}
if (![db open]) {
NSAssert(0, @"Failed to open database.");
[db release];
return nil;
}
[db setTraceExecution:YES];
[db setLogsErrors:TRUE];
cache = [NSMutableDictionary dictionary];
NSLog(@"cache: %@", cache);
}
return self;
}
答案 0 :(得分:5)
您的cache
对象已自动释放,因此当您尝试访问它时,它不再在内存中。
使用[NSMutableDictionary alloc] init]
代替[NSMutableDictionary dictionary]
来获取保留的实例。
答案 1 :(得分:4)
不是您问题的直接答案,已经回答了。
但是我想指出你的单例实现是次优的。 @synchronized
非常昂贵,每次访问单身时都可以避免使用它:
if (!instance) {
@synchronized(self) {
if (!instance) {
instance = [[super allocWithZone:NULL] init];
}
}
}
初始化单例的更好方法是:
+ (DataManager *)sharedInstance {
static DataManager *instance;
static dispatch_once_t donce;
dispatch_once(&donce, ^{
instance = [[self alloc] init];
});
return instance;
}