Re-ordering table view cells in iOS application

There are some situations in iOS applications where we want to drag a particular row or cell of a UITableView to other occupied row or cell. Which means we need to drag and drop a cell at a particular cell index. UITableView is powerful enough to handle this feature with smart animations by using its data source protocol. But we con’t drop a cell at an empty cell space. This is called the Re-ordering feature in UITableView cells. In this tutorial I will explain how to achieve this feature within iOS application. Before we start coding we need to know, two important UITableView data source protocol methods.

(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath

The first data source method tableView:canMoveRowAtIndexPath: asks the data source whether a given row can be moved to another location in the table view. If we need the particular row to be moved to other location then we return YES to that particular row otherwise return NO. This method allows the delegate to specify that the reordering control for a specified row not be shown. By default, the reordering control is shown if the data source implements the tableView:moveRowAtIndexPath:toIndexPath: method.

The second data source method tableView:moveRowAtIndexPath:toIndexPath: Tells the data source to move a row at a specific location in the table view to another location. The tow parameters fromIndexPath and toIndexPath indicate source and destination cell indexes. When we drag any cell then UITableView object sends this message to the data source to perform the required changes.

Open Xcode, create a new project with single view application option and name it as ReorderingCells. Now make ViewController class as the root view of the navigation controller by adding UINavigationController in AppDelegate file. Open .xib file of ViewController, add UITableView outlet, connect it with corresponding object in .h file and register with UITableView data source and delegate protocols.

Now open viewDidLoad method for .m file and add the following code.

self.dataArray = [[NSMutableArray alloc] initWithObjects:@"Drag to reorder 1",@"Drag to reorder 2",@"Drag to reorder 3",@"Drag to reorder 4",@"Drag to reorder 5",nil];
self.title = @"Reordering Rows";
UIBarButtonItem *editButton = [[UIBarButtonItem alloc] initWithTitle:@"Edit" style: UIBarButtonItemStyleBordered target:self action:@selector(editButton:)];
[self.navigationItem setRightBarButtonItem:editButton];

Here dataArray object contains the data to be loaded in the table view. Now we need to implement the action method of edit button as follows.

(void)editButton:(id)sender
{
    if(self.editing)
        {
                [super setEditing:NO animated:NO];
                [aTableView setEditing:NO animated:NO];
                [aTableView reloadData];
                [self.navigationItem.rightBarButtonItem setTitle:@"Edit"];
                [self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStylePlain];
        }
        else
        {
                [super setEditing:YES animated:YES];
                [aTableView setEditing:YES animated:YES];
                [aTableView reloadData];
                [self.navigationItem.rightBarButtonItem setTitle:@"Done"];
                [self.navigationItem.rightBarButtonItem setStyle:UIBarButtonItemStyleDone];
        }
}

After tapping the edit button, UITableView will be allowed to make any changes like deleting, inserting etc and edit button transforms to Done button. Now add the basic data source methods of table view numberOfRowsInSection and cellForRowAtIndexPath as follows.

(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
        return [self.dataArray count];
}

(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   
    static NSString *CellIdentifier = @"Cell";
   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
       
        cell.textLabel.text = [self.dataArray objectAtIndex:indexPath.row];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    return cell;
}

Compile and run the code you will see the following screens, one is before tapping edit button and other one is after tapping edit button.




We have not added the re-ordering feature till now. To support this feature just implement the above mentioned data source methods as follows.

(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
        NSString *item = [self.dataArray objectAtIndex:fromIndexPath.row];
        [self.dataArray removeObject:item];
        [self.dataArray insertObject:item atIndex:toIndexPath.row];
}

Now build and run the code, you will see the following screen after tapping edit button.

Observe that, in place of accessory view we have got a new view called “re-order” bar. Now tap on that bar and hold, then it will allow you to drag and drop any cell to other cell location.

Leave a Reply

Your email address will not be published. Required fields are marked *