EXC_BAD_ACCESS в [self.tableView reloadData] - PullRequest
3 голосов
/ 23 марта 2012

Я делаю простое приложение, которое делает некоторые вычисления.Некоторые из этих расчетов довольно сложны, поэтому для получения результата может потребоваться некоторое время.Я использую UITableView, чтобы позволить пользователю вводить значения.Затем, после нажатия кнопки «Рассчитать», я делаю простой UIView с UIActivityIndicatorView и помещаю его в середину экрана.И тогда я вызываю метод расчета в фоновом режиме.Какой-то код:

    self.activityIndicatorView = [[UIView alloc]initWithFrame:CGRectMake(320/2 - 50, (480 - 64)/2 - 50, 100, 100)];
    self.activityIndicatorView.layer.cornerRadius = 10.0f;
    self.activityIndicatorView.backgroundColor = [UIColor colorWithRed:0. green:0. blue:0. alpha:0.7];
    UIActivityIndicatorView *actInd = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    actInd.frame = CGRectMake((100 - actInd.frame.size.width) / 2, (100 - actInd.frame.size.height) / 2, actInd.frame.size.width, actInd.frame.size.height);
    [actInd startAnimating];
    [self.activityIndicatorView addSubview:actInd];
    [self.activityIndicatorView bringSubviewToFront:actInd];
    [self.view addSubview:self.activityIndicatorView];
    [self.view bringSubviewToFront:self.activityIndicatorView];
    [self performSelectorInBackground:@selector(calculateAllThatShizzle) withObject:nil];

Как видите, все довольно просто.Но если клавиатура все еще видна, она падает (EXC_BAD_ACCESS), когда достигает значения [self.tableView reloadData] в методе -(void)calculateAllThatShizzle с этим в журнале:

2012-03-23 11:06:32.418 MyApp[869:5c07] bool _WebTryThreadLock(bool), 0x6adb270: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
1   WebThreadLock
2   -[UITextRangeImpl isEmpty]
3   -[UITextRange(UITextSelectionAdditions) _isCaret]
4   -[UITextSelectionView setCaretBlinks:]
5   -[UIKeyboardImpl setCaretBlinks:]
6   -[UIKeyboardImpl setDelegate:force:]
7   -[UIKeyboardImpl setDelegate:]
8   -[UIPeripheralHost(UIKitInternal) _reloadInputViewsForResponder:]
9   -[UIResponder _finishResignFirstResponder]
10  -[UIResponder resignFirstResponder]
11  -[UITextField resignFirstResponder]
12  -[UITableView reloadData]
13  -[ChildViewController calculateAllThatShizzle]
14  -[NSThread main]
15  __NSThread__main__
16  _pthread_start
17  thread_start

Так что проблема в том, что она пытаетсясделать что-то с клавиатурой из фонового потока.Я пробовал перебирать ячейки и вызывать [cell.rightTextField resignFirstResponder], но это не помогает.Я также пытался использовать это

-(void)reloadTableViewData {
  [self.tableView reloadData];
}
-(void)calculateAllThatShizzle {
  //some code omitted - code that uses UIKit
  if ([dob timeIntervalSinceDate:calcDate]>0) {
            [errorButton setTitle:@"Calculation Date must be more than Date of Birth" forState:UIControlStateNormal];
            errorButton.hidden = NO;
            [self.activityIndicatorView removeFromSuperview];
            self.activityIndicatorView = nil;
            return;
        }
  [self performSelectorOnMainThread:@selector(reloadTableViewData) withObject:nil waitUntilDone:NO];
}

, но это тоже не помогает.Я использую ELCTextfieldCell

Любая помощь будет оценена.

Спасибо

PS Я проверял некоторые другие вопросы о EXC_BAD_ACCESS на reloadData, но это неНе могу решить проблему с

PPS. Я также могу просто выполнить вычисления в главном потоке, но тогда графический интерфейс пользователя перестает отвечать, а индикатор активности не отображается

Ответы [ 2 ]

2 голосов
/ 23 марта 2012

Предложение:

  • сделать tableView первым ответчиком перед , который вы вызываете CalculateAllThatShizzle, то есть заставить текущий первый респондент подать в отставку и, таким образом, отклонить их клавиатуру
  • изатем ЗАПРЕЩАЕТСЯ вызов до вызова метода TranslateAllThatShizzle после завершения текущего цикла выполнения, т.е. убедитесь, что код для сброса клавиатуры запускается в подходящее время

Итак, что-то вроде этого:

[[self tableView] becomeFirstReponder]; // will dismiss keyboard
[[self performSelector: @selector(startBackgroundStuff) withObject: nil afterDelay: 0.0];

Затем в свой startBackgroundStuff вы можете вставить:

[self performSelectorInBackground:@selector(calculateAllThatShizzle) withObject:nil];

В методе, который вы определенно хотите убедиться, что метод reloadData вызывается в главном потоке.То, как ты это сделал, выглядит хорошо.,Вы также можете сделать следующее:

dispatch_async(dispatch_get_main_queue(), ^{
        [self reloadTableViewData];
    });

(я не знаю, лучше ли одно, чем другое, только то, что следует определенно работает надежно.)

Дополнительный комментарий

В CalculateAllThatShizzle вы делаете вызов UIKit из фона в некоторых условиях, например, [self.activityIndicatorView removeFromSuperview]; Это может вызвать сбой.UIKit звонки должны быть в главном потоке.

В

2 голосов
/ 23 марта 2012

попробуйте этот код

for(int i=0;i<[tblViewData count];i++)
{
    if([[(ELCTextfieldCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]] rightTextField] isFirstResponder])
    {
        [[(ELCTextfieldCell *)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]] rightTextField] resignFirstResponder];
    }
}

меняйте в зависимости от вас.

...