Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7848259
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 2, 20262026-06-02T18:08:23+00:00 2026-06-02T18:08:23+00:00

I am using FSCopyObjectAsync to copy files across volumes. I have used the code

  • 0

I am using FSCopyObjectAsync to copy files across volumes. I have used the code from the cimgf to get me going and it is working pretty well.

One of the last issues I am getting hung up on is that the copy status callback isn’t occurring on a background thread. When I don’t start the copy operation by dispatch_async(copyQueue, ^{, the callback gets called perfectly. When I move it to the background, it won’t fire. Here is the code:

//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);
    }
}

Any help or insight is appreciated!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-02T18:08:24+00:00Added an answer on June 2, 2026 at 6:08 pm

    The problem is that you’re using this with dispatch_async, but FSCopyObjectAsync ties the copy operation callbacks to a specific runloop, and thus a specific thread.

    What you need to do is not use dispatch_async, but either:

    1. perform the copy operation on the main thread (which should probably be OK, in the same way that executing an NSURLConnection on the main thread is OK)
    2. spin off a secondary NSThread, schedule the operation on that thread, and then start the runloop running by calling [[NSRunLoop currentRunLoop] run] (or the appropriate variant).
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Using Rails 3.2.0.rc2 and ruby 1.9.3p0 In app/views/requests/_form.html.erb I have the following code for
Using Android 2.1+. I have a service that gets killed from time to time
Using of mobile dialog authentication is working well for other mobile devices except on
Using android 2.3.3, I have a background Service which has a socket connection. There's
Using the HTML5 File API I can get the Binary String representation of a
Using NSDateComponents I know how to get the day component, but this gives me
Using mercurial, I've run into an odd problem where a line from one committer
Using MVC2 I have an AJAX form which is posting to a bound model.
Using php/html, I want to retrieve email addresses (plus other information) from MySQL and
Using Core Data, I have a fetch request to fetch the minimum of a

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.