views:

1077

answers:

2

Apologies in advanced for my confusion.

I'm trying to do a batch upload of photos in my iPhone application. I have one script that's looping through a user's photos, and then for each photo, calls another script to do the upload. The script that does the upload needs to call back the script that's firing off each of the user's photos to signal success or failure. It's kind of weird, but it's like I need to be able to get the blocking feature of a synchronous call within the loop, but at the same time, the upload script is asynchronous. The code is very involved so I'll try to use pseudocode:

Script one:

foreach (photoNeedsUpload in users photos)

       upload the photo via Upload Script

callback hook: successOrFailureUploading (called back by the Upload Script)

Upload Script:

    1. Do the upload and then wait for NSURLRequest callbacks: 

    connectionDidFinishLoading, didFailWithError, etc., etc.

    2. Upon getting called back, in turn:
call back Script One appropriately with success/failure signal

My issue is that I'd like to have the asynchronous callbacks so I can check the upload status, but I really need to block for each photo and wait for it to get uploaded. Is there a simple way to do something like this? Should I be putting the thread to sleep, or should I just make the http call synchronous? If so, how to check for success?

I admit that I didn't do my design homework and it's starting to feel like I've created a circular issue for myself!

+2  A: 

Well, yeah, sure you can. Just add a flag, say a semaphore, to the caller; make it wait on that flag.

Clear the flag in the callback. Boom, there you are.

The question is: why? Why go to all that trouble; instead just start the process synchronously. Then you don't need a callback.

The problem in both cases is that when you start waiting, your process will apparently hang -- no UI events, no raise-lower, all that stuff. This strikes me as likely undesirable.

You sure you wouldn't rather just have the callback set a flag to tell you the work is done, and come back around to it?

You might look into the Asynchronous Completion Token pattern, too.

Charlie Martin
Went with your first suggestion which is working fine for me, and just called:[NSURLConnection sendSynchronousRequest:req returningResponse: Thanks for the ideas Charlie!
Rob
+1  A: 

I needed to do something similar. I wanted an synchronous download, but needed some of the methods of the asynchronous download (specifically handling authorisation).

I did it like this

-(BOOL)getDataSynchronouslyFromAddress:(NSString*)address
{
    if (downloadRunning)
    {
     return NO;
    }

    downloadRunning=YES;
    downloadSucceeded=NO;

    NSURLConnection *connection=[self startConnectionWithAddress:address];
    if (!connection)
    {
     NSLog(@"no connection");
     downloadRunning=NO;
    }

    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    while (downloadRunning && [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]);

    return downloadSucceeded;
}

when the download has finished, I just set the downloadSucceeded appropriately, and set downloadRunning to NO.

Rob