Ich arbeite mit einem ViewController, der & Datenquellen 2 verschiedene Tabellenansichten delegiert. nach dem, was wünscht der Benutzer (toggeln geschieht mit ‚touchesBegan‘ für bestimmte Bereiche in der Ansicht zu sehen.wechselnd zwischen 2 UITableViews Application Freeze
Der Viewcontroller eines von 3 Subcontrollern eines Register Anwendung ist.
Der Wechsel zwischen dem Tableviews funktioniert fin in wenigen Millisekunden. bekomme ich die richtigen Daten, Layout, etc, und ich kann so oft wie ich.
die erste Tableview enthält nicht schwierig, Daten will zwischen ihnen ändern, damit es
den zweiten geladen wird. tableview2 enthält Daten, die etwa 2-3 Sekunden zum Laden benötigen (abhängig von der Menge) von Entitäten in Coredata). während diese Daten geladen werden & die TableView2 Neuzeichnungen ich eine MBProgressHUD zeigen. das funktioniert auch.
Problem: wenn i interagieren mit dem TabBarController während table2 & Beladung ist die HUD dreht, die app 'friert' das HUD läuft infinitly lang und jede userinteractino ist deaktiviert. Auch der angeklickte Tab konnte nicht geöffnet werden.
Code: touchesBegan FUnction
-(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];
});
});
}
}
}
Code: 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;
}
Code: 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]];
}
sieht jemand wo ich falsch gelaufen bin? oder was sonst könnte das Problem sein? beide Tabellen zeigen gut. Wenn ich beim Laden der zweiten Ansicht nicht mit der App interagiere, funktioniert alles perfekt. irgendwelche Ideen?
Update:
offenbar zwei Fäden miteinander kollidieren, wenn die gleiche fetchroutine zugleich grapping - hier ist ein Screenshot von einem Zustand angehalten debug, während die App ‚gehängt‘. Wenn ich eine andere Registerkarte öffne, die die gleiche Abrufroutine benötigt, hängt die App. wenn ich debugge & pause im aufgehängten zustand zeigt es mir eine linie in der abholroutine. es ist das erste Mal, dass ich mit Themen arbeiten - ich würde wirklich etwas Eingang zu schätzen weiß, wie man diese Kollision zu vermeiden:/
Es tut uns leid, haben Sie keine Zeit, Ihren Code für eine richtige Antwort zu lesen, aber es sieht nicht so aus, als ob Sie GCD verwenden. Wenn Sie den Code werfen, der die andere Tabelle in einen separaten Thread lädt, kann der Hauptthread die Benutzeroberfläche mit Priorität bearbeiten und Sie würden wahrscheinlich jede Verzögerung loswerden. –
Über GCD zustimmen. Mein Vorschlag wäre, zu versuchen, die Ursache zu isolieren. Vielleicht ein kleines Projekt mit nur dieser komplexen Operation und einem einzigen Tisch. Habe auch nicht genau gelesen, aber es ist wahrscheinlich, dass die lange Operation hängt als das OS. – danh
Ein weiterer Hinweis: Holen Sie es in den Zustand "hängen" in debug und pausieren Sie es. Sie könnten den Fehler sofort finden. – danh