此代码似乎不时导致分段错误:
[[NSFileManager defaultManager] performSelectorOnMainThread:@selector(removeItemAtPath:error:) withObject:filePath waitUntilDone:YES];
我想对主线程中的文件执行所有操作,以避免在整个文件夹被迭代时删除文件等冲突。
它产生了这个错误:
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0x1084
Application Specific Information:
objc_msgSend() selector name: release
这是崩溃主线程的堆栈跟踪:
Thread 0 Crashed:
0 libobjc.A.dylib 0x39fc8636 objc_msgSend + 22
1 Foundation 0x30214c67 __NSThreadPerformPerform + 452
2 CoreFoundation 0x2f7f6fef __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
3 CoreFoundation 0x2f7f64b7 __CFRunLoopDoSources0 + 204
4 CoreFoundation 0x2f7f4ca7 __CFRunLoopRun + 628
5 CoreFoundation 0x2f75f769 CFRunLoopRunSpecific + 522
6 CoreFoundation 0x2f75f54b CFRunLoopRunInMode + 104
7 GraphicsServices 0x346bc6d3 GSEventRunModal + 136
8 UIKit 0x320be891 UIApplicationMain + 1134
9 Pocket3 0x00050243 main (main.m:4)
10 libdyld.dylib 0x3a4bcab7 start + 0
我做错了什么?
看起来NSFileManager过早地被释放了,但如果它是单身,怎么会这样呢? 它是否与方法[NSFileManager defaultManager]有关,据说这不是线程安全的?
答案 0 :(得分:1)
NSFileManager
是线程安全的(只要你没有使用它的委托,你不使用它,你不应该使用-defaultManager
)。您可以在当前所在的任何线程上调用[[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]
。仅在主线程上执行它没有任何优势。实际上,如果在后台线程中更新文件系统,性能可能会更好,因为如果操作的时间超过预期,UI将不会阻塞。
方法-removeItemAtPath:error:
需要两个对象,但您只提供一个。因此-removeItemAtPath:error:
方法将看到的第二个参数(NSError **)只是内存中filePath
指针旁边的一些垃圾。
没有-performSelectorOnMainThread:...
的版本需要两个对象。您可以改为使用dispatch_sync
:
dispatch_sync(dispatch_get_main_queue(), ^() {
NSError *error = nil;
BOOL ok = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error];
if(!ok) {
NSLog(@"an error happened: %@", error);
}
}