2012-07-10 68 views
0

我使用這段代碼來顯示一個MBProgressHUD在我的一個視圖的頂部,而我從一個web服務下載數據,唯一的問題是偶爾這個代碼會導致應用程序掛起,HUD顯示「正在下載」並且屏幕被鎖定時什麼都不做。此外,當我按下刷新按鈕,如果我有像鍵盤被顯示給用戶(刷新按鈕進行下載),然後上線的應用程序崩潰:MBProgress HUD崩潰的應用程序reloadData上的tableView

[self.tableView reloadData]; 

我的代碼:

//Checks for network connection then displays HUD while executing pullAndDisplayData method 
- (IBAction) update { 
    UIAlertView *errorView; 

    if([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] == NotReachable) { 
     errorView = [[UIAlertView alloc] 
        initWithTitle: @"Network Error" 
        message: @"No Network connection availible!" 
        delegate: self 
        cancelButtonTitle: @"OK" otherButtonTitles: nil]; 
     [errorView show]; 
    } 
    else 
    { 
     HUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view]; 
     [self.navigationController.view addSubview:HUD]; 

     HUD.delegate = self; 
     HUD.labelText = @"Downloading"; 
     HUD.minSize = CGSizeMake(135.f, 135.f); 

     [HUD showWhileExecuting:@selector(pullAndDisplayData) onTarget:self withObject:nil animated:YES]; 
    } 
} 

//Downloads this users data from the web-service 
- (void) pullAndDisplayData{ 
    // Indeterminate mode 
    ExpensesDataDownloader *downloader = [[ExpensesDataDownloader alloc] init]; 
    [downloader pullAndDisplayData]; 

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    if ([[defaults objectForKey:@"canExportCSVServer"] isEqualToString:@"1"]) 
    { 

    } 

    [self.tableView reloadData]; 

    // Switch to determinate mode 
    HUD.mode = MBProgressHUDModeDeterminate; 
    HUD.labelText = @"Updating"; 
    float progress = 0.0f; 
    while (progress < 1.0f) 
    { 
     progress += 0.01f; 
     HUD.progress = progress; 
     usleep(15000); 
    } 
    // The sample image is based on the work by www.pixelpressicons.com, http://creativecommons.org/licenses/by/2.5/ca/ 
    // Make the customViews 37 by 37 pixels for best results (those are the bounds of the build-in progress indicators) 
    HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]]; 
    HUD.mode = MBProgressHUDModeCustomView; 
    HUD.labelText = @"Completed"; 
    sleep(2); 
} 

任何幫助將不勝感激。

傑克

回答

2

pullAndDisplayData方法在單獨的線程中運行。這使得MBProgressHUD可以使用UI線程來顯示自己。您應該始終從主(UI)線程更新您的UI。使用performSelectorOnMainThread:方法來調用[self.tableView reloadData];和其他UI的東西。我假設[downloader pullAndDisplayData];是同步呼叫。

+0

+1作爲用戶界面只支持要填充的主線程。 – Kuldeep 2012-07-10 13:53:15

0

這個問題可能是由於正在發生一些內存問題,您嘗試使用SVProgressHUD這一點,它是MBProgressHUD擴展版:

您需要做的僅僅是這樣的:

- (void) pullAndDisplayData{ 

    [SVProgressHUD showWithStatus:@"Downloading..."]; 

    // Indeterminate mode 
    ExpensesDataDownloader *downloader = [[ExpensesDataDownloader alloc] init]; 
    [downloader pullAndDisplayData]; 

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 
    if ([[defaults objectForKey:@"canExportCSVServer"] isEqualToString:@"1"]) 
    { 

    } 

    [self.tableView reloadData]; 

    // Switch to determinate mode 
    HUD.mode = MBProgressHUDModeDeterminate; 
    HUD.labelText = @"Updating"; 
    float progress = 0.0f; 
    while (progress < 1.0f) 
    { 
     progress += 0.01f; 
     HUD.progress = progress; 
     usleep(15000); 
    } 
    // The sample image is based on the work by www.pixelpressicons.com, http://creativecommons.org/licenses/by/2.5/ca/ 
    // Make the customViews 37 by 37 pixels for best results (those are the bounds of the build-in progress indicators) 
    HUD.customView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"37x-Checkmark.png"]]; 
    HUD.mode = MBProgressHUDModeCustomView; 
    HUD.labelText = @"Completed"; 
    sleep(2); 

    [SVProgressHUD dismiss]; 
} 

無需要分配或釋放任何東西。它的工作原理就是這樣!

所有最好的!

+0

因爲我不能在你的例子中的任何地方識別背景線程/隊列,所以它看起來像會在主線程中運行並阻止它,因此不會顯示進度,因爲UI將不會有機會運行和更新HUD。 – 2012-07-10 11:56:26

+0

你是否刪除了所有與MBProgressHUD相關的代碼? – 2012-07-10 12:00:01

+0

這不是我的問題,我只是評論你的代碼,不使用它。如果你看看這個問題,你會發現它的意圖是在後臺運行一些代碼,同時顯示HUD。 – 2012-07-10 12:07:05

1

MBprogressHUD API

/** 
* Shows the HUD while a background task is executing in a new thread, then hides the HUD. 
* 
* This method also takes care of autorelease pools so your method does not have to be concerned with setting up a 
* pool. 
* 
* @param method The method to be executed while the HUD is shown. This method will be executed in a new thread. 
* @param target The object that the target method belongs to. 
* @param object An optional object to be passed to the method. 
* @param animated If set to YES the HUD will (dis)appear using the current animationType. If set to NO the HUD will not use 
* animations while (dis)appearing. 
*/ 
- (void)showWhileExecuting:(SEL)method onTarget:(id)target withObject:(id)object animated:(BOOL)animated; 

由於您使用此方法,pullAndDisplayData在新的線程中執行。這可能會導致你有奇怪的問題(我想)。您正在從後臺線程更新UI元素,這不太好。 UI元素將從主線程更新。使用後臺線程僅下載數據。使用它的

Insetad,嘗試使用GCD(大中央調度)

[MBProgressHUD showHUDAddedTo:self.view animated:YES]; 
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{ 
    // download operation here... 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [MBProgressHUD hideHUDForView:self.view animated:YES]; 
     // reload data here... 
    }); 
}); 

如需進一步信息請參閱Usage sectionMBProgressHUD

+0

@MSK感謝您糾正錯字。乾杯!! – 2012-07-10 20:13:17