2012-05-06 24 views
10

nie mówimy o tysiącach wierszy ani o niczym, chociaż gdyby istniał sposób na zwiększenie skali, chciałbym.animowanie dużej liczby wierszy/sekcji w UITableView słaba wydajność

Mam tabelę z 27 odcinkami i 180 rzędami rozmieszczonymi we wszystkich sekcjach, a scenariusz, w którym aktualnie utknąłem, to kiedy animuję rzeczy do stanu modelu z tylko trzema sekcjami i 5 rzędami, i (jeszcze gorzej) z powrotem.

Łączę wszystkie animacje za pomocą funkcji beginUpdates/endUpdates. Moja aplikacja całkiem nieźle blokuje się na 1-2 sekundy na iPhone4, podczas gdy on wymyśla rzeczy, a następnie zaczyna się animacja.

Próbowałem zarówno animować usuwanie/dodawanie każdego wiersza, zachowując sekcje (i zmniejszenie liczby wierszy do 0 w przypadku usuwania), a także animowanie tylko usunięcie/wstawienia samych sekcji (gdy liczba wierszy spadłaby do 0). Założę się, że ta ostatnia da lepszą wydajność, ale w niczym się nie zmieni.

Czy jest coś, co można zrobić po stronie aplikacji, aby przyspieszyć? W tej chwili mam dość gruby kod do wyskoczenia z poszczególnych animacji, jeśli jest ich więcej niż 20, decydując się na ponowne załadowanie danych.

edytuj tutaj kod, który wykazuje problem. Wydajność tego kodu jest nieco lepsza niż równoważny kod monotouch (którego używałem wcześniej), ale nadal jest dość zły.

#import "TableViewController.h" 

@interface MyTableViewDataSource : NSObject<UITableViewDataSource> { 
    int rows; 
}; 

@end 

@implementation MyTableViewDataSource 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 1; 
} 

- (void)setRowCount:(int)r 
{ 
    rows = r; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return rows; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (!cell) 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 

    cell.textLabel.text = [NSString stringWithFormat:@"row %d", indexPath.row]; 

    return cell; 
} 

@end 

@implementation MyTableViewController { 
    UIBarButtonItem *populateButtonItem; 
}; 

- (id)initWithStyle:(UITableViewStyle)style 
{ 
    self = [super initWithStyle:style]; 
    if (self) { 
     populateButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Populate" style:UIBarButtonItemStylePlain target:self action:@selector(populateDataSource)]; 
    } 
    return self; 
} 

- (void)populateDataSource 
{ 
    NSMutableArray* new_rows = [[NSMutableArray alloc] init]; 
    [((MyTableViewDataSource*)self.tableView.dataSource) setRowCount:200]; 

    for (int i = 0; i < 200; i ++) 
     [new_rows addObject:[NSIndexPath indexPathForRow:i inSection:0]]; 

    [self.tableView beginUpdates]; 
    [self.tableView insertRowsAtIndexPaths:new_rows withRowAnimation:UITableViewRowAnimationAutomatic]; 
    [self.tableView endUpdates]; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.tableView.dataSource = [[MyTableViewDataSource alloc] init]; 
    self.navigationItem.rightBarButtonItem = populateButtonItem; 
} 

@end 
+1

Moim pierwszym przypuszczeniem byłoby, że twoje komórki tabeli są winowajcą. Czy używasz komórek niestandardowych? – lyricsboy

+0

Czy możesz napisać jakiś kod? Ponadto: czy twój UITableViewCells jest nieprzejrzysty? – Ahti

+1

Co to jest wskazanie instrumentów, to wąskie gardło? Czy usuwasz je masowo za pomocą pojedynczego deleteRowsAtIndexPaths: ... call, lub wielu pojedynczych połączeń? Czy wywołasz reloadData w środku animacji (nigdy nie możesz tego zrobić)? –

Odpowiedz

3

To ma sens tylko do animowania wierszy, które są widoczne. Zamiast wykonywać animację dla wszystkich wstawianych wierszy, rozważ tylko animację wstawiania tych wierszy, które będą widoczne.

Czy jesteś pewien, że to animacja powoduje opóźnienie? Czy otrzymujesz to samo opóźnienie, jeśli przekazujesz UITableViewRowAnimationNone dla animacji, czy jest to szybsze? Jeśli działa szybciej, to unikaj animowania tych wstawień, które nie będą widoczne.(Możesz dowiedzieć się, które wiersze są obecnie widoczne za pomocą -indexPathsForVisibleRows.) Jeśli nie jest szybszy, problem prawdopodobnie nie jest związany z animacją, a raczej narzut na wstawienie kilkuset wierszy naraz. Przeładowanie całej tabeli, tak jak teraz robisz, jest jedną z opcji; wstawianie rzędów w mniejsze partie to kolejne.

Na koniec warto byłoby profilować aplikację za pomocą Instrumentów podczas wstawiania. Uzyskasz lepszy obraz tego, co robi aplikacja podczas tego opóźnienia, i jest to pierwszy krok w kierunku wyeliminowania opóźnienia.

+0

unikanie animowania wierszy, które nie będą widoczne, jest rzeczywiście tym, co chciałbym zrobić. Ale nie wygląda na to, że indeks IndexPathsForVisibleRows da mi to, czego chcę - animacja prawdopodobnie wypełni widoczny obszar, więc aktualnie widoczne wiersze nie są tymi, które chcę animować ... chyba że program IndexPathsForVisibleRows w jakiś sposób bierze pod uwagę wiersze (i/lub sekcje) będę dodawać/usuwać. – toshok

+0

... powiedział, przełączenie na UITableViewRowAnimationNone było biletem. Jest jeszcze bardzo mała początkowa przerwa, ledwo zauważalna. Więc może to nie tyle liczba animacji, ale może uporządkowanie z (lub obcinanie?), Które robi UITableView podczas przechodzenia przez różne inne elementy wyliczające, które powodowały spowolnienie – toshok

0

Spróbuj przetestować tę samą funkcjonalność w przypadku niektórych zakodowanych tablic ciągów i sprawdzenie zniknęło. Jeśli problem nadal występuje, oznacza to, że problem dotyczy renderowania bez danych.

Dla różnych rodzajów animacji istnieje już kilka niestandardowych elementów sterujących, w których można uzyskać szybszą animację z pewną implementacją jednego liniowca: Here.

1

Używasz UITableViewRowAnimationAutomatic (Odsyłacz: Widok tabeli wybiera odpowiedni styl animacji dla ciebie. (Wprowadzony w iOS 5.0.)), I z jakiegoś powodu, widok tabeli wybiera naprawdę zły, który zanika we wszystkich wiersze podczas ich rozszerzania. Zmiana przezroczystości na 200 UIViews podczas zmiany rozmiaru ramki i przesuwania jej wokół opcji POWODUJE, że jest wolna. :)

można po prostu to zrobić:

[self.tableView insertRowsAtIndexPaths:new_rows withRowAnimation:UITableViewRowAnimationNone]; 

To zmniejszy animacje na bardzo podstawowym animacji UITableView, kiedy wstawianie wierszy, które, moim zdaniem, jest absolutnie wystarczający podczas wkładania, że ​​wiele.

+0

tak, to była naprawdę sztuczka. – toshok

Powiązane problemy