In my previous two articles, I have introduced and discussed the definition and construction method of M layer in MVC framework respectively. The purpose of this article is to take an in-depth look at how we should build the control layer. The control layer is the link between the view layer and the model layer. Now there are also a lot of articles advocating the so-called control layer or weakening the role of the control layer, think this part is a chicken ribs, he will make the application become bloated. Is there a need for him? In general application scenarios, we need to present various interfaces to the user, and then the user through some operations to achieve a certain goal. Three keywords can be extracted from the above scenario: present, action and target. What we want to present and what we want to achieve must be achieved through specific operations, that is to say, through operations to drive the constant change of the interface and the continuous achievement of service objectives, operation is the link between the interface and the target. To represent this real-world scenario, the same should be true in software modeling and design implementations. I think this is the original intention of application model design of MVC framework. In the MVC framework, V is responsible for rendering, C is responsible for operations and M is responsible for objectives. And this design has the following additional considerations:
- View interfaces are constantly updated and optimized according to the user experience. Even the two versions of the same function are completely different, or some view interfaces are scattered to other view interfaces, or the original scattered view interfaces are aggregated into a new view interface. That is, the view rendering part is the part with the most variation and the least persistence.
- The model (service) is relatively stable in that it only provides some concrete underlying business services, and these services are more an upgrade of service level than a complete change of service. Therefore, the model section is the one with the least variation and the longest persistence.
- In general, we need to invoke more than one service to control the operations on the view interface, or the presentation on different interfaces may be supported by the same service. So instead of forcing a one-to-one binding between interface rendering and service objectives, we need to decouple the rendering from the model.
The introduction of the control layer is to solve these contradictions above, it reduces the association between view and model to a minimum, and at the same time, it also solves the contradiction of changeability and invariability. The control layer is a mediator (refer to the mediator pattern in the design pattern) and we should leave the specific operations to the control layer, which drives the presentation of views and the provision of services. This seems like an optimal solution.
Controller – The demarcation boundary of functionality
So what other characteristics should the control layer have besides the ability to process operations and the ties that enable the connection between the view and the model?
From the user’s point of view, an application is actually a collection of functions that provide some capability. Each function has a corresponding display effect and provides a corresponding service. And some features can be broken down into more small features. For developers, functionality is a vertical slice of the application. Developers prefer to refer to it as a modular unit or feature. Each function can provide a complete unit from the interface to the business logic, and functions are generally independent of each other. Functions usually interact with each other through interfaces. The advantage of this design is conducive to reduce the dependency and coupling between modules in the system, and also conducive to the division of labor cooperation and task division between programmers. Therefore, functional partitioning is a very good way to construct an application from both a user and a developer’s perspective. The presentation of functionality in design can be understood as being done through the view, while the implementation of business logic is done through the model layer, so there must be an entity to link the two and have the ability to co-ordinate and control. This entity is best implemented and acted upon by the controller of the control layer. Therefore, in practice, the implementation and division of functions are usually built in units of controllers, which work in the control layer. That is to say, when we realize a function, we usually establish a corresponding controller for this function to achieve, the controller is responsible for the construction of the view and the invocation of the business model, and the framework under the thought is the classic MVC framework!
The realization of control layer in each platform
At present, the mainstream iOS and Android mobile development platforms provide MVC application framework, especially for the implementation of the control layer is almost the same ability and way. The entities of the control layer on both platforms are implemented by corresponding controller classes (called UIViewController for iOS, Activity for Android). And both platforms provide process methods for building controllers, rendering views, and destroying controllers. This implementation mechanism is a very typical template method design pattern, in the base class defines a controller in the life cycle of each part of the call method, you only need to override these methods in the derived class to complete the controller life cycle of each part of the action or processing. To handle interactions or calls between controllers, the system provides a navigation stack management class. The navigation stack is responsible for the entry and exit of each functional controller, while managing all controllers.
Android activities actually encapsulate functions more thoroughly than iOS UIViewController. Activities have the ability to be invoked across processes, so they are more powerful as componentization, and the coupling between controllers is very low. The transfer of parameters between controllers is achieved through serialization and deserialization. However, this has become a disadvantage in some aspects. In order to solve this problem, The Android system provides a class called Fragment, which is a lightweight controller compared to Activity. The purpose is to solve the problem that some large functions need to be separated into multiple sub-functions and solve the problem of parameter transfer between functions.
Introduction to the iOS View Controller life cycle.
Front in the realization of the controller in the control layer are introduced as well as the controller of the life cycle, and also introduces the corresponding relation between function and controller, the controller is the tie that link between view and business model, so the controller must be within the life cycle is responsible for the building and management of the views of present business model, processing user operations, as well as the call, etc. To achieve these capabilities, a template approach to the design pattern is adopted in the controller to solve this problem. What I want to focus on here is the implementation of the iOS view Controller to address these issues. We know that the view controller in iOS is called UIViewController. There are a number of methods defined in this class that describe the state of the controller, and each class derived from the view controller can override the corresponding methods to perform logical processing in the corresponding state of the view controller. Here’s a list of common ways to do this and what you should do in that state:
-
Init this is the controller constructor
-
LoadView completes view construction in this method. You don’t need to override this method if your view is built from a Storyboard or XIB, but you should override this method if your view is built from code. The default implementation of the controller will find the layout description of the view in the associated Storyboard or XIB, if it does, it will build the view to be presented based on the layout description, if not, it will build a default empty view.
-
The viewDidLoad method is called to indicate that the view has been built. This is where the model layer business model objects are built, as well as some event bindings, delegate Settings, and so on. If you are building a layout from code, it is not recommended to build the view layout here and instead write the code in loadView.
-
ViewWillAppear is called when the view is about to render, the view is only rendered when a view is added to a UIWindow, so this method is called before the view is added to the window.
-
The viewDidAppear view has been rendered to the window, and this method is called after the view is added to the window.
-
Called when the viewWillDisappear view is about to be deleted from the window.
-
Called when the viewDidDisappear view has been deleted from the window.
-
Dealloc is called before the controller is destroyed.
How do you build your control layer
How to build a control layer is a very broad proposition, need specific business analysis. Although there is always some common ground and methodology to be found, a good design approach will not have the problem of so-called controller code bloat. The framework idea of MVC itself is very excellent. When there is a problem, the first thing to consider is not to replace the existing framework, but to optimize the existing code and logic from the point of view of design, so that the whole system can achieve an optimal combination.
1. Division of functional folders
As you can see from the previous discussion, a view controller is the basic unit of function implementation, and a view controller is the carrier of a function. An application has multiple functions, and some similar functions usually form a function set. For example, the registration process of an application may be divided into several steps. For example, the Settings of various features of the user system; For example, the payment portion of an order and so on. To manage feature sets, you can place all features under certain feature sets into a specific directory. The final form of an application feature directory tree:
By compartmentalizing functionality, you can help retrieve functionality and make your application more understandable. Operating systems and folders on XCODE are a very common way to build a feature tree directory. Pay attention to the following points when dividing the functional directory tree.
- If some functionality is basic and may be used by several other functions, it can be distilled and stored in a specific folder (the folder can be named Common or Base or something like that). For example, you can derive your own controller base classes from the controller provided by the system, and then store these base classes in a separate folder.
- It is best not to create separate folders for each function. Some cases will appear in each VC.h and.m files to create folders for him, in fact, this is not desirable, because it may lead to too many folders and become more troublesome to locate. We should gather together with similar functions to create folders for management.
- Sometimes a certain function set may be too large, at this time, we can classify the function set again and establish sub-folders for management. The folder division may not be a single-layer tree structure or a multi-layer tree structure.
- There are two types of folders that can be created in XCODE: real (New Group with Folder) and virtual (New Group) folders. It is recommended to create virtual folders, for the sake of easy management, because it is sometimes possible to move controller files from one folder to another (function transfer). If you create a real folder, it is possible that the real folder in which the controller is located will not correspond to the folder in your project. This does not happen with virtual folders.
- There are many different ways to divide functional folders. You can divide folders from a business perspective, or you can divide folders from the presentation of your application interface. For example, in an application, we have a product display system, a payment system and a user system, and our interface display may be a four-tab interface composed of home page, shopping cart and me at the bottom. At this time you can be divided into goods, payment, user folder according to the business, also can be divided into home page, shopping cart, my folder according to the display interface. Because this folder divides and did not have standard to see your individual be fond of and decided. The only requirement is that the functionality within the same folder should be cohesive, meaning that on a given day it can even be pulled out to build a subproject without making a lot of changes.
2. Base controllers and derived classes.
An app will always have its own unique design style, such as the text and font in the title bar and the background. Or we need to monitor the application as a whole, such as burying the interface entry and exit. So we need the basic controller that the system provides UIViewController, UITableviewController, UINavigationController, UICollectionViewController above controller such as the construction of a derived class, which is to achieve a particular function of the controller should not above is derived from the system controller and above the base class and derived from the derivative controller. This allows us to add our own business or interface logic to our derived controller base class, as well as implement some AOP aspects of processing. For example, we could build a derived base class of UINavigationController to do some special processing before or after controller push and pop. But then there is the problem, because the OC language does not support multiple inheritance. We might want to create a derived class of the four system controllers above and add the same code in similar places, such as a similar code in viewDidLoad. To do this, you need to add four copies of the same code such as:
@interface XXXBaseViewController:UIViewController @end @implementation XXXBaseViewController -(void)helperfn { //.. Implement specific extension functionality. } -(void) viewDidLoad { [super viewDidLoad]; [self helperfn]; / / call the extension methods} @ end @ interface XXXBaseNavigationController: UINavigationController @end @implementation XXXBaseNavigationController -(void)helperfn { //.. Implement specific extension functionality. } -(void) viewDidLoad { [super viewDidLoad]; [self helperfn]; // call extension method} @end //... Respectively UITableviewController, UICollectionViewController, etc will be duplicated code.Copy the code
This is obviously an inefficient solution, since we might need to change the Helperfn method four times once the requirements change. How to solve this problem? We divided it into two scenarios:
All functionality extensions do not require extended attributes
In this case, since the extended methods don’t use instance properties of the object, we can implement these common functions by creating a Category method, we can create a Category for UIViewController, and implement common methods in that Category, This shared classification method is then called at a specific location for each derived class. The specific code is as follows:
@interface UIViewController(XXXExtend) -(void)helperfn; @end@implementation UIViewController(XXXExtend) // implementation -(void)helperfn {// implementation of a specific function. } @end @interface XXXBaseViewController:UIViewController @end @implementation XXXBaseViewController -(void) viewDidLoad { [super viewDidLoad]; [self helperfn]; / / call the extension methods} @ end @ interface XXXBaseNavigationController: UINavigationController @end @implementation XXXBaseNavigationController -(void) viewDidLoad { [super viewDidLoad]; [self helperfn]; // call extension method} @end //... Respectively UITableviewController, UICollectionViewController derived class.Copy the code
Of course, you might find it troublesome to add code at a specific point in each derived class. You can also use method Swizzle to solve this problem. You can implement code substitution in the +load method of the class. Here is the concrete code implementation:
@interface UIViewController(XXXExtend) @end @implementation UIViewController(XXXExtend) -(void)helperfn { } -(void)viewDidLoadXXXExtend { [self viewDidLoadXXXExtend]; [self helperfn]; } +(void)load { Method originalMethod = class_getInstanceMethod(self, @selector(viewDidLoad)); Method swizzledMethod = class_getInstanceMethod(self, @selector(viewDidLoadXXXExtend)); method_exchangeImplementations(originalMethod, swizzledMethod); } @end @interface XXXBaseViewController:UIViewController @end @implementation XXXBaseViewController @end @interface XXXBaseNavigationController: UINavigationController @end @implementation XXXBaseNavigationController @end //... Respectively UITableviewController, UICollectionViewController derived class.Copy the code
2. There are cases where attributes need to be extended.
If you have attributes in your base class extension method, then we know that compile-time extension attributes are not supported in the class (but run-time extension attributes are supported). In addition to using methods that extend attributes at operation time, you can extract the shared methods and attributes separately and have them implemented by a helper class, which is then created in the initialization method of the derived base class, and delegate subsequent methods to the helper class. The specific structure design is as follows:
//Helper.h @interface Helper:NSObject @property id prop1; @property id prop2; -(void)fn1; -(void)fn2; -(id)initWithViewController:(UIViewController*)vc; @end //Helper.m @interface Helper() @property(weak) UIViewController *vc; @end@implementation Helper -(id)initWithViewController:(UIViewController*)vc {self = [self init]; if (self ! = nil) { _vc = vc; } return self; } -(void)fn1 { //... self.vc.xxxx; // You can access the view controller's methods here. } @end .......................................... //XXXBaseViewController.h @interface XXXBaseViewController:UIViewController @property id prop1; @end //XXXBaseViewController.m @interface XXXBaseViewController() @property(strong) Helper *helper; @end @implementation XXXBaseViewController -(id)init { self = [super init]; if (self ! = nil) {// Initialize a help object in view controller initialization. _helper = [[Helper alloc] initWithViewController:self]; } return self; } // override the properties in the controller and delegate the actual implementation to the helper -(void)setProp1:(id)prop1 {self.helper.prop1 = prop1; } -(id)prop1 { return self.helper.prop1; } -(void) viewDidLoad { [super viewDidLoad]; [self.helper fn1]; // Call the helper class method. } @end // Use the same mechanism in your other derived classes.Copy the code
As you can see from the above, the helper class is designed with a weak reference pointer to the controller, and the controller is a strong reference to the helper class. The purpose of this design is to prevent the occurrence of circular references. This design pattern is also a very classic method in practice: Sometimes we need to delegate some functions of class A to class B, and B may access the attributes of A in A specific place. In this case, we need to use strong and weak references to solve this problem. The above approach, implemented with helper classes, solves the problem of code duplication in our derived classes. The disadvantage of the above approach is that we need to write a lot of repetitive, stylized code in our derived classes. How to simplify? In fact, we can use the interface protocol and the forwarding mechanism in OC to solve these problems:
// helper. h @protocol Helper // Please set the properties and methods of the interface to optional @optional@property id prop1; @property id prop2; -(void)fn1; -(void)fn2; @interface Helper:NSObject<Helper> @property id prop1; @property id prop2; -(id)initWithViewController:(UIViewController*)vc; @end //Helper.m @interface Helper() @property(weak) UIViewController *vc; @end@implementation Helper -(id)initWithViewController:(UIViewController*)vc {self = [self init];if(self ! = nil) { _vc = vc; }returnself; } -(void)fn1 { //... self.vc.xxxx; // You can access the view controller's methods here. } -(void)fn2 { //... } @end .......................................... //XXXBaseViewController.h @interface XXXBaseViewController:UIViewController @end //XXXBaseViewController.m // Implement the Helper protocol. @interface XXXBaseViewController()<Helper> @property(strong) Helper * Helper; @end @implementation XXXBaseViewController -(id)init { self = [super init];if(self ! = nil) {// Initialize a help object in view controller initialization. _helper = [[Helper alloc] initWithViewController:self]; }returnself; } -(void) viewDidLoad { [super viewDidLoad]; [self fn1]; // call fn1 id *p = self.prop1 // read the property. } // This is the key implementation point, override this method. - (id) forwardingTargetForSelector aSelector: (SEL) {/ / judgment method of defining whether this method is agreement, if it is will be due to the implementer of the method is set to the helper objects. struct objc_method_description omd = protocol_getMethodDescription(@protocol(Helper), aSelector, NO, YES);if(omd.name ! = NULL) {return self.helper;
}
return[super forwardingTargetForSelector:aSelector]; } @end // Use the same mechanism in your other derived classes.Copy the code
You can see we can use OC forwardingTargetForSelector method to realize the method call forwarding processing, without specific definition methods of implementation.
3. Define internal and external interfaces
One of the main ideas of object-oriented programming is encapsulation. The so-called encapsulation is that when defining and designing a class, we try to expose the interface or method that can be understood and needed outside, and hide the intermediate or private features used in the internal implementation as much as possible. Hide complex implementation details as much as possible and expose easy-to-use interfaces for external use. For example, for the packaging of the car, we are exposed only to unlock, start, gear, steering and other operations, and the specific internal composition, the principle of the engine, as well as how the engine drives and other details do not need to be understood by the driver. It is the encapsulation nature of object orientation that allows us to use the methods of an object at the application level without knowing the details. Therefore, we should follow this design idea in the design of the class, exposing the necessary things to the outside, and hiding the implementation details inside the class to complete. This section does not apply only to controller class design, but also to all other systems. It is interesting to note that wrapper implementations of classes provide different capabilities in different languages. In C/C++/OC, class declaration and implementation are done in separate files (.h is the declaration and.m/.c/.cpp is the implementation), whereas in languages like Java and Swift, declaration and implementation are done in the same file. Because of the separation of declaration and implementation in the previous three languages, we can declare exposed methods and properties in header files, while internal private properties are declared and defined in implementation files. The user only needs to import the common header file. In the latter two languages, there is no separation, so there is a preference for interface definition and implementation for this kind of classification of common and private properties (as you can see in Java, where interfaces are used extensively to complete the architecture, and in Swift, where interface programming is promoted).
In object-oriented design, classes and classes cannot exist independently, they always have to establish a relationship between them, which may be one-way or two-way. We all promote one-way dependencies between classes to reduce coupling between classes. This one-way dependence is apparent, at least, in that the methods and properties exposed by the class are visible. But in actual internal implementations this one-way dependence can be broken. So a very common example is we all know that view controller UIViewController has a view property that holds the view that the controller manages, but we don’t see any properties of the controller in view UIView. The representation of this is that the view controller depends on the view, and the view doesn’t depend on the view controller, which is very consistent with the three-tier design of MVC. But is this true in practice? It turns out that’s not the case, because inside the system if a view is the root view of a controller it might have different properties and different processing logic, so actually inside UIView there’s a private property of the view controller that the view belongs to, and that property is viewDelegate. And on UIView it’s defined as an ID type.
In the above two paragraphs, we have mentioned the declaration of public and private methods and attributes. It can be seen that in order to design our class in this way, we only need to expose the common methods and attributes, and hide the private methods and attributes. So how do you implement this defined implementation of public and private methods? Let’s look at three specific scenarios:
- Some properties of a class are public and some are not
*/ / @interface XXXX // public attribute @property id pubp1; */ / public attribute @property id pubp1; @property id pubp2; // Public public method -(void)pubfn1; -(void)pubfn2; @end // xxxx. m // Attributes and methods that are only used internally are defined in the extension. @interface XXXX() // Internal private property @property id prip1; @property id prip2; // Internal private method -(void)prifn1; -(void)prifn2; @end @implementation XXXX @endCopy the code
- Some attributes of a class are exposed as read-only, but the internal implementation can be changed. This is done for security of access and use.
// xxxx. h@interface XXXX // Public attributes read-only @property(readonly) id pubp1;
@property(readonly) id pubp2; @end // xxxx. m // Attributes and methods that are only used internally are defined in the extension. @interface XXXX() // Inside the class these attributes are readable @property id pubp1; @property id pubp1; @end @implementation XXXX @endCopy the code
- There is A correlation between class A and class B. A holds instances of B and makes them public, while B may need internal methods or attributes of A in its implementation, while B does not expose its ownership of A to the outside. Because we refer to them through header files, we don’t see the dependencies in header files, but the internal implementation files clearly see the dependencies.
//A.h @interface A @property(strong) B *b; //A's external exposure holds B @property id others; -(void) pubfn1; @end //A.m // uses B's prip1, prifn1 inside A. @interface B() @property id prip1; -(void)prifn1; @interface A() @property id prip1; -(void)prifn1; @end @implementation A -(void)pubfn1 { //... [b prifn1]; //A internally calls B's private method [B pubfn1]; id temp = b.prip1; Internal attributes} / / @ the end... @interface B -(void)pubfn1; @interface B -(void)pubfn1; @end // b.m@interface A() // prifn1 is used in B. -(void)prifn1; @end@interface B() // The internal hold of B is A. Here because you have mutual holding you have to have one strong holding and one weak holding. @property(weak) A *a; @property id prip1; -(void)prifn1; @end @implementation B -(void)pubfn1 { [a prifn1]; } @endCopy the code
4. Definition and classification extension of various attributes
The controller is used to realize the establishment, management and control of view objects and business model objects. In the realization, the controller will have the properties of many view layer objects, as well as the properties of model layer objects, and also have some of its own properties. At the same time, the controller must process the user’s input at the appropriate time, invoke the services provided by the business model at the appropriate time, and notify the view of the results of the services provided by the business model for rendering and updating at the appropriate time. Therefore, how to organize a controller’s code layout (the code layout is not the interface layout of the view but the source code layout) is very important. There are rules for how to define and place properties, how to categorize methods in a controller, when to create views, when to create business objects, when to add and destroy observers, and how to handle class destructions. This section is more of an introduction to code specifications. I’m going to start with the following points.
(1). The order and rules of the definition of attributes. The design of a class is the first construction of attributes and member variables, and the controller is no different. As mentioned earlier, the controller manages view objects and model objects, so we typically define view objects and business objects as properties in the controller. Here are a few points:
- If properties and member variables in a controller are used and accessed only from within the class, then the properties should be defined in extensions in the controller’s implementation file, not in the controller’s header file, unless the properties are accessed or set externally. For example:
// xxx.m@interface XXX() @property(nonatomic, weak) UILabel *label; @property(nonatomic, strong) User *user; @end @implement XXX @endCopy the code
-
If the controller needs access to a child control view, it is best to define the child control view as weak rather than strong. The main reason for this is that iOS defaults to weak for child controls on SB or XIB, and the main reason is that the root view of the controller may be reconstructed at runtime (for example, if we want to implement a skin function, It is possible to reconstruct the root view in the view controller so that when the root view in the controller is destroyed, the subviews in the root view should also be destroyed, and if you define the subviews with strong, you might end up with the subview having a longer lifetime than the root view. It is also possible that our child controls will use lazy loading mode to create the subview of the root view, so if you use strong you will not be able to rebuild the subview.
-
For an NSString property it’s best to declare it copy. The reason for this is that if you declare it as strong or assign, the assignment of NSMutableString may be changed in subsequent code, causing exceptions. Such as:
NSMutableString *str1 = [@"hello"mutableCopy]; self.userName = str1; // If userName is declared strong, subsequent changes to str1 will also change the contents of userName.Copy the code
-
It is best not to include atomic modifiers on property definitions if your property does not involve any multithreaded access scenarios. The reason is that with the atomic modifier all attributes are assigned and read through the operating system atomic API.
-
Do not save state and persistent data to view objects.
-
If possible, it is best to define the view object properties in the controller separately from the model object properties, and put the view object properties at the top, the controller native properties in the middle, and the model object properties at the bottom.
The following is a typical controller property definition code example, just for your reference:
// xxxViewController.m@interface XXXViewController() // View object attributes are placed at the top. @property(nonatomic, weak) UITextField *nameLabel; @property(nonatomic, weak) UITextField *passwordLabel; @property(nonatomic, copy) NSString *name; @property(nonatomic, assign) BOOL isAgree; @property(nonatomic, strong) User * User; @end @implement XXXViewController @endCopy the code
When your properties are defined, we will implement the methods. Within the methods of a class we have methods that construct and destruct, methods that need to be overloaded, methods that handle events, methods that have a Delegate or observer, methods that are exposed to the public, and methods that have private helper. To facilitate the management, we’d better put these methods to classify, this also is helpful for locating, generally for a controller is the several methods mentioned above, we are generally method on a piece of the same nature, and some specific keywords or classification mechanism can be used to all the methods in the controller. Here I categorize methods in two different ways:
- By syntax keyword. In OC we can use #progma mark — name for easy location and lookup. In practice, controller classes are generally implemented: overriding base class methods, public methods, event handling methods, methods in a Delegate, and private methods, so we can define different labels for these methods. Details are as follows:
// implement XXXViewController. M @implement XXXViewController. These two methods together make it very clear that I initialized those things, I destructed those things. -(instanceType)initXXXXX{} -(void)dealloc{} To attributeset-(void)viewDidLoad{} -(void)viewWillAppear:(BOOL)animated{} -(void)viewDidAppear:(BOOL)animated{} -(void)viewDidAppear:(BOOL)animated{} -(NSString*)name{} -(void)setName:(NSString*) Name {} // put the common methods, which are exposed to external calls by the controller class.#pragma mark -- Public Methods-(void)publicFn1{} -(void)publicFn2{} I personally prefer to start with handle.#pragma mark -- Handle Methods-(void)handleAction1:(id)sender{} -(void)handleAction2:(NSNotification*)noti{} -(void)handleAction3:(NSTimer*)timer{} // Next comes the Delegate event, whose name is denoted by the Delegate protocol name.#pragma mark -- UIDataSource/ /.. Here's how to add a proxy...#pragma mark -- UITableViewDelegate// Next is to store various private methods.#pragma mark -- Private Methods
-(void)privateFn1{}
-(void)privateFn2{}
@end
Copy the code
- If you don’t want to use #pragma with tags, you can use pragma as well. Take the following example:
// this is the default part of the implementation, Construct and destruct methods and all overloaded methods from the base class -(instanceType)initXXXXX{} -(void)dealloc{} // Put the overloaded methods next. To attributeset-(void)viewDidLoad{} -(void)viewWillAppear:(BOOL)animated{} -(void)viewDidAppear:(BOOL)animated{} -(void)viewDidAppear:(BOOL)animated{} -(NSString*)name{} -(void)setName:(NSString*) Name {} @end // Public method @implement XXXViewController(Public) @end // event handler method @implement XXXViewController(Handle) @end @implement XXXViewController(UIDataSource) @end @implement XXXViewController(UITableViewDelegate) @end @implement XXXViewController(Private) @endCopy the code
Welcome to visit my Github address and follow Ouyang Big Brother 2013