Here steal a picture [manual dog-head], in fact, I think we do program developers also want to have a crafty spirit, the product as their own craft, not only to achieve product function, but also to do a good optimization.

Because just recently saw “high-performance iOS application development”, to see the Dai Ming “iOS development master class”, (this is not a marketing ah), by some comprehension, so I decided to try for our app also do some optimization, and the optimization of process record to share with everybody, have a wrong also hope you correct them. I’m going to start by looking at the details of development, exploring the complex UI layout, the size of the package content, startup time, network, and power consumption. Here is to talk about the usual development should pay attention to the details.

Put the details in the first article because I think that is from the project at first we will meet every minute and every second, also easy to we ignore the content, although also will think of at ordinary times, but sometimes also because lazy, not willing to do, although each piece also influence on the performance of the app is not playing, but adds up. So I think details are important. I will enumerate in detail below, the relevance is not very strong, are relatively scattered points.

  1. Agent use

For the proxy method that calls the comparison frequency, we use the [_delegate respondsToSelector:@selector(func)] method to determine whether the delegate respondsToSelector responds to the selector. However, if this method is called frequently, subsequent checks may be unnecessary except for the first time when it is useful. It’s not very common to suddenly fail to respond to a selector that was previously responsive. We can do this by caching information about whether a proxy object can respond to a proxy method.

Take the ServerCenter in the project as an example.

@interface CLCClassPageServerCenter () { struct { unsigned int requestSuccess :1; unsigned int requestFailed :1; }_delegateFlags; } @end - (void)setDelegate:(id<ServerCenterResponseDelegate>)delegate { _delegate = delegate; _delegateFlags.requestSuccess = [delegate respondsToSelector:@selector(requestServerCenterSuccessWithType:serverCenter:)]; _delegateFlags.requestFailed = [delegate respondsToSelector:@selector(requestServerCenterFailed:type:serverCenter:)]; } - (void)requestServerCenterFinished:(BOOL)succeeded type:(NSInteger)type userInfo:(NSDictionary *)userInfo { if (succeeded) { if (_delegateFlags.requestSuccess) { [self.delegate requestServerCenterSuccessWithType:type serverCenter:self]; } } else { if (_delegateFlags.requestFailed) { [self.delegate requestServerCenterFailed:userInfo type:type serverCenter:self]; }}}Copy the code

The flag of a structure can be used to identify whether a certain agent method is implemented. It is recommended to use the “bit segment” data type. Each flag requires only one binary bit, which saves memory.

  1. Function and the cords

Because arm64 architecture has 8 parameter registers, if more than 8 parameters will be pushed to the stack, which affects the efficiency, so c function parameters should not exceed 8 parameters, OC function parameters should not exceed 6 parameters (OC method default has two hidden parameters self and SEL). If there are too many parameters, consider using a dictionary or a configuration file to pass the parameters.

  1. Try to access instance variables directly within the object

Because there is no method dispatch, direct access to instance variables is faster, and the code generated by the compiler accesses directly the memory that holds the object instance. But use dot syntax for properties that require “key-value observation” or lazy loading. A compromise is to write an instance variable through its “set method” and read it directly. But the switch… Case can only handle cases where case is constant, it can’t handle cases where case is non-constant. For example, if (a > 1 && a < 100), it is not possible to use switch… Case. Therefore, the switch can only be more efficient than the ifElse when selecting constant branches, but the ifElse can be used in more situations, and the IfElse is more flexible.

  1. Use of switch, if else

The first step is to reduce the if else hierarchy as much as possible. If the criteria are greater than 3, use the switch as much as possible. Case generates a jump table to indicate the address of the actual case branch, so the switch is more efficient. But the case condition should be continuous, if the span of 1, 20, 40 is larger than the final result of a large assembly or if else.

  1. Time consuming operations should be placed as asynchronous as possible, and the main thread should be displayed first.

  2. Use of the +(void)load method

We usually do some hook operations, usually in the +(void)load method, but because of the project roughly load process 1 load the APP executable file. O, Dyly -> call +load (in memory) for all classes and categories -> 3dyld will call main,+(void) too many loads will affect the speed of app startup. It is recommended to use the +(void)initialize method, which is called when the class receives the first mesgSend message, so it works the same way (note the order and override of the parent, subclass, and class). But it’s not recommended to do too much.

  1. TableView and CollectionView refresh as little as possible, you can refresh a row or a group, refresh as needed

  2. In the project, it was found that after some pages were refreshed, existing pages would be overwritten by abnormal pages. It is suggested to make a judgment when demanding data, and do not display the abnormal pages when the network request fails for the data with existing pages. Increase user experience friendliness.

  3. Avoid frequent destruction and creation of objects, and use NSAutoreleasePool to automatically release the pool if a large number of objects need to be destroyed. Avoid excessive memory peak.

  4. Defer reference to header files as long as possible, and try to follow protocol in.m files

  5. Use static, const, extern, and define properly. Use static const for constants used within the current file, and extern const for constants shared by multiple files.

Define constants with preprocessor instructions (the macro “define”) as little as possible. If a macro definition is declared in a header file, all code that introduces the header file will replace the macro definition. Defining many macros at the same time increases compilation time in a project. The constants thus defined have no type information, and the compiler simply finds and replaces them before compiling. Even if someone redefines a constant value, the compiler does not generate a warning, which can lead to inconsistent constant values in the application.

  1. Use atomic with caution

With atomic, you lock getter/setter methods, but @synchronized is a mutex, which is more performance intensive.

  1. Properties exposed to the outside in the viewMode should be read-only. The recommended properties are readonly for.h files and readwrite for.m files.

  2. Avoid excessive thread switching and control the number of threads.

  3. The use of enumerations is recommended for loop traversal.

  4. Some suggestions for using the UI

  • For controls with fixed frames, initialize the frame when loading lazously. Do not frequently call the related properties of UIView, such as frame, bounds, transform, etc., to minimize unnecessary modifications, calculate the layout in advance as far as possible, and adjust the corresponding properties once necessary. Do not modify the properties more than once.
  • Keep the page view hierarchy to a minimum, because too many UI hierarchies will first consume more memory, and cause the event response chain to pass, affecting the event response time.
  • Try to use lightweight UI controls, such as controls that do not respond to events. Consider using Layer instead.
  • The size of the image should be exactly the same as the size of the UIImageView.
  • Try to avoid displaying a large number of pictures in a short time, and try to synthesize many pictures into one for display.
  • Reduce the opacity of the view (alpha<1) and set opaque to YES
  • Try to avoid using Layder to add rounded corners, edges, and shadows. Use UIBezierPath for edges and rounded corners, and use UIBezierPath for shadows to make the UI cut into smaller images and then set the stretch.

* Do not use ClearColor as much as possible, no background color, and do not set transparency to 0 * Calculate and cache the properties and contents of the cell in advance, and cache the height of the cell

  1. You use blue Lake download pictures when it is recommended to open the picture compression function, the picture quality does not affect the display of as far as possible to choose low picture quality.

  1. For some third-party applications, we may only use some of the functions, so it is recommended to rewrite, select the ones we use, and reduce the package size and code amount.

  2. For list page requests you can set the request data pageSize size according to the network situation.

  3. Use class methods whenever possible. From the ISA flowchart, a class method will have one less lookup than an instance method, so it is more efficient.

  1. Some of the use of the other party library, it is best to encapsulate a layer, can facilitate the replacement later.

The detail method thinks of so much temporarily, everybody has good suggestion to be able to add, have wrong above also welcome to point out.

Continue to update the corrections……