Singleton中的Objective-C调用实例方法

时间:2012-07-01 16:03:31

标签: objective-c ios

我创建了一个名为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;
}

2 个答案:

答案 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;
}