Click to view author Pinterest address
The purpose of writing this article today is to provide a way to help you solve the problem of very bloated controller, to thin the controller.
If you have a project on hand, you might as well open the project and see how many lines of your controller code are there? Take a look at TableView proxy method Cellforrow and Heightforrow code is also very much? The code is mixed with switch and a lot of if Esle's judgment logic. Post-maintenance Look at these if else is not particularly irritable? Especially in the maintenance of their predecessors written code, and have not commented on the mess, there is more want to curse the impulse? Don't be afraid, here is to provide you with a solution, so that your TableView agent method no longer the headache of the If else judgment logic, so that your controller code volume greatly reduced, and later maintenance costs are greatly reduced.
Before we talk about concrete solutions, let's review MVC and MVVM in a nutshell, because today's theme is also related to MVVM. MVC pattern Everybody is familiar with, is Model,view,controller three layer, model is responsible for the data layer, controller is responsible for the business logic layer, View is responsible for interface display layer, model and view through controller to achieve bridge interaction, The program is very extensible and benefits a lot. However, MVC also has its own flaws, that is, the controller is too bloated, if you want to locate a point in the controller is a more troublesome thing.
Then why is the controller so large, because the cell judgment logic in the TableView proxy method is all in the controller, and the network request is also initiated in the controller, there are some other business logic. Is there any higher mode? The MVVM pattern is an upgraded version of the MVC pattern. The model in
MVVM is still responsible for the data layer, and the controller is solely responsible for the display and update of the view, regardless of other business logic. View is still responsible for the interface display. So who is responsible for the business logic that viewcontroller before it? We create a new ViewModel layer, between the Viewcontroller layer and the model layer, which is dedicated to the business logic, as well as the network request. Viewcontroller gets the data from the ViewModel and then shows it on the view, it does not deal directly with the model layer, and the model layer directly deals with the ViewModel layer.
Attach a classic GIF picture below to help you understand the relationship between the two. Well, the front is to review some of the relevant knowledge, in order to understand the next content to do the basis, if you want to learn more about MVC,MVVM can be found online, this kind of article a lot.
Everyone may wonder what is oriented to the super-class programming, in fact, is around the inheritance of this feature, the subclass cell inherits the parent class cell, the object for the parent class to program, and finally to the Controller of the TableView to thin body, is not only the TableView optimization, New ViewModel with MVVM can draw code from a large portion of the controller. It's not clear that it's okay, but here's a very detailed description to let you know. ^_^ me the following first common use of the controller TableView agent method of writing, to paste it out, and then use a new type of super-class to paste it out, we can obviously realize the advantages of using a super-class approach.
Old Way public writing
for Super class programming
See here, there may be people spit groove, the new style is less than the old-fashioned more than 10 line? In fact, this is not the case, the first demo I only wrote three cells as an example, the real project very few a controller only three cell it? The more cells the controller has, the more obvious the benefits are, since in the late stages no matter how many cells are added, the code in the proxy method of the controller TableView will almost never increase, equivalent to building a template that needs to be configured in the newly added cell's internal configuration. Second, real projects are not as simple as business logic? There must be a lot of other logical code nested in the If else, which makes the tableview look bloated.
benefits for Hyper-class programming:
1. The controller is thin. [Controller internal code volume is greatly reduced, logic clearer]
2. Later maintenance costs are greatly reduced. [Later if you want to add or remove a cell, you just need to create or delete a subclass of cell, add or remove a identifier in ViewModel, the controller almost no code added]
The disadvantages of facing a superclass:
1. Create more cell files and a ViewModel file, the packet size will increase in response.
Here is a detailed explanation of what you might want to do with the super-class programming:
First, create a new parent class that inherits from UITableViewCell cell
#import <UIKit/UIKit.h> #import "ResponseNewProgrammeData.h" #import "NewProgrammeCellHeightProtocol.h" //subclass requires Proxy with callback event @protocol newprogrammetableviewcellprotocol <nsobject>- (void) cell1didselectedrightbutton;-(void) cell2didselectedrightbutton;-(void) Cell3didselectedrightbutton;@end @interface newprogrammebasecell : UITableViewCell < Newprogrammecellheightprotocol>@property(nonatomic,Weak)ID<NewProgrammeTableViewCellProtocol> delegate;@property(nonatomic,Strong) Responsenewprogrammedata * RESPONSENEWPROGRAMMEDATA;@end
First, you want to include the controller's data source, because the child class cell's UI, and so on, depends on the data source of the parent class.
Second, to implement the Newprogrammecellheightprotocol protocol, as a computational height, the specific usage in the 2nd explanation.
Finally, if a sub-cell has a click event that requires a callback operation, it can write a protocol Newprogrammetableviewcellprotocol as a property, and in the Controller, delegate points to the controller as a callback.
Second, create a new Newprogrammecellheightprotocol
#import <Foundation/Foundation.h>//针对cell的高度写的协议@protocol NewProgrammeCellHeightProtocol <NSObject>@optional+ (BOOL)isStaticCell;+ (float)cellHeight;@end
- (BOOL) The Isstaticcell method is used in subclasses, if the current cell is a highly fixed static cell, returns Yes, and returns a fixed height in the Cellheight method. Otherwise, no can be returned, and there is no need to write the + (float) Cellheight method. These two methods are used in the Heightforrow method of the controller to calculate the current cell height.
Three, all the cells required for the new controller, and inherit from the parent class cell
#import "NewProgrammeCell1.h" @interface NewProgrammeCell1 ()@property(nonatomic,Weak)Iboutlet UILabel*lblname;@end @implementation NewProgrammeCell1 @synthesizeResponsenewprogrammedata = _responsenewprogrammedata;-(void) Setresponsenewprogrammedata: (Responsenewprogrammedata *) responsenewprogrammedata{_responseNewProgrammeData = Responsenewprogrammedata; Self. Lblname. Text= _responsenewprogrammedata. String1;} + (BOOL) isstaticcell{return YES;} + (float) cellheight{return -;} - (ibaction) Didpressedpush: (ID) Sender {if( Self. Delegate&& [ Self. DelegateRespondstoselector:@selector(Cell1didselectedrightbutton)]) { [ Self. DelegateCell1didselectedrightbutton]; }}@end
The cell's height is fixed static, so the Isstaticcell method returns Yes,cellheight returns the height.
The cell can get the controller data source, according to their own needs to obtain data.
The Didpressedpush method of this cell is to simulate a callback to the controller that requires a click event.
The configuration of the other cells is roughly the same.
Iv. Create a new ViewModel file
#import "NewProgrammeViewModel.h" Static NSString*ConstNewprogrammecell1identifier = @"NewProgrammeCell1";Static NSString*ConstNewprogrammecell2identifier = @"NewProgrammeCell2";Static NSString*ConstNewprogrammecell3identifier = @"NewProgrammeCell3"; @implementation newprogrammeviewmodel - (Nsarray*) getidentifierlist{return@[newprogrammecell1identifier, Newprogrammecell2identifier, Newprogrammecell3identifier];} - (void) requestdata{ Self. Responsenewprogrammedata= [[Responsenewprogrammedata alloc] init];}@end
ViewModel is responsible for configuring the cells that the controller needs to register and the cell,getidentifierlist that are actually displayed to return all the cells that need to be registered. Because the cells of some pages are not fixed, they may be configured dynamically based on the data source. At the same time, ViewModel also responsible for network request data parsing and other business logic code. The ViewModel here is equivalent to the FAT model in the MVVM pattern, which not only handles network requests, but also handles other business logic such as the configuration of the page UI, so that the controller is not bloated.
Five, do the corresponding code configuration in the controller
- (void) configtableviewcell{ for(NSString* Identifer in [ Self. ViewModelGetidentifierlist]) {[ Self. TableViewRegisternib:[uinib Nibwithnibname:identifer Bundle:Nil] Forcellreuseidentifier:identifer]; }}#pragma mark-uitableviewdelegate- (Nsinteger) TableView: (UITableView*) TableView numberofrowsinsection: (Nsinteger) section{return Self. ViewModel. Getidentifierlist. Count;} - (UITableViewCell*) TableView: (UITableView*) TableView Cellforrowatindexpath: (Nsindexpath*) indexpath{NSString* Cellidentifier = [ Self. ViewModel. GetidentifierlistObjectatindex:indexpath. Row]; Newprogrammebasecell * cell = [TableView dequeuereusablecellwithidentifier:cellidentifier]; Cell. Delegate= Self; Cell. Responsenewprogrammedata= Self. ViewModel. Responsenewprogrammedata;returnCell;} - (CGFloat) TableView: (UITableView*) TableView Heightforrowatindexpath: (Nsindexpath*) indexpath{NSString* Cellidentifier = [ Self. ViewModel. GetidentifierlistObjectatindex:indexpath. Row]; class<newprogrammecellheightprotocol> Cellclass = nsclassfromstring (cellidentifier);CGFloatHeight =0;if([Cellclass Isstaticcell]) {height = [cellclass cellheight];returnHeight }Else{Newprogrammebasecell * cell = (newprogrammebasecell*) [ SelfTableview:tableview Cellforrowatindexpath:indexpath]; Height = [cell. ContentviewSystemlayoutsizefittingsize:uilayoutfittingexpandedsize]. Height;returnHeight }}
First, to instantiate the ViewModel object, get all the cells that need to be registered in the Configtableviewcell method, and traverse the registration.
Second, in the Cellforrow proxy method, get all registered cell identifier from the ViewModel object, and then get the assignment from TableView to the parent class cell. And then to do some assignment for the parent cell, that is to call the sub-class cell, make full use of polymorphic characteristics.
Finally, in the Heightforrow proxy method, the identifier of all registered cells is obtained according to the ViewModel object, then the class object of the object subclass cell is reflected by identifier, then the protocol method in the cell is called to calculate the height.
Here, for the super-class programming slimming basic ideas are finished, here is a complete demo click to download the source code, if you like to move small hands to praise, thank you
iOS Development Learning Exchange QQ Group: 529560119
iOS controller slimming-for Super class programming