/ / EXC_BAD_ACCESS su [self.tableView reloadData] - iphone, goal-c, ios, uitableview, exc-bad-access

EXC_BAD_ACCESS su [self.tableView reloadData] - iphone, goal-c, ios, uitableview, exc-bad-access

Sto realizzando un'app semplice che esegue alcuni calcoli. Alcuni di questi calcoli sono piuttosto complessi, quindi potrebbe volerci un po 'di tempo per ottenere il risultato. Sto usando UITableView per consentire all'utente di inserire i valori. Quindi dopo aver fatto clic sul pulsante "Calcola" faccio un semplice UIView con un UIActivityIndicatorView su di esso e l'ho messo al centro dello schermo. E poi chiamo il metodo di calcolo in background. Qualche codice:

    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];

Come vedi è abbastanza semplice. Ma se la tastiera è ancora visibile si arresta in modo anomalo (EXC_BAD_ACCESS) quando arriva a [self.tableView reloadData] nel -(void)calculateAllThatShizzle metodo con quello nel registro:

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

Quindi il problema è che sta provando a fare qualcosa con la tastiera da un thread in background. Ho provato a scorrere tra le celle e chiamare [cell.rightTextField resignFirstResponder], ma non aiuta. Ho anche provato a usarlo

-(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];
}

ma non aiuta neanche. Sto usando ELCTextfieldCell

Qualsiasi aiuto sarà apprezzato.

Grazie

Post scriptum Ho controllato alcune altre domande su EXC_BAD_ACCESS su reloadData, ma non copre il problema che ho

P.P.S. Posso anche solo eseguire i calcoli nel thread principale, ma poi la GUI non risponde e l'indicatore di attività non viene visualizzato

risposte:

1 per risposta № 1

prova questo codice

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];
}
}

cambia secondo te.


2 per risposta № 2

Suggerimento:

  • rendere la tabella Visualizza il primoRisponditore prima tu chiami calcola Tutto ciò che è, cioè forzando le dimissioni del primo risponditore attuale e quindi scartando la tastiera
  • e quindi DEFERISCI la chiamata a calcolaTuttiShizzle dopo il completamento del ciclo di esecuzione corrente, ovvero assicurati che il codice per chiudere la tastiera venga eseguito in un momento adatto

Quindi, qualcosa del genere:

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

Quindi nel tuo startBackgroundStuff puoi inserire:

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

Nel metodo vuoi sicuramente assicurarti che il metodo reloadData sia chiamato sul thread principale. Il modo in cui hai fatto sembra OK. Puoi anche fare quanto segue:

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

(Non so se uno è migliore dell'altro, solo che ciò che segue funziona sicuramente in modo affidabile.)

Commento supplementare

In calcoliTuttiShizzle stai effettuando una chiamata UIKit dallo sfondo in alcune condizioni, ad es. [self.activityIndicatorView removeFromSuperview]; Ciò potrebbe causare un arresto anomalo. Le chiamate UIKit devono essere sul thread principale.

In