2011-11-22 46 views
1

我使用iOS的AWS SDK上传和下载本地硬盘上的文件到Amazon S3存储。我有能力完成这项工作,但我无法让S3代表正确响应,以在操作完成或导致错误时提醒我。我想要上传的文件的数组。对于每个文件创建一个NSOperation其中main程序包含较多:使用代理,操作和队列

AmazonCredentials * credentials = [[AmazonCredentials alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY]; 
    putObjectRequest = [[S3PutObjectRequest alloc] initWithKey:pathCopy inBucket:[self bucket]]; 
    putObjectRequest.filename = pathSource; 
    putObjectRequest.credentials=credentials; 
    [putObjectRequest setDelegate:s3Delegate]; 

这里,委托(s3Delegate)作为常规AmazonServiceRequestDelegate这应该是能够当操作完成到断火的反应产生。我的NSOperations中的每一个都被添加到我的NSOperationQueue中,它不同时执行操作。如果我使用代理[putObjectRequest setDelegate:s3Delegate],则操作不起作用。如果我删除委托的使用,则操作正确执行,但由于没有委托,我无法收到对操作的任何响应。

如果我完全删除了NSOperationQueue的使用并使用[putObjectRequest setDelegate:s3Delegate]委托完美地工作。

我的问题是我做错了在队列中使用委托?由于代理完全有能力执行而不在队列中,这可能与不在主线程上执行有关吗?我真的希望能够使用队列来限制非并发操作的数量,但我无法弄清楚这一点。我希望有人知道这里发生了什么,任何示例代码将不胜感激。谢谢! Cheers,Trond

回答

8

看起来aws sdk在你设置委托后的时间表现异步。 因此,为了让您的异步AWS的东西工作的(异步)的NSOperation,你得把一些魔术等待AWS完成:

在您的.h文件的NSOperation,添加一个布尔值:

@interface UploadOperation : NSOperation <AmazonServiceRequestDelegate> { 
    @private 
    BOOL  _doneUploadingToS3; 
} 

,并在您.m文件,你的主要方法是这样的:

- (void) main 
{ 
    .... do your stuff ….. 

    _doneUploadingToS3 = NO; 

    S3PutObjectRequest *por = nil; 
    AmazonS3Client *s3Client = [[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY withSecretKey:SECRET_KEY]; 
    s3Client.endpoint = endpoint; 

    @try { 
     por = [[[S3PutObjectRequest alloc] initWithKey:KEY inBucket:BUCKET] autorelease]; 
     por.delegate = self; 
     por.contentType = @"image/jpeg"; 
     por.data = _imageData; 

     [s3Client putObject:por]; 
    } 
    @catch (AmazonClientException *exception) { 
     _doneUploadingToS3 = YES; 
    } 

    do { 
     [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
    } while (!_doneUploadingToS3); 

    por.delegate = nil; 

    .... continue with your stuff …. 
} 

不要忘记将委派方法

-(void)request:(AmazonServiceRequest *)request didCompleteWithResponse:(AmazonServiceResponse *)response 
{ 
    _doneUploadingToS3 = YES; 
} 

-(void)request:(AmazonServiceRequest *)request didFailWithError:(NSError *)error 
{ 
    _doneUploadingToS3 = YES; 
} 

-(void)request:(AmazonServiceRequest *)request didFailWithServiceException:(NSException *)exception 
{ 
    _doneUploadingToS3 = YES; 
} 

- (void) request:(AmazonServiceRequest *)request didSendData:(NSInteger)bytesWritten totalBytesWritten:(NSInteger)totalBytesWritten totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite 
{ 
    // Do what you want 
} 

-(void)request:(AmazonServiceRequest *)request didReceiveResponse:(NSURLResponse *)response 
{ 
    // Do what you want 
} 

-(void)request:(AmazonServiceRequest *)request didReceiveData:(NSData *)data 
{ 
    // Do what you want 
} 

注意:这个魔法可以适用于任何异步执行但必须在NSOperation中执行的东西。

+0

谢谢!它完美地与你的建议。这似乎是使这项工作的诀窍是:'do {[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];} while(!_doneUploadingToS3);'我试图运行没有此代码段的操作,它不工作。当我包含它时,代表无缝地工作。你能向我解释为什么这段代码如此重要以及它做了什么?再次感谢!。欢呼声,Trond –

+1

此循环等待_doneUploadingToS3设置为YES。在此之前它会循环(尽管你的CPU不会超载)。 当AWS SDK的某个完成方法被触发时,_doneUploadingToS3被设置为YES,并且执行主方法的其余部分。 – romrom

+0

非常感谢!这正是我的问题。标签:AmazonServiceRequestDelegate无法正常工作Nsoperation nsoperationqueue – Jords