由于 NSDictionary 自动释放,应用程序在 iOS7 中崩溃,但在 8 和 9 中没有
Posted
技术标签:
【中文标题】由于 NSDictionary 自动释放,应用程序在 iOS7 中崩溃,但在 8 和 9 中没有【英文标题】:App crashes in iOS7 but not in 8 &9 due to NSDictionary autorelease 【发布时间】:2016-07-29 06:40:40 【问题描述】:+ (NSString *)getValueforLocale:(NSString*) i18nkey :(NSString*)locale
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSLog(@"paths are : %@",paths);
NSString *libraryDirectory = [paths objectAtIndex:0];
NSLog(@"libraryDirectory : %@",libraryDirectory);
NSString *filePath = [libraryDirectory stringByAppendingPathComponent:@"I8nDB"];
filePath = [filePath stringByAppendingPathComponent:locale];
NSLog(@"file path is : %@",filePath);
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if(fileExists)
NSDictionary *dict = [[[NSDictionary alloc] initWithContentsOfFile:filePath]autorelease];
NSDictionary *resourceBundle = [[[NSDictionary alloc] init]autorelease];
NSString *keyValue = [[[NSString alloc]init]autorelease];
resourceBundle = [dict valueForKey:@"hash"];
keyValue=[resourceBundle valueForKey:i18nkey];
NSLog(@"value for %@ is(container) : %@",i18nkey,keyValue);
if(keyValue != nil || keyValue != NULL)
return keyValue;
else
NSLog(@"key not found in the container file");
NSString *path = [[NSBundle mainBundle] pathForResource:@"Localizable"
ofType:@"strings"
inDirectory:nil
forLocalization:locale];
NSLog(@"path for %@ is : %@",locale,path);
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
if(fileExists)
NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
NSLog(@"value for %@ is(resources) : %@",i18nkey,[dict objectForKey:i18nkey]);
return [dict objectForKey:i18nkey];
else
return NULL;
else
NSLog(@"%@ locale does not exist in container",locale);
NSString *path = [[NSBundle mainBundle] pathForResource:@"Localizable"
ofType:@"strings"
inDirectory:nil
forLocalization:locale];
NSLog(@"path for %@ in resources is : %@",locale,path);
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
if(fileExists)
NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
NSLog(@"value for %@ is : %@",i18nkey,[dict objectForKey:i18nkey]);
return [dict objectForKey:i18nkey];
else
return NULL;
如果我们从上面的代码中删除 Autorelease,如果不是应用程序崩溃,它可以在 ios7 中工作
我主要担心的是为什么它不会在 iOS8 和 9 中崩溃而只会在 iOS7 中崩溃 这些版本是否有与自动发布相关的变化
【问题讨论】:
问题代码可以在一个iOS版本中运行而不在其他版本中运行是正常的。因为 Apple 会在每个发行说明中更改系统。所以只有没有问题的代码才能在所有 iOS 中运行 【参考方案1】:为什么不使用 ARC?那么你就不需要autorelease
...
见http://rypress.com/tutorials/objective-c/memory-management
您的问题可能与ARC的设置有关。
【讨论】:
【参考方案2】:在您的代码中,您只分配一个字典
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];
所以你只需要关心它,另一个对象不属于你!所以你不需要释放或自动释放它们。
尝试流动代码
+ (NSString *)getValueforLocale:(NSString*) i18nkey :(NSString*)locale
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSLog(@"paths are : %@",paths);
NSString *libraryDirectory = [paths objectAtIndex:0];
NSLog(@"libraryDirectory : %@",libraryDirectory);
NSString *filePath = [libraryDirectory stringByAppendingPathComponent:@"I8nDB"];
filePath = [filePath stringByAppendingPathComponent:locale];
NSLog(@"file path is : %@",filePath);
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filePath];
if(fileExists)
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:filePath];
//NSDictionary *resourceBundle = [[[NSDictionary alloc] init]autorelease];
//NSString *keyValue = [[[NSString alloc]init]autorelease];
NSDictionary *resourceBundle = [dict valueForKey:@"hash"];
// relese dict here because not use after
[dict release];
NSString *keyValue=[resourceBundle valueForKey:i18nkey];
NSLog(@"value for %@ is(container) : %@",i18nkey,keyValue);
if(keyValue != nil || keyValue != NULL)
return keyValue;
else
NSLog(@"key not found in the container file");
NSString *path = [[NSBundle mainBundle] pathForResource:@"Localizable"
ofType:@"strings"
inDirectory:nil
forLocalization:locale];
NSLog(@"path for %@ is : %@",locale,path);
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
if(fileExists)
// NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSLog(@"value for %@ is(resources) : %@",i18nkey,[dict objectForKey:i18nkey]);
return [dict objectForKey:i18nkey];
else
return NULL;
else
NSLog(@"%@ locale does not exist in container",locale);
NSString *path = [[NSBundle mainBundle] pathForResource:@"Localizable"
ofType:@"strings"
inDirectory:nil
forLocalization:locale];
NSLog(@"path for %@ in resources is : %@",locale,path);
fileExists = [[NSFileManager defaultManager] fileExistsAtPath:path];
if(fileExists)
// NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSLog(@"value for %@ is : %@",i18nkey,[dict objectForKey:i18nkey]);
return [dict objectForKey:i18nkey];
else
return NULL;
【讨论】:
【参考方案3】:在手动引用计数中,需要平衡保留和释放。
在
NSDictionary *dict = [[[NSDictionary alloc] initWithContentsOfFile:filePath]autorelease];
NSDictionary *resourceBundle = [[[NSDictionary alloc] init]autorelease];
保留和释放是平衡的,因为alloc
(连同retain
、new
、copy
、mutableCopy
)返回一个保留实例,而autorelease
算作release
。
然而,在
NSDictionary *dict = [[NSDictionary dictionaryWithContentsOfFile:path]autorelease];
你有一个过度释放,因为你是 autorelease
一些你没有保留的东西。
iOS版本与此完全无关。
【讨论】:
以上是关于由于 NSDictionary 自动释放,应用程序在 iOS7 中崩溃,但在 8 和 9 中没有的主要内容,如果未能解决你的问题,请参考以下文章