NSFileManager 和 NSDirectoryEnumerator 崩溃?
Posted
技术标签:
【中文标题】NSFileManager 和 NSDirectoryEnumerator 崩溃?【英文标题】:NSFileManager and NSDirectoryEnumerator Crash? 【发布时间】:2011-03-09 21:24:04 【问题描述】:下面的代码在walker = [fileManager enumeratorAtPath:directory];
崩溃。代码在第一次调用 refresh
时执行正常,但在第二次(和后续)调用时崩溃。
关于我可能做错了什么有什么想法吗?
- (void)refresh
NSString* directory = nil;
NSFileManager* fileManager = nil;
NSDirectoryEnumerator* walker = nil;
if(files == nil)
files = [[NSMutableArray alloc] init];
else
[files removeAllObjects];
ASSERT(files != nil);
if(files == nil) goto EARLY_EXIT;
fileManager = [[NSFileManager alloc] init];
ASSERT(fileManager != nil);
if(fileManager == nil) goto EARLY_EXIT;
directory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
ASSERT(directory != nil);
if(directory == nil) goto EARLY_EXIT;
ASSERT(directory != nil);
walker = [fileManager enumeratorAtPath:directory];
ASSERT(walker != nil);
if(walker == nil) goto EARLY_EXIT;
NSString* file;
while((file = [walker nextObject]) != nil)
BOOL isDirectory = YES;
if([fileManager fileExistsAtPath:file isDirectory:&isDirectory] && !isDirectory)
[files addObject:file];
EARLY_EXIT:
//if(walker != nil)
// [walker release];
if(fileManager != nil)
[fileManager release];
//if(directory != nil)
// [directory release];
【问题讨论】:
请,请,请不要使用 goto! (说真的……阅读一下这个!) 不敢相信,25 年后,我再次面临 goto 的邪恶!见鬼,我什至不知道你可以在 Objective-C 中做到这一点。虽然,它确实解释了当我在 Apple 工作时,他们在火刑柱上烧死了一个人。 > 25 年后我不敢相信我再次面临 goto 的邪恶。我在 30 多年前就学会了——旧习惯很难改掉。 你看到什么样的崩溃?您是否已验证NSHomeDirectory()
每次都返回您期望的结果?
【参考方案1】:
事实证明,在 ios 和 10.5 及更高版本中,您不应再使用[NSFileManager defaultManager]
。使用 Cocoa 近 15 年,我在这个问题上咬了一口。我会把它留给其他人的警告 -- TechZen
尽管您在这段代码中犯下了许多违背良好编程习惯的罪过,但您真正的问题在这里:
fileManager = [[NSFileManager alloc] init];
NSFileManger 在每个应用程序中都是一个单例。你永远不会自己初始化它。获取单例的正确方法是:
fileManager=[NSFileManager defaultManager];
... 返回单例。但是,您通常不会为属性或变量而烦恼,而只是这样使用它:
walker = [[NSFileManager defaultManager] enumeratorAtPath:directory];
你知道你不应该在发布代码中使用断言,对吧?
【讨论】:
> 尽管有许多不利于良好编程实践的罪过。我会认为你也不关心 goto 的。就个人而言,我真的不关心样式,只要所有返回值都被断言和检查。 > NSFileManger 在每个应用程序中都是一个单例。您永远不会自己初始化 > 它。获取单例的正确方法是: > fileManager=[NSFileManager defaultManager];嗯...我读过的 Apple 文档指出defaultManager
不是线程安全的,应该使用 [[NSFileManager alloc] init]
。
@noloader -- 哈!你说得对,文档现在说不要在 iOS 和 10.5 及更高版本中使用 [NSFileManager defaultManager]
。我被旧知识烧伤了。看来你不是唯一一个有旧习惯的人。现在,我必须回去修复一些代码,很多代码。
@noloader -- *** 不允许 cmets 中的段落格式。只是粗体、斜体、代码和链接(都是内联的。)【参考方案2】:
我发现了同样的崩溃。在 iOS 4.3 中崩溃,但在 5.0 中运行良好。哈哈。我通过代码重构以使用字符串枚举器而不是 url 枚举器:
NSFileManager* localFileManager = [[NSFileManager alloc] init];
NSDirectoryEnumerator* enumerator = [localFileManager enumeratorAtPath:path];
for (NSString* file in enumerator)
// do stuff...
祝你好运。 (并摆脱那些 goto)。
【讨论】:
以上是关于NSFileManager 和 NSDirectoryEnumerator 崩溃?的主要内容,如果未能解决你的问题,请参考以下文章