質問

for (int i=0; i<[array count]; i++)
{
    NSError *error;
    NSArray *ipaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *idocumentsDir = [ipaths objectAtIndex:0];
    NSString *idataPath = [idocumentsDir stringByAppendingPathComponent:@"File"];
    NSLog(@"idataPath:%@",idataPath);

    //Create folder here
    if (![[NSFileManager defaultManager] fileExistsAtPath:idataPath])
    {
        [[NSFileManager defaultManager] createDirectoryAtPath:idataPath withIntermediateDirectories:NO attributes:nil error:&error];
    }
    // Image Download here
    NSString *fileName = [idataPath stringByAppendingFormat:@".jpg"];
    NSLog(@"imagePathDOWNLOAD:%@",fileName);

    _imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[array objectAtIndex:i]]];
    [_imgData writeToFile:fileName atomically:YES];

    tempImg.image = [UIImage imageWithData:_imgData];   
}

このループの進行状況ビューを設定する方法、データをダウンロードするための進行状況ビューを設定したいと思います。 Progressラベル(IE%)だけでなく、小数の割合が必要です。

役に立ちましたか?

解決

簡単な解決策は、これを非同期的に行い、進行状況ビューを更新することです。

  1. 進行状況ビューを作成し、それをあなたのビューに追加します

  2. コードをバックグラウンドキューに派遣します

  3. 各ダウンロードが終了したら、メインキューに戻る進行状況の更新をディスパッチします

擬似コードでは、それはどのようになりますか

UIProgressView *progressView = [[UIProgressView alloc] init];
// configure the progress view and add it to your UI

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    for (int i=0; i<[array count]; i++)
    {
        NSError *error;
        NSArray *ipaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *idocumentsDir = [ipaths objectAtIndex:0];
        NSString *idataPath = [idocumentsDir stringByAppendingPathComponent:@"File"];
        NSLog(@"idataPath:%@",idataPath);

        //Create folder here
        if (![[NSFileManager defaultManager] fileExistsAtPath:idataPath])
        {
            [[NSFileManager defaultManager] createDirectoryAtPath:idataPath withIntermediateDirectories:NO attributes:nil error:&error];
        }
        // Image Download here
        NSString *fileName = [idataPath stringByAppendingFormat:@".jpg"];
        NSLog(@"imagePathDOWNLOAD:%@",fileName);

        _imgData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:[array objectAtIndex:i]]];
        [_imgData writeToFile:fileName atomically:YES];

        // now dispatch any UI updates back to the main queue
        dispatch_async(dispatch_get_main_queue(), ^{

            [progressView setProgress: (CGFloat) (i + 1.0) / [array count] animated:YES];
            tempImg.image = [UIImage imageWithData:_imgData];
        });
    }
});

ますますエレガントなアプローチのシリーズもあります。

  1. コンカレントキューを使用して(上記ではなく、画像を連続的にダウンロードします)、画像をダウンロードします。これは大幅に高速になります。キュー操作を提案するかもしれません maxConcurrentCount5, 、同時性を享受するが、同時リクエストの数のiOS制限を超えないようにしてください。

  2. 使用する NSURLConnectionDataDelegate ではなく、ベースのダウンロード NSData 方法 initWithContentsOfURL, 、個々のダウンロード中に暫定的な進捗を提供できます。見る ダウンロードマネジャー また ダウンロード操作 例えば。

  3. 使用する アフネットワーキング また、ダウンロードProgressブロックベースのインターフェイスも提供します。


上記のポイント1で、私はあなたが同時キューの使用を検討することを提案したので、私はそれをベンチマークすることにしました。私にとって、以下のこのGCDの実装は、 NSOperationQueue それに続く実装。

GCDの実装は次のとおりです。

CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();

UIProgressView *progressView = [self addProgressView];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSInteger downloadSuccessCount = 0;
    NSInteger downloadFailureCount = 0;

    NSString *idataPath = [self createDownloadPath];

    for (int i = 0; i < [array count]; i++)
    {
        // Image Download here
        NSString *filename = [self pathForItem:i array:array folder:idataPath];
        NSURL *url = [self urlForItem:i array:array];
        NSData *data = [[NSData alloc] initWithContentsOfURL:url];
        UIImage *image = nil;
        if (data)
            image = [UIImage imageWithData:data];
        if (image) {
            downloadSuccessCount++;
            [data writeToFile:filename atomically:YES];
        } else {
            downloadFailureCount++;
        }

        // now dispatch any UI updates back to the main queue
        dispatch_async(dispatch_get_main_queue(), ^{

            [progressView setProgress: (CGFloat) (downloadSuccessCount + downloadFailureCount) / [array count] animated:YES];

            // update the image in the UI if you want

            [UIView transitionWithView:self.imageView duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
                tempImg.image = image;
            } completion:nil];
        });
    }

    NSLog(@"Completed in %.1f seconds", CFAbsoluteTimeGetCurrent() - start);
});

これに NSOperationQueue 実装:

CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();

UIProgressView *progressView = [self addProgressView];

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 5;

NSString *idataPath = [self createDownloadPath];
self.downloadSuccessCount = 0;
self.downloadFailureCount = 0;

NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"Completed in %.1f seconds", CFAbsoluteTimeGetCurrent() - start);
}];

for (int i = 0; i < [array count]; i++)
{
    NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        // Image Download here
        NSString *filename = [self pathForItem:i array:array folder:idataPath];
        NSURL *url = [self urlForItem:i array:array];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = nil;
        if (data)
            image = [UIImage imageWithData:data];
        if (image)
            [data writeToFile:filename atomically:YES];

        // now dispatch any UI updates back to the main queue
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{

            if (image) {
                self.downloadSuccessCount++;

                // update the image in the UI if you want, though this slows it down

                [UIView transitionWithView:self.imageView duration:0.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
                    tempImg.image = image;
                } completion:nil];
            }
            else
                self.downloadFailureCount++;

            [progressView setProgress: (CGFloat) (self.downloadSuccessCount + self.downloadFailureCount) / [array count] animated:YES];
        }];
    }];

    [queue addOperation:operation];
    [completionOperation addDependency:operation];
}

[queue addOperation:completionOperation];

あなたが使用する場合、結論 NSOperationQueue (これは同時性を提供するだけでなく、GCDの同時キューでも実行できますが、同時操作の数(ネットワーク操作の場合は5つ以下に制限する必要がある)を簡単に制御できます)大きなパフォーマンスの利点。

さらに良いことに、私が提案したように、アフネットワーキングを採用することです。この操作の並行性の利点だけでなく、他の利点もあります。

他のヒント

[progressView setProgress: (CGFloat) (i + 1.0) / [array count] animated:YES];
self.progressLabel.text = [NSString stringWithFormat:@"%.0f",self.progressView.progress*100];
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top