[英]connectionDidFinishLoading - how to force update UIView?
我可以從互聯網上下載ZIP文件。 后處理是在connectionDidFinishLoading中完成的,除了沒有更新UIView元素外,其他方法都可以正常工作。 例如,我設置了statusUpdate.text = @“解壓縮文件”,但是直到connectionDidFinishLoading完成后,該更改才會出現。 同樣,在該方法結束之前,不會更新UIProgressView和UIActivityIndicatorView對象。
有什么方法可以從此方法中強制更新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.