簡體   English   中英

connectionDidFinishLoading-如何強制更新UIView?

[英]connectionDidFinishLoading - how to force update UIView?

我可以從互聯網上下載ZIP文件。 后處理是在connectionDidFinishLoading中完成的,除了沒有更新UIView元素外,其他方法都可以正常工作。 例如,我設置了statusUpdate.text = @“解壓縮文件”,但是直到connectionDidFinishLoading完成后,該更改才會出現。 同樣,在該方法結束之前,不會更新UIProgressView和UIActivityIndi​​catorView對象。

有什么方法可以從此方法中強制更新UIView嗎? 我嘗試設置[self.view setNeedsDisplay],但是沒有用。 它似乎正在主線程中運行。 此處的所有其他命令都可以正常工作-唯一的問題是更新UI。

謝謝!

更新:這是不更新UIVIEW的代碼:

-(void)viewWillAppear:(BOOL)animated {
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(processUpdate:) userInfo:nil repeats:YES];
    downloadComplete = NO;
    statusText.text = @"";

}

-(void)processUpdate:(NSTimer *)theTimer {
    if (! downloadComplete) {
        return;
    }

    [timer invalidate];
    statusText.text = @"Processing update file."; 
    progress.progress = 0.0;
        totalFiles = [newFiles count];
    for (id fileName in newFiles) {
        count++;
            progress.progress = (float)count / (float)totalFiles;
        // ... process code goes here ...
         }
}

在processUpdate結束時,我設置downloadComplete = YES。 此程序可以正常構建和運行,並且可以按預期工作,除非在processUpdate完成之前UIVIEW中沒有任何更新,然后所有內容都立即更新。

感謝您一直以來的幫助!

正如Niels所說,如果要查看視圖更新,必須將控制權返回到運行循環。 但是除非確實需要,否則不要開始分離新線程。 我推薦這種方法:

- (void)connectionDidFinishLoading:(NSConnection *)connection {
    statusUpdate.text = @"Uncompressing file";
    [self performSelector:@selector(doUncompress) withObject:nil afterDelay:0];
}

- (void)doUncompress {
    // Do work in 100 ms chunks
    BOOL isFinished = NO;
    NSDate *breakTime = [NSDate dateWithTimeIntervalSinceNow:100];
    while (!isFinished && [breakTime timeIntervalSinceNow] > 0) {
        // do some work
    }
    if (! isFinished) {
        statusUpdate.text = // here you could update with % complete
        // better yet, update a progress bar
        [self performSelector:@selector(doUncompress) withObject:nil afterDelay:0];
    } else {
        statusUpdate.text = @"Done!";
        // clean up
    }
}

基本思想是您要一小塊地工作。 您從方法中返回以允許運行循環定期執行。 對performSelector:的調用將確保控件最終返回到您的對象。

請注意,這樣做的風險是用戶可能會以您意想不到的方式按下按鈕或與UI交互。 在工作時調用UIApplication的beginIgnoringInteractionEvents來忽略輸入可能會有所幫助...除非您想變得非常好並提供一個cancel按鈕來設置一個用於檢查doUncompress方法的標志...

您也可以嘗試自己運行運行循環,每[[NSRunLoop currentRunLoop] runUntilDate:...]調用一次[[NSRunLoop currentRunLoop] runUntilDate:...] ,但我從未在自己的代碼中嘗試過。

問題原來是UI沒有在for()循環中更新。 請參閱此線程中的答案以獲取簡單的解決方案!

當您處於connectionDidFinishLoading狀態時,應用程序運行循環中不會發生其他任何事情。 控件需要傳遞回運行循環,以便可以協調UI更新。

只需將數據傳輸標記為已完成,並標記要更新的視圖即可。 將下載數據的任何繁重處理推遲到它自己的線程中。

該應用程序將回調您的視圖,使它們稍后在運行循環中刷新其內容。 根據需要在自己的自定義視圖上實現drawRect。

如果您在主線程中收到connectionDidFinishLoading,那么您就不走運了。 除非您從此方法返回,否則UI中不會刷新任何內容。

另一方面,如果在單獨的線程中運行連接,則可以使用以下代碼安全地更新UI:

UIProgressView *prog = ... <your progress view reference> ...
[prog performSelectorOnMainThread:@selector(setProgress:)
                       withObject:[NSNumber numberWithFloat:0.5f]
                    waitUntilDone:NO];

注意不要從非主線程更新performSelectorOnMainThread始終使用performSelectorOnMainThread方法!

完全按照計時器的方式進行操作,只需使用ConnectionDidFinish:將處理代碼分派到新線程即可。 計時器可以從主線程運行,因此可以更新UI。

暫無
暫無

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

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