-
Notifications
You must be signed in to change notification settings - Fork 1
DD 4.7. Moving Cells and Sections in Table Views
You want to move and shuffle cells and sections inside a table view, with smooth and intuitive animations.
Use the moveSection:toSection: method of the table view to move a section to a new position. You can also use the moveRowAtIndexPath:toIndexPath: method to move a table view cell from its current place to a new place.
To demonstrate this, let’s create a table view and preload it with three sections, each of which contains three cells of its own. Let’s start with the implementation file of our view controller:
#import "ViewController.h" static NSString *CellIdentifier = @"CellIdentifier"; @interface ViewController () <UITableViewDelegate, UITableViewDataSource> @property (nonatomic, strong) UITableView *myTableView; @property (nonatomic, strong) NSMutableArray *arrayOfSections; @end
Our view controller will become the data source of the table view. The table view has sections, and each section has rows. We will keep an array of arrays; the first array is our array of sections, which will itself contain other arrays that contain our cells. The ar rayOfSections defined on top of the implementation file of our view controller will bear that responsibility. Let’s go ahead and populate this array:
- (NSMutableArray *) newSectionWithIndex:(NSUInteger)paramIndex cellCount:(NSUInteger)paramCellCount{ NSMutableArray *result = [[NSMutableArray alloc] init]; NSUInteger counter = 0; for (counter = 0; counter < paramCellCount; counter++){ [result addObject:[[NSString alloc] initWithFormat:@"Section %lu Cell %lu", (unsigned long)paramIndex, (unsigned long)counter+1]]; } return result; } - (NSMutableArray *) arrayOfSections{ if (_arrayOfSections == nil){ NSMutableArray *section1 = [self newSectionWithIndex:1 cellCount:3]; NSMutableArray *section2 = [self newSectionWithIndex:2 cellCount:3]; NSMutableArray *section3 = [self newSectionWithIndex:3 cellCount:3]; _arrayOfSections = [[NSMutableArray alloc] initWithArray:@[ section1, section2, section3 ] ]; } return _arrayOfSections; }
We shall then instantiate our table view and implement the necessary methods in the UITableViewDataSource protocol to populate our table view with data:
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{ return self.arrayOfSections.count; } - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ NSMutableArray *sectionArray = self.arrayOfSections[section]; return sectionArray.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = nil; cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; NSMutableArray *sectionArray = self.arrayOfSections[indexPath.section]; cell.textLabel.text = sectionArray[indexPath.row]; return cell; } - (void)viewDidLoad{ [super viewDidLoad]; self.myTableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; [self.myTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; self.myTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.myTableView.delegate = self; self.myTableView.dataSource = self; [self.view addSubview:self.myTableView]; }
Showtime! Shall we first have a look at how sections can be moved to a new position? Let’s write a method that will move Section 1 to Section 3:
- (void) moveSection1ToSection3{ NSMutableArray *section1 = self.arrayOfSections[0]; [self.arrayOfSections removeObject:section1]; [self.arrayOfSections addObject:section1]; [self.myTableView moveSection:0 toSection:2]; }
Moving cells is very similar to moving sections. To move cells, all we have to do is use the moveRowAtIndexPath:toIndexPath: method. Remember that you can move a cell from one section to the same section, or to a new section. Let’s make it easy and move Cell 1 in Section 1 to Cell 2 in the same section and see what happens:
- (void) moveCell1InSection1ToCell2InSection1{ NSMutableArray *section1 = self.arrayOfSections[0]; NSString *cell1InSection1 = section1[0]; [section1 removeObject:cell1InSection1]; [section1 insertObject:cell1InSection1 atIndex:1]; NSIndexPath *sourceIndexPath = [NSIndexPath indexPathForRow:0 inSection:0]; NSIndexPath *destinationIndexPath = [NSIndexPath indexPathForRow:1 inSection:0]; [self.myTableView moveRowAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; }
So what is going on in this code? Well, we need to make sure our data source holds the correct data that needs to be displayed in our table view after we have moved the cells around, so we remove Cell 1 in Section 1 first. That moves Cell 2 to Cell 1, and Cell 3 to Cell 2, with a total of 2 cells in the array. Then we will insert Cell 1 into Index 1 (second object) of the array. That will make our array contain Cell 2, Cell 1, and then Cell 3. After that is done, we have actually moved the cells in our table view.
Let’s make this a bit more difficult. How about moving Cell 2 in Section 1 to Cell 1 in Section 2?
- (void) moveCell2InSection1ToCell1InSection2{ NSMutableArray *section1 = self.arrayOfSections[0]; NSMutableArray *section2 = self.arrayOfSections[1]; NSString *cell2InSection1 = section1[1]; [section1 removeObject:cell2InSection1]; [section2 insertObject:cell2InSection1 atIndex:0]; NSIndexPath *sourceIndexPath = [NSIndexPath indexPathForRow:1 inSection:0]; NSIndexPath *destinationIndexPath = [NSIndexPath indexPathForRow:0 inSection:1]; [self.myTableView moveRowAtIndexPath:sourceIndexPath toIndexPath:destinationIndexPath]; }