2011-08-04 3 views
32

Przeszukałem wszystkie przykłady w Internecie i nie mogłem wymyślić, jak właściwie dodać komórkę do widoku tabeli z animacją. Załóżmy, że mam jedną sekcję z jedną komórką i chcę dodać kolejną komórkę, gdy użytkownik kliknie na akcesorium pierwszej komórki.jak prawidłowo korzystać z insertRowsAtIndexPaths?

Mój „dodać” metoda robi to:

- (IBAction) toggleEnabledTextForSwitch1onSomeLabel: (id) sender { 
if (switch1.on) { 

    NSArray *appleComputers = [NSArray arrayWithObjects:@"WWWWW" ,@"XXXX", @"YYYY", @"ZZZZ", nil]; 
    NSDictionary *appleComputersDict = [NSDictionary dictionaryWithObject:appleComputers forKey:@"Computers"]; 
    [listOfItems replaceObjectAtIndex:0 withObject:appleComputersDict]; 
    [tblSimpleTable reloadData]; 

} 

Który działa, ale nie ma animacji. Rozumiem, że aby dodać animację, muszę użyć metody insertRowsAtIndexPaths: withRowAnimation, więc wypróbowałem mnóstwo opcji, ale zawsze zawiesza się przy wykonywaniu metody insertRowsAtIndexPaths: withRowAnimation.

Moja ostatnia próba była w ten sposób:

- (IBAction) toggleEnabledTextForSwitch1onSomeLabel: (id) sender { 
if (switch1.on) { 

    NSIndexPath *path1 = [NSIndexPath indexPathForRow:1 inSection:0]; //ALSO TRIED WITH indexPathRow:0 
     NSArray *indexArray = [NSArray arrayWithObjects:path1,nil]; 
    [tblSimpleTable insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationRight]; 

} 
} 

Co robię źle? Jak mogę to łatwo zrobić? Nie rozumiem tej całej rzeczy indexPathForRow ... Nie rozumiem też, jak dzięki tej metodzie mogę dodać nazwę etykiety do nowej komórki. Proszę, pomóż ... dzięki!

+0

Czy zaktualizowałeś swoje źródło danych o 2 elementy? –

Odpowiedz

22

ważną rzeczą, aby pamiętać podczas korzystania insertRowsAtIndexPaths jest to, że UITableViewDataSource potrzeby, aby dopasować co mówi wstawka. Jeśli dodasz wiersz do widoku tabeli, upewnij się, że dane kopii zapasowej są już zaktualizowane, aby pasowały do ​​siebie.

+0

co z moimi indeksami - czy są poprawne zakładając, że dodaję jeszcze jeden wiersz do tabeli jednorzędowej? – TommyG

+0

OK, miałeś rację - usunąłem wszystkie aktualizacje mojego nowego stołu/słownika i teraz to działa. Dzięki!! – TommyG

6

Przede wszystkim należy zaktualizować model danych tuż przed samą tablicą aktualizacji. Ponadto można użyć:

[tableView beginUpdates]; 
// do all row insertion/delete here 
[tableView endUpdates]; 

i tabela będzie produkować wszystko zmieniło się od razu z animacją (jeśli podasz go)

+0

próbowałem - nie miało to znaczenia. – TommyG

+0

Myślę, że nie zaktualizowałeś swojego modelu danych przed zmianą. Czy możesz opublikować wiadomość wyjątku? –

+0

2011-08-04 10: 54: 55.601 ViewTest [36300: b903] *** Brak asercji w - [UITableView _endCellAnimationsWithContext:],/SourceCache/UIKit_Sim/UIKit-1448.89/UITableView.m: 995 2011-08-04 10: 54: 55.602 ViewTest [36300: b903] CoreAnimation: ignorowanie wyjątku: Nieprawidłowa aktualizacja: nieprawidłowa liczba wierszy w sekcji 0. Liczba wierszy zawartych w istniejącej sekcji po aktualizacja (1) musi być równa liczbie wierszy zawartych w tej sekcji przed aktualizacją (1), plus lub minus liczba wierszy wstawionych lub usuniętych z tej sekcji (1 wstawiony, 0 usunięty). – TommyG

22

Jest to proces dwuetapowy:

Najpierw zaktualizować źródło danych tak numberOfRowsInSection i cellForRowAtIndexPath powróci prawidłowe wartości dla danych po przekładek. Musisz to zrobić przed wstawieniem lub usunięciem wierszy, albo pojawi się błąd "nieprawidłowej liczby wierszy", który otrzymujesz.

Następnie wstawić wiersz:

[tblSimpleTable beginUpdates]; 
[tblSimpleTable insertRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationRight]; 
[tblSimpleTable endUpdates]; 

prostu wstawienie lub usunięcie wiersza nie zmienia źródło danych; musisz to zrobić sam.

+0

+1 dzięki, że całkowicie pomogło! – TommyG

+0

To za mało: należy również umieścić kod zmiany źródła danych w sekcji beginUpdates/endUpdates, ponieważ jest to również część "transakcji". – ettore

+0

Nie powinieneś umieszczać kodu źródłowego zmieniającego kod wewnątrz początku/końca, ponieważ jest on niezależny od aktualizacji tabeli. Rozdzielenie obaw. "Transakcja" jest po prostu aktualizacją wyświetlania tabeli. –

0

do szybkiego użytkowników

// have inserted new item into data source 

// update 
self.tableView.beginUpdates() 
var ip = NSIndexPath(forRow:find(self.yourDataSource, theNewObject)!, inSection: 0) 
self.tableView.insertRowsAtIndexPaths([ip], withRowAnimation: UITableViewRowAnimation.Fade) 
self.tableView.endUpdates() 
+0

Oto samouczek w Swift ---> [Aktualizacje UITableView do zachowania integralności oryginalnej trylogii] (https: // grokswift. com/uitableview-updates /), demonstracja jak używać insertRowsAtIndexPaths i beginUpdates –

2

insertRowsAtIndexPaths:withRowAnimation: oraz zmian do modelu danych oba muszą występować w międzybeginUpdates i endUpates

stworzyłem prosty przykład, który powinien działać na własną rękę. Spędziłem tydzień, próbując to rozgryźć, ponieważ nie mogłem znaleźć żadnych prostych przykładów, więc mam nadzieję, że to oszczędza czasu i bólu głowy!

@interface MyTableViewController() 
@property (nonatomic, strong) NSMutableArray *expandableArray; 
@property (nonatomic, strong) NSMutableArray *indexPaths; 
@property (nonatomic, strong) UITableView *myTableView; 
@end 

@implementation MyTableViewController 

- (void)viewDidLoad 
{ 
    [self setupArray]; 
} 

- (void)setupArray 
{ 
    self.expandableArray = @[@"One", @"Two", @"Three", @"Four", @"Five"].mutableCopy; 
} 

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    return self.expandableArray.count; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    //here you should create a cell that displays information from self.expandableArray, and return it 
} 

//call this method if your button/cell/whatever is tapped 
- (void)didTapTriggerToChangeTableView 
{ 
    if (/*some condition occurs that makes you want to expand the tableView*/) { 
     [self expandArray] 
    }else if (/*some other condition occurs that makes you want to retract the tableView*/){ 
     [self retractArray] 
    } 
} 

//this example adds 1 item 
- (void)expandArray 
{ 
    //create an array of indexPaths 
    self.indexPaths = [[NSMutableArray alloc] init]; 
    for (int i = theFirstIndexWhereYouWantToInsertYourAdditionalCells; i < theTotalNumberOfAdditionalCellsToInsert + theFirstIndexWhereYouWantToInsertYourAdditionalCells; i++) { 
     [self.indexPaths addObject:[NSIndexPath indexPathForRow:i inSection:0]]; 
    } 

    //modify your array AND call insertRowsAtIndexPaths:withRowAnimation: INBETWEEN beginUpdates and endUpdates 
    [self.myTableView beginUpdates]; 
    //HERE IS WHERE YOU NEED TO ALTER self.expandableArray to have the additional/new data values, eg: 
    [self.expandableArray addObject:@"Six"]; 
    [self.myTableView insertRowsAtIndexPaths:self.indexPaths withRowAnimation:(UITableViewRowAnimationFade)]; //or a rowAnimation of your choice 

    [self.myTableView endUpdates]; 
} 

//this example removes all but the first 3 items 
- (void)retractArray 
{ 
    NSRange range; 
    range.location = 3; 
    range.length = self.expandableArray.count - 3; 

    //modify your array AND call insertRowsAtIndexPaths:withRowAnimation: INBETWEEN beginUpdates and endUpdates 
    [self.myTableView beginUpdates]; 
    [self.expandableArray removeObjectsInRange:range]; 
    [self.myTableView deleteRowsAtIndexPaths:self.indexPaths withRowAnimation:UITableViewRowAnimationFade]; //or a rowAnimation of your choice 
    [self.myTableView endUpdates]; 
} 

@end