2011-11-22 45 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