1

我创建了一个名为DataManager. 我已经设置了一些缓存。但是,当尝试从 的另一个实例方法中调用缓存实例方法时DataManagerEXC_BAD_ACCESS出现以下错误:

NSMutableArray *stops = [[DataManager sharedInstance] getCacheForKey:@"stops"];

数据管理器.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;

数据管理器.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;
}

从另一个视图控制器调用时似乎会发生这种情况。那是第一个视图控制器没有错误,第二个视图控制器,错误。

这是我第一次尝试单例,所以我确定我犯了一个简单的错误。但我自己看不到。

注意:我尝试[self getCache...]过相同的结果。

更新

这是我的单例实现。改编自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;
}
4

2 回答 2

5

您的cache对象是自动释放的,因此当您尝试访问它时它不再在内存中。

使用[NSMutableDictionary alloc] init]而不是[NSMutableDictionary dictionary]获取保留的实例。

于 2012-07-01T16:13:53.277 回答
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;
}
于 2012-07-01T16:21:25.610 回答