/ / EXC_BAD_ACCESS bei [self.tableView reloadData] - iPhone, Objective-C, iOS, UitableView, Exc-Bad-Access

EXC_BAD_ACCESS bei [self.tableView reloadData] - iPhone, Objective-C, iOS, UitableView, Exc-Bad-Access

Ich mache eine einfache App, die einige Berechnungen durchführt. Einige dieser Berechnungen sind ziemlich komplex, daher kann es eine Weile dauern, bis das Ergebnis vorliegt. Ich benutze UITableView Benutzer die Werte eingeben zu lassen. Dann mache ich nach Anklicken des "Berechnen" -Buttons ein einfaches UIView mit einem UIActivityIndicatorView darauf und ich lege es in die Mitte des Bildschirms. Und dann rufe ich die Berechnungsmethode im Hintergrund auf. Ein bisschen Code:

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

Wie Sie sehen, ist es ziemlich einfach. Aber wenn die Tastatur noch sichtbar ist, stürzt sie ab (EXC_BAD_ACCESS) wenn es darum geht [self.tableView reloadData] in dem -(void)calculateAllThatShizzle Methode mit dem im Protokoll:

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

Das Problem ist also, dass es versucht, etwas mit der Tastatur von einem Hintergrund-Thread aus zu tun. Ich habe versucht, die Zellen zu durchlaufen und anzurufen [cell.rightTextField resignFirstResponder], aber es hilft nicht. Ich habe es auch versucht

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

aber es hilft auch nicht. Ich benutze ELCTextfieldCell

Jede Hilfe wird geschätzt.

Vielen Dank

P.S. Ich habe einige andere Fragen zu geprüft EXC_BAD_ACCESS auf reloadData, aber es behandelt nicht das Problem, das ich habe

P.P.S. Ich kann die Berechnungen auch einfach im Hauptthread ausführen, aber dann reagiert die Benutzeroberfläche nicht mehr und die Aktivitätsanzeige wird nicht angezeigt

Antworten:

1 für die Antwort № 1

Probieren Sie diesen Code aus

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

verändere dich nach dir.


2 für die Antwort № 2

Vorschlag:

  • Machen Sie die tableView zum firstResponder Vor Sie rufen berechne alle das Zischen auf, d. h. erzwingen, dass der aktuelle Ersthelfer zurücktritt, und schließen somit die Tastatur
  • und dann VERWEISEN Sie den Aufruf von berechne alles, bis die aktuelle Ausführungsschleife abgeschlossen ist, d. h. stellen Sie sicher, dass der Code zum Entlassen der Tastatur zu einem geeigneten Zeitpunkt ausgeführt wird

Also so etwas:

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

Dann können Sie in Ihrem startBackgroundStuff Folgendes einfügen:

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

In der Methode möchten Sie auf jeden Fall sicherstellen, dass die reloadData-Methode im Hauptthread aufgerufen wird. Die Art und Weise, wie Sie es getan haben, sieht in Ordnung aus. Sie können auch Folgendes tun:

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

(Ich weiß nicht, ob einer besser ist als der andere, aber das, was folgt, funktioniert auf jeden Fall zuverlässig.)

Ergänzender Kommentar

In calculatorAllThatShizzle tätigen Sie unter bestimmten Umständen einen UIKit-Anruf aus dem Hintergrund, z. [self.activityIndicatorView removeFromSuperview]; Das kann zu einem Absturz führen. UIKit-Aufrufe müssen sich im Haupt-Thread befinden.

Im