TableView is the most commonly used control in iOS app. A lot of code is directly or indirectly associated with the tableView task, including providing data, updating TableView, controlling TableView behavior and so on. Here are some ways to keep your tableView code clean and structured.
IOS development exchange technology group: 563513413, no matter you are big bull or small white are welcome to enter, share BAT, Ali interview questions, interview experience, discuss technology, we exchange learning and growth together!
UITableViewController vs. UIViewController
The characteristics of TableViewController
Table View controllers can read table View data, set tabvleView editing mode, respond to keyboard notifications, and so on. The Table View Controller can also support “pull down refresh” by using UIRefreshControl.
Child View Controllers
TableViewController can also be added as a Child View controller to other ViewControllers, and then the tableViewController will continue to manage the tableView, The parentViewController manages other things we care about.
-(void)addDetailTableView
{
DetailViewController *detail = [DetailViewController new];
[detail setup];
detail.delegate = self;
[self addChildViewController:detail];
[detail setupView];
[self.view addSubview:detail.view];
[detail didMoveToParentViewController:self];
}
If you use the code above, you need to establish a connection between the Child View Controller and the parent View Controller. For example, if the user selects a cell in a tableView, the parentViewController needs to know about that in order to respond to the click time. So the best approach is for the Table View Controller to define a protocol that the parent View Controller implements.
@protocol DetailViewControllerDelegate
-(void)didSelectCell;
@end
@interface ParentViewController ()
@end
@implementation ParentViewController
//….
-(void)didSelectCell
{
//do something…
}
@end
Although this results in frequent communication between view Controllers, it ensures low coupling and reusability of the code.
Scattered code
When you’re dealing with tableViews, you have all sorts of different tasks that span the Model layer, the Controller layer, the View layer. So it’s important to spread out these different pieces of code to prevent the viewController from becoming a “landfill” for dealing with these issues. Keeping this code as separate as possible makes it more readable, maintainable and testable.
Bridge the gap between ModelObeject and Cell
In many cases, we need to submit the data we want to present in the View layer, and we need to maintain the separation between the View layer and the Model layer, so the dateSource in the tableView often overworks:
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Cell *cell = [tableView dequeueReusableCellWithIdentifier:@”Cell”];
[cell setup];
NSString *text = self.title;
cell.label.text = text;
UIImage *photo = [UIImage imageWithName:text];
cell.photoView.image = photo;
}
The dataSorce will become cluttered and should be grouped into cell categories.
@implementation Cell (ConfigText)
-(void)configCellWithTitle:(NSString *)title
{
self.label.text = title;
UIImage *photo = [UIImage imageWithName:title];
cell.photoView.image = photo;
return cell;
}
That way the dataSource would be very simple.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Cell *cell = [tableView dequeueReusableCellWithIdentifier:@”Cell”];
[cell configCellWithTitle:self.title];
return cell;
}
Reuse the cell
You can go one step further and make the same cell capable of displaying multiple ModelObjects. The first step is to define a protocol in the cell. Objects that you want to display in the cell must comply with this protocol. You can then modify the config Method of the classification to make the object comply with this protocol, so that the cell can accommodate different data types.
Handle cell state in cell
If you want to set the tableView’s behavior, such as changing the highlight state after the selected operation, you can use the delegate method in tableViewController:
-(void)tableView:(UITableView *)tableView didHighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
Cell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.label.shadowColor = [UIColor greenColor];
}
-(void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath
{
Cell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.label.shadowColor = nil;
}
However, when swapping out these cells or redesigning them, you still need to get used to the delegate method. The implementation of the detail in the cell is intertwined with the implementation of the detail in the delegate method, so the logic should be moved into the cell:
@implementation Cell
/ /…
-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
[super setHighlighted:highlighted animated:animated];
if(highlighted)
{
self.label.shadowColor = [UIColor greenColor];
}
else
{
self.label.shadowColor = nil;
}
}
@end
A delegate needs to know the different states of a view, but it doesn’t need to know how to modify the view or what properties need to be set to change the view from state to state. All the logic should be done by the view, providing only an API externally. This is an effective separation between the View layer and the Controller layer implementation code.
Handle different cell types
If there are different cell types in a tableView, the dataSource becomes bloated and difficult to manipulate. In the following code, there are two different cell types, one for displaying images and titles, and one for displaying stars. To separate the code that works with different cells, the dataSource method simply performs the different cell’s own setup methods.
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
BOOL isStarRank = self.keys[(NSUInteger)indexPath.row];
UITableViewCell *cell;
if(isStarRank)
{
cell = [self setupStarCell];
}
else
{
cell = [self setupDefaultCell];
}
}
-(StarCell *)setupStarCell
{
//do something…
}
-(UITableViewCell *)setupDefaultCell
{
//do something…
}
Edit the TableView
TableView provides convenient editing functions, the ability to delete and move cells. In these events, the tableView’s dataSource gets notifications through delegate methods, so there are often changes to the data in these delegate methods, and modifying the data is clearly the task of the Model layer. The model should provide interfaces for deleting, sorting, and so on, so that it can be called via the dataSource method. Thus the Controller acts as a mediator between the View and the Model without knowing the implementation details of the Model layer. At the same time, the logic of the model becomes easier to test because there is no task to mess with the viewController.
conclusion
TableViewController and other controllers should act as coordinators and intermediaries between the Model and View, and should not care about tasks belonging to the View or Model layer. With this in mind, make the delegate and dataSource smaller and contain only formulaic code.
Not only does it reduce the size and complexity of the tableViewController, but it also puts the domain logic and interface logic into related classes, wraps implementation details in simple APIS, and ultimately improves code readability and code coordination.