我FSCopyObjectAsync
用来跨卷复制文件。我已经使用cimgf中的代码让我继续前进,并且运行良好。
我挂断的最后一个问题是复制状态回调没有发生在后台线程上。当我不通过 开始复制操作时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);
}
}
任何帮助或见解表示赞赏!