Editing mode of UITableView
Implement the simple deletion function of UITableView (the delete button appears with the left swipe)
First, the UITableView needs to enter editing mode. Implement the following method, and even if you don’t write any code, you will enter editing mode:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
}
When the Delete button that appears, the above method will be called, so some logic for performing deletion operations can be implemented in this method, such as:
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Modify the model first
[ removeObjectAtIndex:];
// Update the view later
[ deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
If you want to modify the text of the Delete button, you can implement the following proxy method:
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"Delete";
}
This method can quickly implement the simple deletion method that comes with the system. When the UITableView enters the editing mode (the Delete button appears), continue to click on the cell and automatically cancel the editing mode, which is very convenient.
In some applications, you may see that when the user clicks a button, a red circle will appear on the left side of the cell in the UITableView, and there is a - inside. When clicking this -, the left swipe effect will appear and the Delete button will appear. How to achieve it?
UITableView has an editing property. If this property is set to YES, it will enter editing mode; similarly, if set to NO, it will exit.
In the example mentioned above, when the user clicks the button, it enters the edit mode. The default form of the edit mode is to have a red - on the left. When the user clicks, the Delete button appears with its own left swipe effect. When the user clicks the Delete button, the method mentioned above will be called.
So after saying so much, you just need to set editing to YES and implement the above method to achieve the above effect.
Reuse of UITableViewCell
UITableViewCell If in the tableView:cellForRowAtIndexPath: method, like other classes, use the following method:
UITableViewCell *cell = [[UITableViewCell alloc] init];
= @"hello";
...
Although this can be displayed correctly, there are problems with performance.
Apple actually helped us improve performance. Assuming that you want to display 200 rows of data, if you create 200 cells at the same time, it will undoubtedly be very performance-consuming and not much meaning - because some cells have not been displayed at all.
Therefore, when using UITableView, the tableView:cellForRowAtIndexPath: method will only be called when the cell is about to be displayed. That is to say, if there are 200 rows of data, only the cells we can see will be created, while those data that cannot be seen will not be created.
For example, 5 cells can be displayed at the same time (numbered from 0 - 4) on the mobile phone screen. Then when the user slides up the tableView, the 6th cell will appear, and the 1st cell has not disappeared yet, so 6 UITableViewCells will be created at this time. When the 7th cell appears, the 1st cell will completely disappear from the screen. At this time, the UITableViewCell object will be destroyed and the 7th cell will be created. And so on, when a new cell appears, a new cell will be created and the disappearing cell will be destroyed.
Although there is no need to create 200 cells at the same time, there will still be performance problems when constantly creating and destroying cells.
A better way Apple provides is to reuse the cell rather than destroy it.
Every time a new cell appears (that is, when the tableView:cellForRowAtIndexPath: method is executed), you should not create a cell directly, but you should search for whether there is a reusable cell in the buffer pool. If there is, then reuse the cell; if there is no, create a cell. In this way, no matter whether the data is 200 rows, 2000 rows or 20000 rows, what is actually created is only the number of cells visible to the screen.
As for the example above, when the 7th cell is about to appear and the 1st cell disappears, the first cell will not be destroyed at this time, but will be placed in the buffer pool and wait for reuse. At this time, the 7th cell will first go to the buffer pool to find whether there is a reusable cell. If there is a (that is the disappearing first cell), it will be reused instead of recreating. In this way, one disappears and this will be reused next time, which will ensure that the minimum number of cells is created and the needs can still be met.
To implement cell reuse, the following methods can be used:
Use the code to create a new cell yourself:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString * const cellIdentifier = @"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
= [UIColor greenColor];
}
= @"hello";
return cell;
}
Here are a few points to note:
When the cell is nil and needs to create a new cell, the initWithStyle:reuseIdentifier: method is used instead of the init method. This is because when creating a new cell, an identifier needs to be bound, so that the same type that can be reused can be found when reusing it. If the init method is used, there is no bound identifier, so that the corresponding reusable cell cannot be successfully found during reuse.
Generally, in if(!cell), that is, when a new cell is created, some properties that only need to be initialized once are initialized, rather than outside this bracket. Because it will be executed multiple times outside the brackets, these properties do not need to be set multiple times. Similarly, if different cells need to set different attributes or data, they need to be executed outside the brackets, because every time the cell appears outside the brackets, it will be executed, which ensures that the unused cells correspond to different attributes or data. If the code that should have different properties set in different cells is placed in brackets, the data will not be overwritten again when reusing the cell, and incorrect results will occur, and the problem of data redundancy in the morning.
Another way is to automatically create a new cell:
NSString * const cellIdentifier = @"CellIdentifier";
- (void)viewDidLoad
{
[super viewDidLoad];
[ registerClass:[UITableViewCell class] forCellReuseIdentifier:cellIdentifier];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
= @"hello";
return cell;
}
First, you need to register a class, which means telling the tableView. First, go to the buffer pool to find whether there is a reusable cell. If there is, take it and reuse it; if there is no, then automatically generate a cell based on the previously registered UITableViewCell class, and bind it to the reuse identifier.
This method saves us from manually creating cells ourselves, but there are also shortcomings: the styles provided by Apple to us cannot be used except for the default ones.
The first method is to create the cell manually, using initWithStyle:reuseIdentifier: You can pass in different styles to create the cell provided by Apple, but it cannot be implemented in the second method.
The second method is often used in our custom cell. Although we cannot use more styles with the system, we can first register the class of the customized cell (change the UITableViewCell with a custom cell), and then first go to the buffer pool to find if there is a reusable cell. If not, create the cell based on the registered cell and bind the identifier. Of course, when using dequeueReusableCellWithIdentifier:, the returned Cell type should also be a custom Cell type.
The registered one can not only be Class, but also nib, which means that the cell created through xib can be registered, which is the same as the above method.
You can also set the prototype cell identifier directly through the Storyboard, and use the cell directly in dequeueReusableCellWithIdentifier: without registering in advance or manually creating the cell.