我正在使用FSCopyObjectAsync
跨卷复制文件。我已经使用cimgf的代码让我走了,它工作得很好。在后台线程上不会调用FSCopyObjectAsync回调方法
我最近遇到的问题之一是复制状态回调不会发生在后台线程上。当我没有通过dispatch_async(copyQueue, ^{
开始复制操作时,回调得到完美调用。当我将它移动到背景时,它不会触发。这里是代码:
//Excerpt from existing method
// Create the semaphore, specifying the initial pool size
fd_sema = dispatch_semaphore_create(1);
dispatch_queue_t copyQueue = dispatch_queue_create("copy.theQueue", 0);
dispatch_group_t group = dispatch_group_create();
for(SearchPath * p in searchPaths) {
dispatch_async(copyQueue, ^{
NSString * newDestination = [NSString stringWithFormat:@"%@%@",destination,p.relativePath];
NSString * source = [NSString stringWithFormat:@"%@%@",p.basePath,p.relativePath];
NSError * error = nil;
//Wait until semaphore is available
dispatch_semaphore_wait(fd_sema, DISPATCH_TIME_FOREVER);
//Update progress window text
[progressview.label setStringValue:[NSString stringWithFormat:@"Copying \"%@\" to \"%@\"",[source lastPathComponent],[destination lastPathComponent]]];
if(p.isDirectory) {
BOOL result = [[NSFileManager defaultManager] createDirectoryAtPath:newDestination withIntermediateDirectories:NO attributes:nil error:nil];
if(result) {
//Item was a directory
dispatch_semaphore_signal(fd_sema);
}
}else{
[self startCopy:source dest:[newDestination stringByDeletingLastPathComponent]];
}
if(error) {
MTLogDebug(@"Error! : %ld", error.code);
}
}); //End async
} //End for loop
//End excerpt
- (void)startCopy:(NSString *)source dest:(NSString *) destination
{
// Get the current run loop and schedule our callback
//TODO:Make this work while on a background thread
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
FSFileOperationRef fileOp = FSFileOperationCreate(kCFAllocatorDefault);
OSStatus status = FSFileOperationScheduleWithRunLoop(fileOp, runLoop, kCFRunLoopDefaultMode);
if(status)
{
NSLog(@"Failed to schedule operation with run loop: %@", status);
return;
}
// Create a filesystem ref structure for the source and destination and
// populate them with their respective paths from our NSTextFields.
FSRef sourceRef;
FSRef destinationRef;
//FSPathMakeRef((const UInt8 *)[source fileSystemRepresentation], &sourceRef, NULL);
FSPathMakeRefWithOptions((const UInt8 *)[source fileSystemRepresentation],
kFSPathMakeRefDefaultOptions,
&sourceRef,
NULL);
Boolean isDir = true;
//FSPathMakeRef((const UInt8 *)[destination fileSystemRepresentation], &destinationRef, &isDir);
FSPathMakeRefWithOptions((const UInt8 *)[destination fileSystemRepresentation],
kFSPathMakeRefDefaultOptions,
&destinationRef,
&isDir);
// Start the async copy.
status = FSCopyObjectAsync (fileOp,
&sourceRef,
&destinationRef, // Full path to destination dir
NULL, // Use the same filename as source
kFSFileOperationDefaultOptions,
statusCallback,
0.1,
NULL);
NSLog(@"Stat: %d",status);
CFRelease(fileOp);
if(status) {
NSLog(@"Failed to begin asynchronous object copy: %d", status);
}
}
static void statusCallback (FSFileOperationRef fileOp,
const FSRef *currentItem,
FSFileOperationStage stage,
OSStatus error,
CFDictionaryRef statusDictionary,
void *info)
{
if (statusDictionary) {
NSNumber *bytesCompleted = (__bridge NSNumber *) CFDictionaryGetValue(statusDictionary, kFSOperationBytesCompleteKey);
NSURL *url = (__bridge NSURL *)convertedURLRef;
if([bytesCompleted intValue] > 0) {
if(stage == kFSOperationStageRunning) {
//Update progress indicator
[progressview.indicator setDoubleValue:progressview.indicator.doubleValue + [newNumberValue floatValue]];
}
}
}
if (stage == kFSOperationStageComplete) {
dispatch_semaphore_signal(fd_sema);
}
}
任何帮助或洞察力的赞赏!
请显示代码的其余部分,包括您在哪里进行dispatch_async调用以及运行后台线程运行循环的代码。 – 2012-04-24 22:04:44
@PeterHosey好主意。刚添加完整的代码。谢谢 – Westley 2012-04-24 22:43:34