开发者

IPhone: File Upload using dispatch_async for background upload

I want to perform a image upload while the running application at the background. I am able to upload the image to the server using the code on this link. How can I upload a photo to a server with the iPhone?

I heard the NSUrlConnection can be asynchronous and it was used in the EPUploader. In my code, I add some extra method that will create a file in the application directory used for the EPUploader. During this creation of the file, I don't want it to create on the main thread of the application so I wrap all the code including the EPUploader itself with the dispatch_async on the global queue. That way I won't block the main thread while the file are creating.

It has no problem if I use dispatch_sync but dispatch_async I find something weird when I placed the breakpoint at NSUrlConnection connection :

- (void)upload

{

    NSData *data = [NSData dataWithContentsOfFile:filePath];
    //ASSERT(data);
    if (!data) {
            [self uploadSucceeded:NO];
        return;
    }
    if ([data length] == 0) {
        // There's no data, treat this the same as no file.
        [self uploadSucceeded:YES];
        return;
    } /* blah blah */
    NSURLConnection * connection = [[NSURLConnection alloc] initWithRequest:urlRequest delegate:self];

     if (!connection) {
        [self uploadSucceeded:NO];
        return;
    }
    else
        return;

I went to debug at the breakpoint and instead of going to if statement, the debugger jumps to the first return statement of this method. After that, the selectors I passed on to this class never gets called. This happen only on dispatch_async and it work on dispatch_sync on the global queue.

Does anybody know how to solve this issue?

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

dispatch_async(queue, ^{
    NSAutoreleasePool *pool = [[NSAutorele开发者_如何学PythonasePool alloc] init];     

    self.uploadIndex = 0;
    ALAsset *asset = [self.assets objectAtIndex:0];

    [[FileUploader alloc] initWithAsset:[NSURL URLWithString:@"http://192.168.0.3:4159/default.aspx"]
                                  asset:asset
                               delegate:self
                           doneSelector:@selector(onUploadDone:)
                          errorSelector:@selector(onUploadError:)];
    //[self singleUpload:self.uploadIndex];
    [pool release];


});


There are a couple of things that should be changed.

  1. Remove the NSAutoreleasePool, it is not needed.
  2. Copy the block to the heap because it's life will probably exceed that of the calling code.

Example:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

    dispatch_async(queue, [[^{
        self.uploadIndex = 0;
        ALAsset *asset = [self.assets objectAtIndex:0];

        [[FileUploader alloc] initWithAsset:[NSURL URLWithString:@"http://192.168.0.3:4159/default.aspx"]
                                      asset:asset
                                   delegate:self
                               doneSelector:@selector(onUploadDone:)
                              errorSelector:@selector(onUploadError:)];
    } copy] autorelease]);

If you are using ARC (which you certainly are since you should be) there is no need for the copy or autorelease.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜