2012-06-04 51 views
6

我想使用AmazonS3Client putObject。奇怪的是,它似乎只能在iOS主线程上运行我的putObject代码时才起作用。AmazonS3Client putObject仅适用于iOS主线程?

的代码基本上是这样的:

-(void)uploadVideoToS3 
{ 
    S3PutObjectRequest * videoPOR = [[S3PutObjectRequest alloc] initWithKey:video.onlineVideoID inBucket:video.onlineVideoBucketName]; 
    videoPOR.contentType = @"video/quicktime"; 
    videoPOR.data  = [NSData dataWithContentsOfURL:video.convertedVideoLocalURL]; 
    videoPOR.delegate = self; 

    // Put the thumbnail and video into the specified s3 
    AmazonS3Client * s3 = [AmazonClientManager s3]; 

    [s3 putObject:videoPOR]; 
    [videoPOR release]; 
} 

桶存在,我的权限等,如果我只需拨打

[self uploadVideoToS3] 

在我的代码(这是关闭主线程) ,整个视频上传方法运行(我有一些NSLogs来证明这一点),但我从来没有得到任何状态回调,没有任何异常抛出,并且该对象永远不会放入S3的桶中。

当我调用主线程上传功能,像这样:

dispatch_async(dispatch_get_main_queue(), ^(void) { 
        [self uploadVideoToS3]; 
       }); 

我得到进步回调,一切正常,并且对象成功投放S3桶。

有谁知道putObject是否只适用于iOS主线程?如果是这样,那将是不幸的,因为它通常是UI线程。

感谢, 凯文

附:我试着调用非主线程上的函数调用,其结果相同。

+0

你用什么代码尝试将它分派给另一个线程? – Pochi

+0

'dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0),^ {[self uploadVideoToS3]});' – kevlar

+0

在AWS网站上发现了一篇有趣的文章。使用dispatch_async可能是问题。不确定,但在这里你去 - >尽量避免在主线程上使用dispatch_sync .http://mobile.awsblog.com/post/Tx1ZZHQHSD0O3SF/Using-the-AWS-SDK-for-iOS-Asynchronously- Part-IV-Grand-Central-Dispatch-GCD-Best –

回答

4

我在想你的线程一旦完成发送请求就终止,因此回调没有线程去。创建一个线程并不意味着它会永远存在。一旦它完成任务,它结束并回收线程池。要在另一个线程上执行此操作,您将不得不设计一个与运行循环集成的方法。 Apple文档中的Threading Programming Guide中有一节。

+0

这是一个很好的观点。我试图通过在上传完成后执行'dispatch_queue_create'然后执行'dispatch_release'来解决这个问题,但是在创建队列后上传不会继续。听起来这仍然是你理论的受害者?我会尝试一些其他方法来通过运行循环来延长线程的生命周期,谢谢。 – kevlar

+1

队列与线程分开。队列将根据系统条件产生任意数量的线程,以完成当前正在处理的块。 – borrrden

+0

我明白了,所以我需要坚持一个线程(NSThread)而不是使用say,NSOperationQueue? – kevlar

2

问题是,如果您设置委托,S3PutObjectRequest实际上是异步运行的。委托在当前运行循环上发送回调,该回调在主线程上正常工作,但不在调度队列线程上。您必须开始自己的运行循环才能处理代表。我仍然在试图决定管理这件事的最佳方式。

当然,我希望他们只是简单地提供同步和异步方法,而不是奇迹般地切换,但这在代理属性的AmazonServiceRequest.h头文件中有解释。

+0

谢谢,我想通过使线程保持运行循环直到上传完成。 – kevlar

2

AmazonS3Client的putObject方法会阻塞主线程。即使我正面临着这个问题。但我发现在S3TransferManager更好的解决方案。

例如代码:

AmazonS3Client * s3 = [AmazonClientManager s3]; 

S3PutObjectRequest * videoPOR = [[S3PutObjectRequest alloc] initWithKey:video.onlineVideoID inBucket:video.onlineVideoBucketName];     
videoPOR.contentType = @"video/quicktime"; 
videoPOR.data = [NSData dataWithContentsOfURL:video.convertedVideoLocalURL]; 

S3TransferManager *manager = [S3TransferManager new]; 
manager.s3 = s3; 
[manager upload:videoPOR]; 

S3TransferManager异步运行。你可以找到更多的信息here

1

我知道这个问题有点旧,但我刚刚遇到同样的问题,并想分享我找到的解决方案:https://github.com/0i0/iOS-Amazon-S3-upload-service

正如人们所提到的,如果您调用主线程上传数据,则需要确保线程保持活动状态。一种方法是使用NSRunLoops。在下面的代码中,我们看到do-while循环将访问当前线程的运行循环,并将持续该线程直到上传完成。

-(void)uploadFileWithData:(NSData *)data 
       fileName:(NSString *)fileName 
       progress:(void (^)(NSInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))progressCallback 
        success:(void (^)(id responseObject))successCallback 
        failure:(void (^)(NSError *error))failureCallback 
{ 

    progress = progressCallback; 
    success = successCallback; 
    failure = failureCallback; 

    _doneUploadingToS3 = NO; 


    AmazonS3Client *s3Client = [[AmazonS3Client alloc] initWithAccessKey:kAWSAccessKeyID withSecretKey:kAWSsecret]; 
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_async(queue, ^{ 

     NSString *pathToFile = [NSString stringWithFormat:@"%@%@",kAWSPath,fileName]; 
     // Upload image data. Remember to set the content type. 
     S3PutObjectRequest *por = nil; 
     por = [[S3PutObjectRequest alloc] initWithKey:pathToFile inBucket:kAWSBucket]; 
     por.cannedACL = [S3CannedACL publicRead]; 
     @try { 

      por.delegate = self; 
      por.contentType = @"image/jpeg"; 
      por.data = data; 

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


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

     por.delegate = nil; 
    }); 

} 

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

感谢您对非主线程s3上传的洞察。即使上传失败,我也发现didCompleteWithResponse触发器,并且没有找到确定失败的简单方法。我只想用ObjectPut权限上传,所以程序无法触发ObjectGet来检查文件是否存在。

相关问题