0

iOS での GCD とキューの組み合わせについては、ほとんど疑問がありません。それらをここに入れさせてください

初め。IOS6 プログラミング クックブックによると、非同期と同期を使用して画像をダウンロードするための小さなコード スニペットを次に示します。以下のように

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);dispatch_async (concurrentQueue, ^ {
UIImage *image = nil;
dispatch_sync(concurrentQueue, ^ { /* download image here */ });
dispatch_sync(dispatch_get_main_queue, ^ { /* show the downloaded image here */ });
});

2番。Url からいくつかの画像をダウンロードする必要がありますが、ダウンロードされた画像の数を示す進行状況ビューを更新する必要があります。だから私は次のコードスニペットを使用しています

dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async (concurrentQueue, ^ { dispatch_sync(dispatch_get_main_queue, ^ { /* download image here and update progress view here */ });
});

メインスレッドの進行状況ビューを更新していることに注意してください。しかし、すべての画像がダウンロードされた後、進行状況ビューが表示されます。私は他のリンクをチェックしましたが、答えがはっきりしていませんでした.問題の理由がわかりません. 私のコードは以下の通りです。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{dispatch_sync(dispatch_get_main_queue(), ^{
       alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
       prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
       prgView.frame = CGRectMake(10, 50, 270, 20);
       [alert addSubview:prgView];
       [alert show];
      prgView.progress=0.0;
       actual= 0.0;

       for(NSInteger i=0; i<[fileLinks count];i++)
       {

        //  [self downLoadFileFromUrl : fileLinks[i]: i ];
           NSLog(@"Url is %@", fileLinks[i]);
           NSLog(@"i value is %d", i);
           NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
           NSString * _filename=  [fileLinks[i] lastPathComponent];
           NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
           [filePath appendString: _filename] ;
           [imagedata writeToFile: filePath atomically:YES];
           prgView.progress =((float) i /([fileLinks count]));
           NSLog(@" progress value is %f", prgView.progress);

       }
   });
});

ここで何が問題なのですか?私のもう1つの疑問は、長い処理タスクの実行中にユーザーを保持したい場合(進行状況ビューまたはアクティビティインジケーターを表示する)、メインスレッドでそれを行うことはできませんか? (プログレスバーまたはアクティビティインジケーターが表示されている場合)、非同期、同時スレッドまたはメインスレッドとの同期などの組み合わせを使用する必要がある理由など.

そして、どのシナリオで、非同期、同期、メインキュー、同時キュー、シリアルキューの適切な組み合わせを使用しなければならなかったのか、少し混乱しています。誰かが私に説明してくれるか、理解するための良いリンクを提供してくれたら async 、 sync 、および 3 つのキューの組み合わせ。それは素晴らしい。

4

3 に答える 3

2

メインキューで「UIProgressView」を作成して更新する必要があります

別のキュー(メインキューではない)で作業を行います

また、作業中に GUI 上のオブジェクトを更新する場合は、メイン キューで行う必要があります。

次のようにできます。

alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
    prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
    prgView.frame = CGRectMake(10, 50, 270, 20);
    [alert addSubview:prgView];
    [alert show];
    prgView.progress=0.0;
    actual= 0.0;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        for(NSInteger i=0; i<[fileLinks count];i++)
        {
            //  [self downLoadFileFromUrl : fileLinks[i]: i ];
            NSLog(@"Url is %@", fileLinks[i]);
            NSLog(@"i value is %d", i);
            NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
            NSString * _filename=  [fileLinks[i] lastPathComponent];
            NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
            [filePath appendString: _filename] ;
            [imagedata writeToFile: filePath atomically:YES];

            dispatch_async(dispatch_get_main_queue(), ^{
                prgView.progress =((float) i /([fileLinks count]));
            });
            NSLog(@" progress value is %f", prgView.progress);
        }
    });

電子ブックを読むことができます: "Pro.Multithreading.and.Memory.Management.for.iOS.and.OS.X" (購入または gg に問い合わせてください)

幸運を!

于 2013-07-29T10:03:04.710 に答える
0

コードをよく見ると、実際にはすべてメイン スレッドで実行されていることがわかります。

^{dispatch_sync(dispatch_get_main_queue(), ^{
       alert = [[UIAlertView alloc] initWithTitle:@"Please Wait Downloading reports..." message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil] ;
       prgView = [[UIProgressView alloc]initWithProgressViewStyle:UIProgressViewStyleBar];
       prgView.frame = CGRectMake(10, 50, 270, 20);
       [alert addSubview:prgView];
       [alert show];
      prgView.progress=0.0;
       actual= 0.0;
       for(NSInteger i=0; i<[fileLinks count];i++)
       {

        //  [self downLoadFileFromUrl : fileLinks[i]: i ];
           NSLog(@"Url is %@", fileLinks[i]);
           NSLog(@"i value is %d", i);
           NSData *imagedata = [NSData dataWithContentsOfURL:[NSURL URLWithString:fileLinks[i]]];
           NSString * _filename=  [fileLinks[i] lastPathComponent];
           NSMutableString *filePath = [[NSMutableString alloc] initWithFormat:@"%@", [VSCore getTempFolder]];
           [filePath appendString: _filename] ;
           [imagedata writeToFile: filePath atomically:YES];
           prgView.progress =((float) i /([fileLinks count]));
           NSLog(@" progress value is %f", prgView.progress);

       }
   });

これにより、メイン スレッドで downloadFileFromUrl と進行状況ビューの更新が実行されます (downloadFileFromUrl が非同期操作でない限り、これはわかりません)。

基本的に、セカンダリ スレッドで downloadFileFromUrl メソッドを実行する必要があります。次に、メイン スレッドでこのビットのみを実行します。

于 2013-07-29T09:26:34.903 に答える