ios - UITableView: using moveRowAtIndexPath:toIndexPath: and reloadRowsAtIndexPaths:withRowAnimation: together appears broken -


i want use ios 5's nifty row-movement calls animate tableview match model state changes, instead of older-style delete-and-insert.

changes may include both reordering , in-place updates, , want animate both, rows need reloadrowsatindexpaths.

but! uitableview appears plain wrong in handling of row reloads in presence of moves, if updated cell shifts position because of moves. using older delete+insert calls, in way should equivalent, works fine.

here's code; apologize verbosity compile , run. meat in domoves: method. exposition below.

#define thisworks @implementation scrambledlist // extends uitableviewcontroller { nsmutablearray *model; } - (void)viewdidload { [super viewdidload]; model = [nsmutablearray arraywithobjects: @"zero", @"one", @"two", @"three", @"four", nil]; [self.navigationitem setrightbarbuttonitem:[[uibarbuttonitem alloc] initwithtitle: #ifdef thisworks @"\u0001f603" #else @"\u0001f4a9" #endif style:uibarbuttonitemstyleplain target:self action:@selector(domoves:)]]; } -(ibaction)domoves:(id)sender { int fromrow = 4, torow = 0, changedrow = 2; // 2 = "before" position, docs say. // model changes happen... [model replaceobjectatindex:changedrow withobject:[[model objectatindex:changedrow] stringbyappendingstring:@"\u2032"]]; id tmp = [model objectatindex:fromrow]; [model removeobjectatindex:fromrow]; [model insertobject:tmp atindex:torow]; // tell table view [self.tableview beginupdates]; [self.tableview reloadrowsatindexpaths:[nsarray arraywithobject:[nsindexpath indexpathforrow:changedrow insection:0]] withrowanimation:uitableviewrowanimationright]; // again, index "before" state; tableview should figure out wants row 3 when time comes #ifdef thisworks [self.tableview deleterowsatindexpaths:[nsarray arraywithobject:[nsindexpath indexpathforrow:fromrow insection:0]] withrowanimation:uitableviewrowanimationautomatic]; [self.tableview insertrowsatindexpaths:[nsarray arraywithobject:[nsindexpath indexpathforrow:torow insection:0]] withrowanimation:uitableviewrowanimationautomatic]; #else // doesn't [self.tableview moverowatindexpath:[nsindexpath indexpathforrow:fromrow insection:0] toindexpath:[nsindexpath indexpathforrow:torow insection:0]]; #endif [self.tableview endupdates]; } #pragma mark - table view data source boilerplate, not interesting - (nsinteger)tableview:(uitableview *)tableview numberofrowsinsection:(nsinteger)section { return model.count; } - (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath { uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:@""]; if (cell == nil) cell = [[uitableviewcell alloc] initwithstyle:uitableviewcellstylesubtitle reuseidentifier:@""]; [cell.textlabel settext:[[model objectatindex:indexpath.row] description]]; [cell.detailtextlabel settext:[nsstring stringwithformat:@"this cell provided row %d", indexpath.row]]; return cell; } 

what code does: sets tiny model (small mutable array); when button pushed, makes small change middle element of list, , moves last element first. updates table view reflect these changes: reloads middle row, removes last row , inserts new row zero.

this works. in fact, adding logging cellforrowatindexpath shows although ask row 2 reloaded, tableview correctly asks row 3 because of insert once it's time update. huzzah!

now comment out top #ifdef use moverowatindexpath call instead.

now tableview removes row 2, asks fresh row 2 (wrong!), , inserts in final row-2 position (also wrong!). net result row 1 moved down two slots instead of one, , scrolling offscreen force reload shows how it's gone out of sync model. understand if moverowatindexpath changed tableview's private model in different order, requiring use of "new" instead of "old" index paths in reloads or model fetches, that's not what's going on. note in second "after" pic, third , fourth rows in opposite order, should't happen no matter cell i'm reloading.

before state

after 1 button push, delete-insert style

after 1 button push, move-style

my vocabulary has grown colorful cursing apple. should cursing myself instead? row moves plain incompatible row reloads in same updates block (as as, suspect, inserts , deletes)? can enlighten me before go file bug report?

i spent time playing code, , agree; looks doesn't work.

this whole area bit under-documented, don't can mix moverowatindexpath:toindexpath: reload methods. does in can mixed row-insertion , row-deletion methods. seems work if modify code exercise instead. so, might asking enhancement, not filing bug. either way, i'd send radar.


Comments

Popular posts from this blog

javascript - backbone.js Collection.add() doesn't `construct` (`initialize`) an object -

php - Get uncommon values from two or more arrays -

Adding duplicate array rows in Php -