簡體   English   中英

如何在異步線程中更新ProgressView

[英]How To Update ProgressView in Async Thread

在iOS中,我對GCD和隊列的組合幾乎沒有疑問。 讓我把這些放在這里

第一。 根據IOS6編程cookbook,這里是使用異步和同步下載圖像的小代碼片段。 及其如下

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 */ });
});

第二。 我需要從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);

       }
   });
});

那么這里有什么問題? 而另一個疑問是,如果任何人想要在執行長處理任務時持有用戶(顯示進度視圖或活動指示符),他們不能在主線程中這樣做嗎? (如果他們正在顯示進度條或活動指示符),為什么我們必須使用異步,同步和並發線程或主線程等的組合等。

我有點困惑,因為我必須使用異步,同步,主隊列,並發隊列,串行隊列的正確組合。 如果任何一個給我解釋我或提供了良好的鏈接,了解異步,同步和3隊列的組合。 那挺棒的。

您應該在主隊列上創建和更新“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)

祝好運!

異步和同步的組合是正確的,但主線程和其他線程的組合導致循環,特別是在使用同步主線程的異步線程中。

如果你仔細看看你的代碼,你會注意到你實際上正在運行主線程中的所有內容。

^{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方法,然后只在主線程上運行這個位:prgView.progress =((float)i /([fileLinks count]));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM