6

私はAmazonS3Clientを使ってputObjectをしようとしています。奇妙なことに、iOSのメインスレッドでputObjectコードを実行した場合にのみ機能するようです。

コードは基本的に次のようになります。

-(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]

私のコード(メインスレッドから外れている)では、ビデオアップロードメソッド全体が実行されます(これを証明するNSLogがいくつかあります)が、ステータスコールバックを取得したり、例外がスローされたり、オブジェクトがバケットに入れられたりすることはありませんS3で。

次のようにメインスレッドでアップロード関数を呼び出すと、次のようになります。

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

進行状況のコールバックを受け取り、すべてが機能し、オブジェクトはS3バケットに正常に配置されます。

putObjectがiOSメインスレッドでのみ機能するかどうか誰かが知っていますか?もしそうなら、それは通常UIスレッドなので、それは残念なことです。

ありがとう、ケビン

PS同じ失敗した結果で非メインスレッドに関数呼び出しをディスパッチしようとしました。

4

5 に答える 5

4

リクエストの送信が完了するとスレッドが終了すると思います。したがって、コールバックには移動するスレッドがありません。スレッドを作成しても、それが永遠に存続することを自動的に意味するわけではありません。タスクが完了すると、タスクは終了し、スレッドプール用に再利用されます。別のスレッドでこれを行うには、実行ループと統合するメソッドを設計する必要があります。Appleドキュメントのスレッドプログラミングガイドにそのセクションがあります。

于 2012-06-04T01:32:17.850 に答える
2

問題は、デリゲートを設定した場合、S3PutObjectRequestが非同期で実行されることです。デリゲートは、現在の実行ループでコールバックを送信します。これは、メインスレッドでは正常に機能しますが、ディスパッチキュースレッドでは機能しません。デリゲートを処理するには、独自の実行ループを開始する必要があります。私はまだこれを管理するための最良の方法を決定しようとしています。

もちろん、魔法のように切り替えるのではなく、単に同期メソッドと非同期メソッドを提供することを望みますが、これはデリゲートプロパティのAmazonServiceRequest.hヘッダーファイルで説明されています。

于 2012-08-10T13:59:40.323 に答える
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は非同期で実行されます。詳細については、こちらをご覧ください。

于 2013-04-12T13:59:12.550 に答える
1

この質問は少し古いことは知っていますが、同じ問題が発生したばかりで、https ://github.com/0i0/iOS-Amazon-S3-upload-serviceから見つけた解決策を共有したいと思いました。

人々が言及しているように、メインスレッドからデータをアップロードするように呼び出す場合は、スレッドが存続していることを確認する必要があります。そのための1つの方法は、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);
}
于 2013-11-25T16:47:43.110 に答える
0

非メインスレッドのs3アップロードに関する洞察に感謝します。アップロードが失敗した場合でもdidCompleteWithResponseトリガーが見つかり、失敗したことを簡単に判断する方法が見つかりませんでした。ObjectPut権限のみでアップロードしようとしているので、プログラムはObjectGetを起動して、ファイルが存在するかどうかを確認できません。

于 2014-04-30T22:02:01.930 に答える