如何解决( EXC_BAD_ADDRESS in Objective-C )?
How to solve it ( EXC_BAD_ADDRESS in Objective-C )?
有时,我的应用程序会出现致命错误并显示 EXC_BAD_ADDRESS 错误日志。
我的代码是什么原因造成的?
崩溃日志
0. Crashed: GGMutableDictionary Isolation Queue
0 libobjc.A.dylib 0x184e2c150 objc_msgSend + 16
1 CoreFoundation 0x1862e0d04 -[NSDictionary descriptionWithLocale:indent:] + 916
2 CoreFoundation 0x1862e0dac -[NSDictionary descriptionWithLocale:indent:] + 1084
3 Foundation 0x186da35a4 _NSDescriptionWithLocaleFunc + 76
4 CoreFoundation 0x1863788bc __CFStringAppendFormatCore + 8440
5 CoreFoundation 0x18637678c _CFStringCreateWithFormatAndArgumentsAux2 + 244
6 Foundation 0x186da3418 +[NSString stringWithFormat:] + 68
7 app 0x10019f4b8 -[TinyDB saveAsync] + 4296963256
8 app 0x10019c86c __26-[TinyDB putString:value:]_block_invoke + 4296951916
9 libdispatch.dylib 0x18526e9a0 _dispatch_client_callout + 16
10 libdispatch.dylib 0x18527bee0 _dispatch_barrier_sync_f_invoke + 84
11 app 0x10019c7e0 -[TinyDB putString:value:] + 4296951776
源文件
此 class 与许多其他 class 异步使用。
这个 class 应该是线程安全的。但是 EXC_BAD_ADDRESS 致命错误发生在 saveAsync 方法中。
我认为 weakDictionaryRef 或 isolationQueue 变量被释放。我想解决这个问题。我应该在此代码中修复什么?
感谢您的意见。
TinyDB.h 文件
@interface TinyDB : NSObject
@property (nonatomic, retain) NSString * docPath;
// @property (nonatomic, retain) NSMutableDictionary * dictionary;
@property (nonatomic, retain) NSFileManager * fileManager;
@property (nonatomic, retain) NSString * dir;
@property (nonatomic, assign) BOOL flagWrite;
- (instancetype)initWithFile:(NSString *)file;
- (NSString *)getDocPath;
- (void)putDouble:(NSString *)key value:(double)value;
- (void)putInt:(NSString *)key value:(NSInteger)value;
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value;
- (void)putString:(NSString *)key value:(NSString *)value;
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value;
- (void)putLong:(NSString *)key value:(NSInteger)value;
- (void)putBool:(NSString *)key value:(BOOL)value;
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value;
- (id)get:(NSString *)key;
- (NSMutableArray *)getMutableArray:(NSString *)key;
- (BOOL)has:(NSString *)key;
- (void)saveAsync;
- (void)save;
- (NSString *)jsonString;
- (NSString *)stringify:(id)obj;
- (NSString *)getSet:(id)value;
- (NSString *)getPairSet:(NSString *)key value:(id)value;
- (NSMutableDictionary*)getMutableDictionary:(NSString*)key;
- (NSString *)getString:(NSString *)key;
- (BOOL)getBool:(NSString*)key;
- (NSArray *)allKeys;
- (void)removeObjectForKey:(NSString*)key;
@end
TinyDB.m 文件
@implementation TinyDB
{
@private dispatch_queue_t isolationQueue_;
@private __strong NSMutableDictionary * _myDictionary;
}
@synthesize docPath=docPath,fileManager=fileManager,dir=dir,flagWrite=flagWrite;
BOOL flagOnSave = false;
BOOL flagWrite = true;
NSString* dir;
NSString* docPath = @"";
NSLock* _dicLock=nil;
NSFileManager* fileManager;
__weak id _weakDictionaryRef;
-(id)initWithFile:(NSString *)file{
self = [super init];
docPath = file;
// ##########################################
isolationQueue_ = dispatch_queue_create([@"GGMutableDictionary Isolation Queue" UTF8String], DISPATCH_QUEUE_CONCURRENT);
// ##########################################
fileManager = [NSFileManager defaultManager];
dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) firstObject];
dir = [NSString stringWithFormat:@"%@/myapp/",dir];
BOOL flagFileExist = [fileManager fileExistsAtPath:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]];
_myDictionary = [[NSMutableDictionary alloc] init];
if(flagFileExist){
[BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Found!!! %@ --> ",file]];
@try{
NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithContentsOfFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]];
_myDictionary = [[NSMutableDictionary alloc] initWithDictionary:dic];
}@catch(NSException * e){
_myDictionary = [[NSMutableDictionary alloc] init];
}@finally{
}
}else{
[BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Not Found!!!--> %@ ",file]];
_myDictionary = [[NSMutableDictionary alloc] init];
}
_weakDictionaryRef = _myDictionary;
[self saveAsync];
return self;
}
-(void)putString:(NSString*)key value:(NSString*)value{
dispatch_barrier_sync(isolationQueue_, ^{
if(value == nil){
return;
}
@try{
[_myDictionary setObject:value forKey:key];
}@catch(NSException* e){
NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
_myDictionary = buff;
_weakDictionaryRef = _myDictionary;
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:value forKey:key];
});
}@finally{
}
[self saveAsync];
});
}
- (void)putDouble:(NSString *)key value:(double)value{
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:[[NSNumber alloc] initWithDouble:value] forKey:key];
[self saveAsync];
});
}
- (void)putInt:(NSString *)key value:(NSInteger)value{
dispatch_barrier_sync(isolationQueue_, ^{
@try{
[_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
}@catch(NSException* e){
NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
_myDictionary = buff;
_weakDictionaryRef = _myDictionary;
[_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
}@finally{
}
[self saveAsync];
});
}
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value{
dispatch_barrier_sync(isolationQueue_, ^{
if( key != nil && value != nil ){
[_myDictionary setObject:value forKey:key];
[self saveAsync];
}
});
}
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value{
dispatch_barrier_sync(isolationQueue_, ^{
TinyDB* db = value;
NSString* docuPath = [db getDocPath];
@try{
[_myDictionary setObject:docuPath forKey:key];
}@catch(NSException* e){
NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
_myDictionary = buff;
_weakDictionaryRef = _myDictionary;
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:docuPath forKey:key];
});
}@finally{
}
[self saveAsync];
});
}
- (void)putLong:(NSString *)key value:(NSInteger)value{
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
[self saveAsync];
});
}
- (void)putBool:(NSString *)key value:(BOOL)value{
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:[[NSNumber alloc] initWithBool:value] forKey:key];
[self saveAsync];
});
}
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value{
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:value forKey:key];
[self saveAsync];
});
}
-(void)removeObjectForKey:(NSString*)key{
dispatch_barrier_sync(isolationQueue_, ^{
if( _myDictionary != nil && [_myDictionary objectForKey:key] != nil ){
[_myDictionary removeObjectForKey:key];
}
});
}
-(void) save{
dispatch_barrier_sync(isolationQueue_, ^{
@try {
// NSLog([NSString stringWithFormat:@"writeToFile Error : orgPath = %@/%@.myapp / %@",dir,docPath, self.dictionary ]);
// NSMutableDictionary* nsDic = self.dictionary;
if( _myDictionary != nil ){
NSDictionary * _dictionary =
(__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
(__bridge CFPropertyListRef)(_myDictionary),
kCFPropertyListImmutable));
if( _dictionary != nil ){
[_dictionary writeToFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath] atomically: false];
}
}
}@catch (NSException *exception) {
_myDictionary = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
_weakDictionaryRef = _myDictionary;
}@finally {
}
});
}
// ################################################################
// normal function
- (NSString *)jsonString{
__block NSString* buff = @"";
dispatch_barrier_sync(isolationQueue_, ^{
if( _myDictionary != nil ){
NSDictionary * _dictionary = nil;
// dispatch_barrier_sync(isolationQueue_, ^{
_dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
(__bridge CFPropertyListRef)(_myDictionary),
kCFPropertyListImmutable));
if( _dictionary != nil ){
buff = [self stringify:_dictionary];
}
}else{
NSLog(@"buff = [self stringify:_myDictionary]; is nil ");
}
});
return buff;
}
- (NSString *)stringify:(id)obj{
if([obj isKindOfClass:[NSDictionary class]]){
int idx = 0;
NSString* buff = @"{";
if( obj != nil ){
NSDictionary* dic = [NSDictionary dictionaryWithDictionary:obj]; //obj;
for(NSString* key in dic){
id value = [dic objectForKey:key];
if(idx != 0){
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","];
}
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getPairSet:key value:value]];
idx++;
}
}
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"}"];
return buff;
}else if([obj isKindOfClass:[NSArray class]]){
int idx = 0;
NSString* buff = @"[";
if( obj != nil ){
NSMutableArray* _a = [[NSMutableArray alloc] init];
for( int ai = 0; ai < [obj count]; ai++){
if( [obj objectAtIndex:ai] != nil ){
[_a addObject:[obj objectAtIndex:ai]];
}
}
NSArray* arr = [NSArray arrayWithArray:_a]; //obj;
for(id value in arr){
if(idx != 0){
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","];
}
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getSet:value]];
idx++;
}
}
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"]"];
return buff;
}else{
return [self getSet:obj];
}
}
- (NSString *)getSet:(id)value{
NSString* buff = @"";
if([value isKindOfClass:[NSString class]]){
buff = [[NSString alloc] initWithFormat:@"%@\"%@\"",buff,value];
}else if([value isKindOfClass:[NSNumber class]]){
NSNumber* val = value;
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[val stringValue]];
}else{
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self stringify:value]];
}
return buff;
}
- (NSString *)getPairSet:(NSString *)key value:(id)value{
NSString* buff = @"";
if([value isKindOfClass:[NSString class]]){
buff = [[NSString alloc] initWithFormat:@"%@\"%@\":\"%@\"",buff,key,value];
}else if([value isKindOfClass:[NSNumber class]]){
buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[value stringValue]];
}else{
buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[self stringify:value]];
}
return buff;
}
-(NSMutableDictionary*)getMutableDictionary:(NSString*)key{
NSMutableDictionary* dic = [[NSMutableDictionary alloc] init];
id obj = [_myDictionary objectForKey:key];
if(obj != nil){
dic = [[NSMutableDictionary alloc] initWithDictionary:obj];
}
return dic;
}
-(NSArray *)allKeys{
__block NSArray* arr = nil;
dispatch_barrier_sync(isolationQueue_, ^{
if( _myDictionary != nil ){
arr = [_myDictionary allKeys];
}
});
return arr;
}
- (NSString *)getDocPath{
return docPath;
}
- (id)get:(NSString *)key{
__block id _obj = nil;
dispatch_barrier_sync(isolationQueue_, ^{
_obj = [_myDictionary objectForKey:key];
});
return _obj;
}
- (NSString *)getString:(NSString *)key{
__block NSString* returnStr = @"";
dispatch_barrier_sync(isolationQueue_, ^{
if([_myDictionary objectForKey:key]==nil){
returnStr = @"";
}
if([[_myDictionary objectForKey:key] isKindOfClass:[NSString class]]){
returnStr = [_myDictionary objectForKey:key];
}else{
returnStr = @"";
}
});
return returnStr;
}
- (BOOL)getBool:(NSString*)key{
__block BOOL flag = false;
dispatch_barrier_sync(isolationQueue_, ^{
if([_myDictionary objectForKey:key]==nil){
flag = NO;
}
if([[_myDictionary objectForKey:key] isKindOfClass:[NSNumber class]]){
NSNumber* boolValue = [_myDictionary objectForKey:key];
if([boolValue boolValue] == YES){
flag = YES;
}else{
flag = NO;
}
}else{
flag = NO;
}
});
return flag;
}
- (NSMutableArray *)getMutableArray:(NSString *)key{
__block NSMutableArray* _arr = nil;
dispatch_barrier_sync(isolationQueue_, ^{
_arr = [_myDictionary objectForKey:key];
});
return _arr;
}
- (BOOL)has:(NSString *)key{
__block BOOL flag = false;
dispatch_barrier_sync(isolationQueue_, ^{
if([_myDictionary objectForKey:key] != nil){
flag = true;
}else{
flag = false;
}
});
return flag;
}
// #########################
// save function
int flagTest = 0;
bool mark = 0;
NSTimer* saveTimer = nil;
-(void)saveAsync{
@try {
[BSDebugger log:[NSString stringWithFormat:@"_weakDictionaryRef : %@ ",_weakDictionaryRef ]];
if( _myDictionary != nil ){
if( _weakDictionaryRef != nil ){
NSDictionary * _dictionary = nil;
_dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
(__bridge CFPropertyListRef)(_myDictionary),
kCFPropertyListImmutable));
@try{
flagOnSave = true;
UIBackgroundTaskIdentifier taskID = [myappCore beginBackgroundUpdateTask];
flagWrite = false;
NSString* orgPath = [[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath ];
@try {
if( _dictionary != nil ){
[_dictionary writeToFile:orgPath atomically:YES];
}
}@catch (NSException *exception) {
[BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exception callStackSymbols]]];
}@finally {
}
flagWrite = true;
flagOnSave = false;
[myappCore endBackgroundUpdateTask:taskID];
}@catch (NSException *exceptionMain) {
[BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exceptionMain callStackSymbols]]];
}@finally {
_dictionary = nil;
}
return;
// });
}
}
}@catch (NSException *exception) {
}@finally {
// [_dicLock unlock];
}
}
@end
一些想法:
打开僵尸 (How to enable NSZombie in Xcode)。执行此操作时,您将获得有关导致崩溃的对象的更多信息。
如果你能随意让错误发生,在saveAsync
的顶部设置一个断点并逐步执行它。
以某种方式更改 stringWithFormat
调用,使它们不引用任何可能被释放的内容,然后查看问题是否消失。如果是这样,您就会知道是什么原因造成的。
我发现有时覆盖我怀疑的对象中的 retain
和 release
并打印一些东西或设置一个断点,这样我就可以看到谁可能过度释放了一个对象。
有时,我的应用程序会出现致命错误并显示 EXC_BAD_ADDRESS 错误日志。
我的代码是什么原因造成的?
崩溃日志
0. Crashed: GGMutableDictionary Isolation Queue
0 libobjc.A.dylib 0x184e2c150 objc_msgSend + 16
1 CoreFoundation 0x1862e0d04 -[NSDictionary descriptionWithLocale:indent:] + 916
2 CoreFoundation 0x1862e0dac -[NSDictionary descriptionWithLocale:indent:] + 1084
3 Foundation 0x186da35a4 _NSDescriptionWithLocaleFunc + 76
4 CoreFoundation 0x1863788bc __CFStringAppendFormatCore + 8440
5 CoreFoundation 0x18637678c _CFStringCreateWithFormatAndArgumentsAux2 + 244
6 Foundation 0x186da3418 +[NSString stringWithFormat:] + 68
7 app 0x10019f4b8 -[TinyDB saveAsync] + 4296963256
8 app 0x10019c86c __26-[TinyDB putString:value:]_block_invoke + 4296951916
9 libdispatch.dylib 0x18526e9a0 _dispatch_client_callout + 16
10 libdispatch.dylib 0x18527bee0 _dispatch_barrier_sync_f_invoke + 84
11 app 0x10019c7e0 -[TinyDB putString:value:] + 4296951776
源文件
此 class 与许多其他 class 异步使用。 这个 class 应该是线程安全的。但是 EXC_BAD_ADDRESS 致命错误发生在 saveAsync 方法中。 我认为 weakDictionaryRef 或 isolationQueue 变量被释放。我想解决这个问题。我应该在此代码中修复什么? 感谢您的意见。
TinyDB.h 文件
@interface TinyDB : NSObject
@property (nonatomic, retain) NSString * docPath;
// @property (nonatomic, retain) NSMutableDictionary * dictionary;
@property (nonatomic, retain) NSFileManager * fileManager;
@property (nonatomic, retain) NSString * dir;
@property (nonatomic, assign) BOOL flagWrite;
- (instancetype)initWithFile:(NSString *)file;
- (NSString *)getDocPath;
- (void)putDouble:(NSString *)key value:(double)value;
- (void)putInt:(NSString *)key value:(NSInteger)value;
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value;
- (void)putString:(NSString *)key value:(NSString *)value;
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value;
- (void)putLong:(NSString *)key value:(NSInteger)value;
- (void)putBool:(NSString *)key value:(BOOL)value;
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value;
- (id)get:(NSString *)key;
- (NSMutableArray *)getMutableArray:(NSString *)key;
- (BOOL)has:(NSString *)key;
- (void)saveAsync;
- (void)save;
- (NSString *)jsonString;
- (NSString *)stringify:(id)obj;
- (NSString *)getSet:(id)value;
- (NSString *)getPairSet:(NSString *)key value:(id)value;
- (NSMutableDictionary*)getMutableDictionary:(NSString*)key;
- (NSString *)getString:(NSString *)key;
- (BOOL)getBool:(NSString*)key;
- (NSArray *)allKeys;
- (void)removeObjectForKey:(NSString*)key;
@end
TinyDB.m 文件
@implementation TinyDB
{
@private dispatch_queue_t isolationQueue_;
@private __strong NSMutableDictionary * _myDictionary;
}
@synthesize docPath=docPath,fileManager=fileManager,dir=dir,flagWrite=flagWrite;
BOOL flagOnSave = false;
BOOL flagWrite = true;
NSString* dir;
NSString* docPath = @"";
NSLock* _dicLock=nil;
NSFileManager* fileManager;
__weak id _weakDictionaryRef;
-(id)initWithFile:(NSString *)file{
self = [super init];
docPath = file;
// ##########################################
isolationQueue_ = dispatch_queue_create([@"GGMutableDictionary Isolation Queue" UTF8String], DISPATCH_QUEUE_CONCURRENT);
// ##########################################
fileManager = [NSFileManager defaultManager];
dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) firstObject];
dir = [NSString stringWithFormat:@"%@/myapp/",dir];
BOOL flagFileExist = [fileManager fileExistsAtPath:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]];
_myDictionary = [[NSMutableDictionary alloc] init];
if(flagFileExist){
[BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Found!!! %@ --> ",file]];
@try{
NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithContentsOfFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]];
_myDictionary = [[NSMutableDictionary alloc] initWithDictionary:dic];
}@catch(NSException * e){
_myDictionary = [[NSMutableDictionary alloc] init];
}@finally{
}
}else{
[BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Not Found!!!--> %@ ",file]];
_myDictionary = [[NSMutableDictionary alloc] init];
}
_weakDictionaryRef = _myDictionary;
[self saveAsync];
return self;
}
-(void)putString:(NSString*)key value:(NSString*)value{
dispatch_barrier_sync(isolationQueue_, ^{
if(value == nil){
return;
}
@try{
[_myDictionary setObject:value forKey:key];
}@catch(NSException* e){
NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
_myDictionary = buff;
_weakDictionaryRef = _myDictionary;
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:value forKey:key];
});
}@finally{
}
[self saveAsync];
});
}
- (void)putDouble:(NSString *)key value:(double)value{
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:[[NSNumber alloc] initWithDouble:value] forKey:key];
[self saveAsync];
});
}
- (void)putInt:(NSString *)key value:(NSInteger)value{
dispatch_barrier_sync(isolationQueue_, ^{
@try{
[_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
}@catch(NSException* e){
NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
_myDictionary = buff;
_weakDictionaryRef = _myDictionary;
[_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
}@finally{
}
[self saveAsync];
});
}
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value{
dispatch_barrier_sync(isolationQueue_, ^{
if( key != nil && value != nil ){
[_myDictionary setObject:value forKey:key];
[self saveAsync];
}
});
}
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value{
dispatch_barrier_sync(isolationQueue_, ^{
TinyDB* db = value;
NSString* docuPath = [db getDocPath];
@try{
[_myDictionary setObject:docuPath forKey:key];
}@catch(NSException* e){
NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
_myDictionary = buff;
_weakDictionaryRef = _myDictionary;
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:docuPath forKey:key];
});
}@finally{
}
[self saveAsync];
});
}
- (void)putLong:(NSString *)key value:(NSInteger)value{
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
[self saveAsync];
});
}
- (void)putBool:(NSString *)key value:(BOOL)value{
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:[[NSNumber alloc] initWithBool:value] forKey:key];
[self saveAsync];
});
}
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value{
dispatch_barrier_sync(isolationQueue_, ^{
[_myDictionary setObject:value forKey:key];
[self saveAsync];
});
}
-(void)removeObjectForKey:(NSString*)key{
dispatch_barrier_sync(isolationQueue_, ^{
if( _myDictionary != nil && [_myDictionary objectForKey:key] != nil ){
[_myDictionary removeObjectForKey:key];
}
});
}
-(void) save{
dispatch_barrier_sync(isolationQueue_, ^{
@try {
// NSLog([NSString stringWithFormat:@"writeToFile Error : orgPath = %@/%@.myapp / %@",dir,docPath, self.dictionary ]);
// NSMutableDictionary* nsDic = self.dictionary;
if( _myDictionary != nil ){
NSDictionary * _dictionary =
(__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
(__bridge CFPropertyListRef)(_myDictionary),
kCFPropertyListImmutable));
if( _dictionary != nil ){
[_dictionary writeToFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath] atomically: false];
}
}
}@catch (NSException *exception) {
_myDictionary = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
_weakDictionaryRef = _myDictionary;
}@finally {
}
});
}
// ################################################################
// normal function
- (NSString *)jsonString{
__block NSString* buff = @"";
dispatch_barrier_sync(isolationQueue_, ^{
if( _myDictionary != nil ){
NSDictionary * _dictionary = nil;
// dispatch_barrier_sync(isolationQueue_, ^{
_dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
(__bridge CFPropertyListRef)(_myDictionary),
kCFPropertyListImmutable));
if( _dictionary != nil ){
buff = [self stringify:_dictionary];
}
}else{
NSLog(@"buff = [self stringify:_myDictionary]; is nil ");
}
});
return buff;
}
- (NSString *)stringify:(id)obj{
if([obj isKindOfClass:[NSDictionary class]]){
int idx = 0;
NSString* buff = @"{";
if( obj != nil ){
NSDictionary* dic = [NSDictionary dictionaryWithDictionary:obj]; //obj;
for(NSString* key in dic){
id value = [dic objectForKey:key];
if(idx != 0){
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","];
}
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getPairSet:key value:value]];
idx++;
}
}
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"}"];
return buff;
}else if([obj isKindOfClass:[NSArray class]]){
int idx = 0;
NSString* buff = @"[";
if( obj != nil ){
NSMutableArray* _a = [[NSMutableArray alloc] init];
for( int ai = 0; ai < [obj count]; ai++){
if( [obj objectAtIndex:ai] != nil ){
[_a addObject:[obj objectAtIndex:ai]];
}
}
NSArray* arr = [NSArray arrayWithArray:_a]; //obj;
for(id value in arr){
if(idx != 0){
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","];
}
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getSet:value]];
idx++;
}
}
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"]"];
return buff;
}else{
return [self getSet:obj];
}
}
- (NSString *)getSet:(id)value{
NSString* buff = @"";
if([value isKindOfClass:[NSString class]]){
buff = [[NSString alloc] initWithFormat:@"%@\"%@\"",buff,value];
}else if([value isKindOfClass:[NSNumber class]]){
NSNumber* val = value;
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[val stringValue]];
}else{
buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self stringify:value]];
}
return buff;
}
- (NSString *)getPairSet:(NSString *)key value:(id)value{
NSString* buff = @"";
if([value isKindOfClass:[NSString class]]){
buff = [[NSString alloc] initWithFormat:@"%@\"%@\":\"%@\"",buff,key,value];
}else if([value isKindOfClass:[NSNumber class]]){
buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[value stringValue]];
}else{
buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[self stringify:value]];
}
return buff;
}
-(NSMutableDictionary*)getMutableDictionary:(NSString*)key{
NSMutableDictionary* dic = [[NSMutableDictionary alloc] init];
id obj = [_myDictionary objectForKey:key];
if(obj != nil){
dic = [[NSMutableDictionary alloc] initWithDictionary:obj];
}
return dic;
}
-(NSArray *)allKeys{
__block NSArray* arr = nil;
dispatch_barrier_sync(isolationQueue_, ^{
if( _myDictionary != nil ){
arr = [_myDictionary allKeys];
}
});
return arr;
}
- (NSString *)getDocPath{
return docPath;
}
- (id)get:(NSString *)key{
__block id _obj = nil;
dispatch_barrier_sync(isolationQueue_, ^{
_obj = [_myDictionary objectForKey:key];
});
return _obj;
}
- (NSString *)getString:(NSString *)key{
__block NSString* returnStr = @"";
dispatch_barrier_sync(isolationQueue_, ^{
if([_myDictionary objectForKey:key]==nil){
returnStr = @"";
}
if([[_myDictionary objectForKey:key] isKindOfClass:[NSString class]]){
returnStr = [_myDictionary objectForKey:key];
}else{
returnStr = @"";
}
});
return returnStr;
}
- (BOOL)getBool:(NSString*)key{
__block BOOL flag = false;
dispatch_barrier_sync(isolationQueue_, ^{
if([_myDictionary objectForKey:key]==nil){
flag = NO;
}
if([[_myDictionary objectForKey:key] isKindOfClass:[NSNumber class]]){
NSNumber* boolValue = [_myDictionary objectForKey:key];
if([boolValue boolValue] == YES){
flag = YES;
}else{
flag = NO;
}
}else{
flag = NO;
}
});
return flag;
}
- (NSMutableArray *)getMutableArray:(NSString *)key{
__block NSMutableArray* _arr = nil;
dispatch_barrier_sync(isolationQueue_, ^{
_arr = [_myDictionary objectForKey:key];
});
return _arr;
}
- (BOOL)has:(NSString *)key{
__block BOOL flag = false;
dispatch_barrier_sync(isolationQueue_, ^{
if([_myDictionary objectForKey:key] != nil){
flag = true;
}else{
flag = false;
}
});
return flag;
}
// #########################
// save function
int flagTest = 0;
bool mark = 0;
NSTimer* saveTimer = nil;
-(void)saveAsync{
@try {
[BSDebugger log:[NSString stringWithFormat:@"_weakDictionaryRef : %@ ",_weakDictionaryRef ]];
if( _myDictionary != nil ){
if( _weakDictionaryRef != nil ){
NSDictionary * _dictionary = nil;
_dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
(__bridge CFPropertyListRef)(_myDictionary),
kCFPropertyListImmutable));
@try{
flagOnSave = true;
UIBackgroundTaskIdentifier taskID = [myappCore beginBackgroundUpdateTask];
flagWrite = false;
NSString* orgPath = [[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath ];
@try {
if( _dictionary != nil ){
[_dictionary writeToFile:orgPath atomically:YES];
}
}@catch (NSException *exception) {
[BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exception callStackSymbols]]];
}@finally {
}
flagWrite = true;
flagOnSave = false;
[myappCore endBackgroundUpdateTask:taskID];
}@catch (NSException *exceptionMain) {
[BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exceptionMain callStackSymbols]]];
}@finally {
_dictionary = nil;
}
return;
// });
}
}
}@catch (NSException *exception) {
}@finally {
// [_dicLock unlock];
}
}
@end
一些想法:
打开僵尸 (How to enable NSZombie in Xcode)。执行此操作时,您将获得有关导致崩溃的对象的更多信息。
如果你能随意让错误发生,在saveAsync
的顶部设置一个断点并逐步执行它。
以某种方式更改 stringWithFormat
调用,使它们不引用任何可能被释放的内容,然后查看问题是否消失。如果是这样,您就会知道是什么原因造成的。
我发现有时覆盖我怀疑的对象中的 retain
和 release
并打印一些东西或设置一个断点,这样我就可以看到谁可能过度释放了一个对象。