2012-03-25 4 views
1

Я работаю с ViewController, который делегирует & datasources 2 разных табличных представления. в соответствии с тем, что пользователь хочет видеть (переключение происходит с «touchesBegan» для определенных областей в представлении.чередовать 2 приложения UITableViews freeze

ViewController является одним из 3 subcontrollers из вкладок приложения.

Чередование между tableviews работает только плавник . я получить правильные данные, расположение и т.д., и я могу переключаться между ними так часто, как я хочу.

первый TableView не содержит сложных данных, поэтому он будет загружен в течение нескольких миллисекунд.

второй tableview2 содержит данные, которые загружаются примерно 2-3 секунды (в зависимости от суммы сущностей в coredata). пока эти данные загружаются & tableview2 перерисовывает, я показываю MBProgressHUD. это тоже работает.

Проблема: если я взаимодействовать с tabbarcontroller в то время как table2 загружается & ИЛС вращается, приложение «зависает» ИЛС работает infinitly долго и любой userinteractino отключен. а также щелкнутая вкладка не откроется.

КОД: touchesBegan Функция

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{ 


    if (isLoadingAllMonth) { 
     return; 
    } 
    [[MBProgressHUD HUDForView:self.view]removeFromSuperview]; 


    UITouch *touch = [[event allTouches]anyObject]; 
    int viewTag = touch.view.tag;       // 1 for thisMonth, 2 for allMonth 


    if (viewTag == 1) { 
     [allMonthButtonView setAlpha:.8]; 
     [thisMonthButtonView setAlpha:1]; 
     if (allMonthIsActive == NO) { 
      return; 
     } 
     else{ 
      [self reloadThisMonth]; 
      [allMonthTable removeFromSuperview]; 
      [self.view addSubview:thisMonthTable]; 

      allMonthIsActive = NO; 
     } 
    } 

    else if(viewTag == 2){ 

     if (!allMonthIsActive) { 
      allMonthIsActive = YES; 



      if (isLoadingAllMonth) { 
       return; 
      } 

      [self.view addSubview:HUD]; 
      [allMonthTable setFrame:CGRectMake(4, 64, 312, 343)]; 
      [allMonthTable setBackgroundColor:[self grayColor]]; 
      [self.view addSubview:allMonthTable]; 

      HUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; 
      dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 
       isLoadingAllMonth = YES; 

       [self reloadAllMonth]; 

       dispatch_async(dispatch_get_main_queue(), ^(void) { 

        [self.allMonthTable reloadData];   // Or reload tableView 
        [HUD hide:YES]; 
       }); 

      }); 
     } 
    } 

} 

КОД: reloadAllMonth

-(void)reloadAllMonth{ 
    UIFont *titleFont = [UIFont fontWithName:@"Cochin" size:14.0]; 
    UIFont *detailFont = [UIFont fontWithName:@"Cochin" size:18.0]; 
    [[MBProgressHUD HUDForView:self.view] setLabelFont:titleFont]; 
    [[MBProgressHUD HUDForView:self.view] setDetailsLabelFont:detailFont]; 

    [[MBProgressHUD HUDForView:self.view] setLabelText:@"Please wait"]; 


    [[MBProgressHUD HUDForView:self.view] setDetailsLabelText:@"Cleaning Cache"]; 
    if (allMonthData.count != 0) { 
     for (NSMutableArray *arr in allMonthData) { 
      [arr removeAllObjects]; 
     } 

     [allMonthData removeAllObjects]; 

     for (NSMutableArray *arr in allMonthDataNumbers) { 
      [arr removeAllObjects]; 
     } 

     [allMonthDataNumbers removeAllObjects]; 

    } 

    NSDate *rootDate = [NSDate dateWithTimeIntervalSinceReferenceDate:(10*365*24*60*60)]; 
    int rootMonth = [[dataHandler getMonthNumber:rootDate] intValue]; 

    NSMutableArray *allExp = [[NSMutableArray alloc]init]; 
    NSNumber *currentMonth = [dataHandler getMonthNumber:[NSDate date]]; 
    NSMutableArray *temp = [[NSMutableArray alloc]init ]; 
    NSNumber *tempMonth = [NSNumber numberWithInt:(currentMonth.intValue+1)]; 

    [temp removeAllObjects]; 
    [[MBProgressHUD HUDForView:self.view] setDetailsLabelText:@"Updating Data..."]; 

    while (tempMonth.intValue > rootMonth) { 
     tempMonth = [NSNumber numberWithInt:(tempMonth.intValue-1)]; 
     temp = [NSMutableArray arrayWithArray:[dataHandler fetchAllExpensesForMonth:tempMonth]] ; 
     if (temp.count != 0) { 
      [allExp addObject:temp]; 
     } 

    } 
    allMonthData = allExp; 

    if (!allMonthDataNumbers) { 
     allMonthDataNumbers = [[NSMutableArray alloc]init]; 

    } 
    [[MBProgressHUD HUDForView:self.view] setDetailsLabelText:@"Updating Balances..."]; 

    for (NSArray *current in allMonthData) { 
     Expense *exp = [current objectAtIndex:0]; 
     NSNumber *monthNumber = exp.month; 
     double budget = 0; 
     double spent = 0; 
     double balance = 0; 
     int count = 0; 
     double avgDayBal = 0; 

     for (Expense *exp in current) {     // iterate this month 
      if (exp.expenseType.boolValue == 0) {     // all day type expensees 
       spent = spent+exp.value.doubleValue; 
       count ++; 
      } 
      else if (exp.expenseType.boolValue == 1) { 
       budget = budget+exp.value.doubleValue; 
      } 
     } 
     balance = budget+spent; 
     avgDayBal = balance/[dataHandler numberOfDaysInMonthForMonth:monthNumber]; 

     NSMutableArray *temp = [[NSMutableArray alloc]init]; 
     [temp addObject:monthNumber]; 
     [temp addObject:[NSNumber numberWithDouble:budget ]]; 
     [temp addObject:[NSNumber numberWithDouble:spent ]]; 
     [temp addObject:[NSNumber numberWithDouble:balance ]]; 
     [temp addObject:[NSNumber numberWithInt:count ]]; 
     [temp addObject:[NSNumber numberWithDouble:avgDayBal ]]; 

     [allMonthDataNumbers addObject:temp]; 
    } 
    NSNumber *day = [dataHandler getDayNumber:[NSDate date] ]; 
    [[allMonthDataNumbers lastObject] addObject:day]; 

    NSLog(@"We have %d month", [allMonthDataNumbers count]); 

    [[MBProgressHUD HUDForView:self.view] setDetailsLabelText:@"Updating Interface..."]; 


    [allMonthTable reloadData]; 
    isLoadingAllMonth = NO; 

} 

КОД: reloadThisMonth

-(void)reloadThisMonth{ 

    [dataHandler updateData]; 

    if (!tableData) { 
     tableData = [[NSMutableArray alloc]initWithCapacity:31]; 
    } 

    for (NSMutableArray *temp in tableData) { 
     [temp removeAllObjects]; 
    } 
    [tableData removeAllObjects]; 

    for (int j = 0; j < 31; j++) {   //fill with 31 empty mutuable arrays 
     NSMutableArray *tempArray = [[NSMutableArray alloc]init]; 
     [tableData addObject:tempArray]; 
    } 

    for (Expense *exp in dataHandler.allMonthExpenses) { 
     if (exp.expenseType.boolValue == 0) { 
      [[tableData objectAtIndex:(exp.day.intValue-1)]addObject:exp]; 
     } 
    } 
    int countDayExp = 0; 
    for (NSMutableArray *arr in tableData) { 
     countDayExp = countDayExp + arr.count; 
    } 
    if (countDayExp == 0) { 
     hasDayExpenses = NO; 
    } 
    else{ 
     hasDayExpenses = YES; 
    } 

    [thisMonthTable reloadData]; 
    [thisMonthTable setBackgroundColor:[self grayColor]]; 

} 

Кто-нибудь видит, где я ошибся? или что еще может быть проблемой? обе таблицы показывают штраф. если я не взаимодействую с приложением во время загрузки второго представления, все работает отлично. есть идеи?

обновление:

по-видимому, два потока сталкиваются, когда один и тот же grapping fetchroutine в то же время - вот скриншот из состояния паузы отладки в то время как приложение «висел». если я открою другую вкладку, которая нуждается в той же процедуре выборки, которую приложение зависает. если я отлаживаю & пауза в зависании, он показывает мне строку в процедуре выборки. его первый раз, когда я работаю с потоками - я был бы очень признателен некоторые материалы о том, как избежать этого столкновения:/

threads colliding

+0

Извините, у вас нет времени, чтобы прочитать ваш код для правильного ответа, но это не похоже на то, что вы используете GCD. Если вы выбросите код, который загружает другую таблицу в отдельный поток, тогда основной поток может обрабатывать пользовательский интерфейс с приоритетом, и вы, вероятно, избавитесь от какого-либо отставания. –

+0

Согласитесь с GCD. Мое предложение было бы попытаться изолировать причину. Возможно, создайте небольшой проект с этой сложной операцией и одной таблицей. Также не читали детали, но вполне вероятно, что длительная операция висит, чем ОС. – danh

+0

Еще один намек: возьмите его в зависание и отложите. Вы можете найти ошибку сразу. – danh

ответ

0

У меня была аналогичная проблема с MBProgressHUD во время выполнения задач в другом потоке. То, как я решил это, было использовать свойство * HUD везде вместо локальной переменной. Похоже, что вы используете локальную переменную в некоторых местах и ​​переменную экземпляра в других.

@property (strong, nonatomic) MBProgressHUD *HUD; 

Затем используйте это нравится:

HUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; 
HUD.delegate = self; 

Выполнить код в другом потоке, а затем вызвать основной поток с помощью НОД, чтобы скрыть его и удалить HUD:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 

//Your Code to execute in the background 

     dispatch_async(dispatch_get_main_queue(), ^(void) { 
      //Code here to update stuff on main thread 
      //Example: hide hud or change hud label 
        HUD.labelText = @"Foo Done, Bar started"; //change label 
        [HUD hide:YES];       // or hide HUD 
        [self.tableView reloadData];   // Or reload tableView 
       }); 

}); 

а также MBProgressHUD Делегат:

- (void)hudWasHidden:(MBProgressHUD *)hud { 
    // Remove HUD from screen when the HUD was hidded 
    [HUD removeFromSuperview]; 
    HUD = nil; 
} 

Метод:

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

такой же, как там, где я столкнулся с наибольшей неприятностью. Похоже, что HUD не знает, что ваш взгляд был изменен, и считает, что селектор не закончен и продолжает работать, блокируя основной поток. Поэтому я избавился от этого метода и использовал экземпляр Variable * HUD и GCD, извлекая основной поток всякий раз, когда мне нужно было обновить ярлык HUD или скрыть/удалить его, как в приведенном выше коде.

+0

Я обновил свой код touchBegun в quesiton. проблема остается такой же печально ... она зависает в процедуре выборки после попытки открыть другую вкладку, которая использует тот же fetchroutine. –

+0

Можно ли убить отправленную нить при нажатии на табуляцию? –

Смежные вопросы