IOS tips for maintaining smooth interface

Source: Internet
Author: User
Tags uikit

Original http://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/


This article will be a very detailed analysis of the various performance issues in the IOS interface building and the corresponding solutions, as well as an open source microblogging list implementation, showing how to build smooth interactions through actual code.

Index

Demo Project

How the screen displays the image

Causes of lag and solutions

CPU resource consumption reasons and solutions

GPU resource consumption reasons and solutions

Asyncdisplaykit

The origin of ASDK

ASDK's information

The basic principle of ASDK

ASDK Layer Pre-synthesis

ASDK Asynchronous concurrency Operations

Runloop Task Distribution

Weibo Demo performance Optimization tips

Pre-layout

Pre-rendering

Drawing asynchronously

Global concurrency control

More efficient asynchronous picture loading

Other areas that can be improved

How to evaluate the smoothness of the Interface demo project

Before starting the technical discussion, you can download the Demo I wrote and go to the real machine and experience it: Https://github.com/ibireme/YYKit. The Demo contains a list of feeds for Weibo, a publishing view, and a list of Twitter feeds. To be fair, all interfaces and interactions have been copied from the official app, and the data has been crawled from the official app. You can also replace the data in the Demo by crawling your own data to make comparisons easier. Although the functionality behind the official application is more complex, it does not result in too much interaction performance differences.

This Demo can run on IOS 6 at a minimum, so you can try it on your old device. In my test, even on IPhone 4S or IPad 3, the Demo list still keeps a smooth interaction with 50~60 FPS while sliding fast, while the list views of other apps such as Weibo, friends circles, and so on, are already heavily jammed.

Weibo Demo has about 4,000 lines of code, Twitter only 2000 lines of code, third-party library only used Yykit, the number of files is less, convenient to view. Okay, here's the text.

How the screen displays the image

First of all, from the previous CRT display principle. CRT electronic Gun According to the above method, from the top to the next line of scan, the scan is completed after the display of a frame screen, then the electronic gun back to the initial position to continue the next scan. To synchronize the display of the display with the video controller of the system, the monitor (or other hardware) generates a series of timing signals with the hardware clock. When the electronic gun is switched to a new line and ready for scanning, the monitor emits a horizontal sync signal (horizonal synchronization), referred to as HSync, and when a frame is drawn, the electronic gun returns to its original position, ready to draw the next frame before The monitor emits a vertical sync signal (vertical synchronization), referred to as VSync. The display is usually refreshed at a fixed frequency, which is the frequency at which the VSync signal is generated. Although the current equipment is mostly liquid crystal display, but the principle is still unchanged.

In general, the CPU, GPU, and monitor in a computer system work together in this way. The CPU calculates the display content submitted to the GPU,GPU render results into the frame buffer after the rendering is complete, then the video controller reads the data of the framebuffer in line with the VSync signal, passing through the possible digital-to-analog conversions to the display.

In the simplest case, there is only one frame buffer, when the frame buffer reads and refreshes have a relatively large efficiency problem. In order to solve the efficiency problem, the display system usually introduces two buffers, that is, a double buffering mechanism. In this case, the GPU will pre-render a frame into a buffer, let the video controller read, the next frame is rendered well, the GPU will direct the video controller's pointer to the second buffer. As a result, efficiency can be greatly improved.

Double buffering, while solving efficiency problems, introduces a new problem. When the video controller has not been read finished, that is, when the screen content is just half-time, the GPU submits a new frame of content to the frame buffer and swaps the two buffers, the video controller will display the second half of the new frame of data to the screen, causing a tearing phenomenon, such as:

To solve this problem, the GPU usually has a mechanism called vertical synchronization (shorthand is also v-sync), when the vertical synchronization is turned on, the GPU waits for the display's VSync signal to be emitted before a new frame of rendering and buffer updates. This can solve the tearing phenomenon, but also increase the smoothness of the picture, but the need to consume more computing resources, will also bring some delay.

So what is the current mainstream mobile device? As you can see from the Internet, IOS devices always use dual caches and turn on vertical sync. and Android device until the 4.1 version, Google began to introduce this mechanism, the current Android system is three cache + vertical synchronization.

Causes of lag and solutions

After the VSync signal arrives, the system graphics Service notifies the App,app main thread to start computing the display content in the CPU, such as view creation, layout calculation, picture decoding, text drawing, etc. through Cadisplaylink mechanism. The CPU then submits the computed content to the GPU, which is transformed, synthesized, and rendered by the GPU. The GPU then submits the rendered result to the frame buffer, waiting for the next VSync signal to appear on the screen. Due to the mechanism of vertical synchronization, if the CPU or GPU does not complete the content submission within a VSync time, the frame will be discarded, waiting for the next opportunity to display again, and the display will remain unchanged. This is the reason for the interface lag.

As you can see from the above figure, the CPU and GPU, regardless of which block the display process, will cause the frame to drop. Therefore, it is also necessary to evaluate and optimize the CPU and GPU pressure separately during development.

CPU resource consumption reasons and Solution Object creation

object creation allocates memory, adjusts properties, and even reads files, and consumes CPU resources. Try to use lightweight objects instead of weights to optimize performance. For example, Calayer is much lighter than UIView, so it is more appropriate to use Calayer to display a control that does not need to respond to touch events. If the object does not involve UI operations, it is put to the background thread to create, but unfortunately contains the Calayer control, can only be created and manipulated in the main thread. When creating a View object through Storyboard, its resource consumption is much larger than creating objects directly through code, and Storyboard is not a good technology choice in a performance-sensitive interface.

Try to postpone the creation of objects and spread the creation of objects across multiple tasks. Although this is difficult to achieve, and the advantages are not many, but if you have the ability to do it, or try as much as possible. If the object can be reused, and the cost of reuse is smaller than freeing and creating new objects, such objects should be reused as much as possible in a cache pool.

Object adjustment

Object tuning is also often where CPU resources are consumed. In particular, there is no property inside the Calayer:calayer, and when the property method is called, it is internally added by the runtime Resolveinstancemethod to the object, and the corresponding attribute value is saved to an internal Dictionary. It also notifies delegate, creates animations, and so on, and consumes resources very much. The UIView about display-related properties, such as Frame/bounds/transform, are actually calayer attribute mappings, so the resources consumed are much larger than the general properties when adjusting these properties of UIView. For this you are in the application, should minimize the unnecessary property modification.

When the view hierarchy is adjusted, there are many method calls and notifications between UIView and Calayer, so you should try to avoid adjusting the view hierarchy, adding and removing views when optimizing performance.

Object Destruction

The destruction of objects, although the consumption of resources is not much, but accumulated also cannot be ignored. Typically, when a container class holds a large number of objects, the resource consumption is very obvious when it is destroyed. Similarly, if the object can be placed in the background thread to release, then move to the background thread. Here's a tip: Capture the object into a block and throw it into the background queue to send a message to avoid a compiler warning so that the object can be destroyed in the background thread.

Nsarray *tmp = Self.array;self.array = Nil;dispatch_async (queue, ^{    [TMP class];});
Nsarray *tmp=self.array;self.array=nil;dispatch_async (queue,^{    [Tmpclass];});
Layout calculation

The calculation of the view layout is the most common place in the App that consumes CPU resources. If you can calculate the layout of the view ahead of time in a background thread and cache the views layout, this place is basically not a performance issue.

Regardless of the technique by which the view is laid out, it will eventually fall to the adjustment of attributes such as Uiview.frame/bounds/center. As mentioned above, the adjustment of these properties is very resource-intensive, so try to calculate the layout in advance, adjust the corresponding properties one at a time when necessary, and not to calculate and adjust these properties multiple times and frequently.

AutoLayout

AutoLayout is a technology that Apple itself advocates, and in most cases it can improve development efficiency, but AutoLayout often produces serious performance problems for complex views. As the number of views grows, the CPU consumption that AutoLayout brings increases exponentially. Specific data can be seen in this article: http://pilky.me/36/. If you do not want to manually adjust properties such as frame, you can use some tool methods instead (such as common Left/right/top/bottom/width/height shortcut properties), or use Componentkit, Asyncdisplaykit and other frameworks.

Text calculation

If an interface contains a large amount of text (such as a Weibo friend circle, etc.), the width and height of the text will take up a large portion of the resources and is unavoidable. If you do not have special requirements for text display, you can refer to the following UILabel internal implementation: using [nsattributedstring BoundingRectWithSize:options:context:] To calculate the text width, with the-[ Nsattributedstring DrawWithRect:options:context:] to draw the text. Although these two methods perform well, they still need to be placed in a background thread to avoid blocking the main thread.

If you draw the text with Coretext, you can generate the Coretext typeset object First, then calculate it yourself, and the Coretext object can be reserved for later use.

Text rendering

All the text content controls that are visible on the screen, including the UIWebView, are formatted with Coretext and plotted as Bitmap on the bottom. Common text controls (UILabel, Uitextview, and so on), whose layout and drawing are made on the main thread, can be very stressful when large amounts of text are displayed. For this solution there is only one, which is the custom text control, which is drawn asynchronously with Textkit or the bottommost coretext. Although this implementation is very troublesome, but its advantages are also very large, Coretext object creation, can directly obtain the text of the wide and high information, to avoid multiple calculations (adjust the size of the UILabel once, UILabel when drawing the internal calculation again); Coretext objects consume less memory and can be cached for rendering more than once later.

Decoding of pictures

When you create a picture with UIImage or cgimagesource, the image data is not decoded immediately. The image is set to Uiimageview or calayer.contents, and the data in the Cgimage is decoded before Calayer is submitted to the GPU. This step takes place in the main thread and is unavoidable. If you want to circumvent this mechanism, it is common practice to draw the picture into cgbitmapcontext in the background thread, and then create the image directly from the Bitmap. Now the common network Picture library has this function.

Drawing of images

The drawing of an image is usually done by drawing the image to the canvas using the methods that begin with CG, and then creating a picture from the canvas and showing the process. The most common place is [UIView DrawRect:] inside. Since the Coregraphic method is usually thread-safe, the drawing of the image can be easily placed in a background thread. The process of a simple asynchronous drawing is generally as follows (the reality is much more complicated than this, but the principle is basically the same):

-(void) display {    Dispatch_async (backgroundqueue, ^{        cgcontextref ctx = cgbitmapcontextcreate (...);        Draw in context ...        Cgimageref img = cgbitmapcontextcreateimage (CTX);        Cfrelease (CTX);        Dispatch_async (Mainqueue, ^{            layer.contents = img;        });}    );
-(void) Display{dispatch_async (backgroundqueue,^{cgcontextrefctx=cgbitmapcontextcreate (...); /Draw in context ... Cgimagerefimg=cgbitmapcontextcreateimage (CTX); Cfrelease (CTX);d ispatch_async (mainqueue,^{layer.contents=img;});});
GPU resource consumption reasons and solutions

Compared to CPUs, the GPU is capable of a single thing: receiving submitted textures (Texture) and vertex descriptions (triangles), applying transformations (transform), blending and rendering, and outputting them to the screen. Usually you can see the content, mainly is the texture (picture) and shape (triangular simulation vector graphics) two categories.

Rendering of textures

All Bitmap, including images, text, and rasterized content, will eventually be submitted by memory to the video and bound to the GPU Texture. Whether it's the process of committing to video memory, or the process of GPU tuning and rendering Texture, it consumes a lot of GPU resources. When a large number of images are displayed in a short time (such as when there are very many images and TableView), the CPU usage is very low, the GPU occupies very high, and the interface will still drop frames. The way to avoid this is to minimize the display of large numbers of images in a short period of time, as many pictures as possible to be displayed.

When the picture is too large to exceed the maximum texture size of the GPU, the picture needs to be pre-preprocessed by the CPU, which brings additional resource consumption to both the CPU and the GPU. At present, the IPhone 4S or more models, the maximum texture size is 4096x4096, more detailed information can be seen here: iosres.com. Therefore, try not to let the size of the picture and view exceed this value.

Blending of views (composing)

When multiple views (or calayer) overlap together, the GPU first mixes them together. If the view structure is too complex, the blending process consumes a lot of GPU resources. To mitigate the GPU consumption of this situation, the application should minimize the number and level of views and mark the opaque attribute in an opaque view to avoid useless Alpha channel compositing. Of course, this can also be used in the above method, a number of views pre-rendered as a picture to display.

The generation of graphs.

Calayer's border, fillets, shadows, masks, Casharplayer vector graphics display, usually trigger off-screen rendering (offscreen rendering), while off-screen rendering typically occurs in the GPU. When a large number of fillet calayer appear in a list view, and a quick swipe, you can observe that the GPU resources are already full, and CPU resource consumption is low. The interface still slides normally, but the average number of frames drops to a very low point. To avoid this, you can try to turn on the Calayer.shouldrasterize property, but this will pass the original off-screen rendering to the CPU. For some occasions where rounded corners are required, it is also possible to simulate the same visual effects by covering the original view with a picture of the rounded corners already drawn. The most thorough solution is to draw the graphic you want to display in a background thread as a picture, avoiding the use of attributes such as fillets, shadows, masks, and so on.

Asyncdisplaykit

Asyncdisplaykit is an open source for Facebook to keep the IOS interface smooth, I learned a lot of things, so I will spend more space to introduce and analyze it.

The origin of ASDK

ASDK is the author of Scott Goodson (Linkedin),

He worked at Apple and was responsible for the development of some of IOS's built-in apps, such as stocks, calculators, maps, clocks, settings, Safari, and, of course, the development of the UIKIT framework. Later, after joining Facebook, he was responsible for Paper's development, creating and opening up Asyncdisplaykit. He is currently responsible for IOS development and user experience improvements in Pinterest and Instagram.

ASDK Open Source Since June 2014, released in October, Version 1.0. Currently ASDK is about to release version 2.0.

V2.0 added more layout-related code, and the Componentkit team contributed a lot.

Now the version on Github's Master branch is V1.9.1, which already contains the full contents of the V2.0.

ASDK's information

To understand the principles and details of ASDK, it's best to start with the following videos:

2014.10.15 Nslondon-scott Goodson-behind Asyncdisplaykit

2015.03.02 MCE 2015-scott goodson-effortless responsiveness with Asyncdisplaykit

2015.10.25 Asyncdisplaykit 2.0:intelligent User interfaces-nsspain 2015

The first two video content is similar, is introduced ASDK the basic principle, accompanies introduces the POP and so on other items.

The latter video adds an introduction to the new features of ASDK 2.0.

In addition, you can go to Github issues to see ASDK related discussions, here are a few more important things:

About Runloop Dispatch

About the difference between Componentkit and ASDK

Why not support Storyboard and AutoLayout

How to evaluate the smoothness of the interface

After that, you can also go to Google Groups to see and discuss more:

The basic principle of Https://groups.google.com/forum/#!forum/asyncdisplaykitASDK

Asdk that the main process of blocking the task, mainly divided into the above three major categories. The calculation, rendering, decoding, drawing of text and layout can be performed asynchronously in various ways, but UIKit and Core Animation related operations must be performed on the main thread. The goal of ASDK is to try to remove these tasks from the main thread and move them away, optimizing performance as much as possible.

To achieve this goal, ASDK attempts to encapsulate the UIKit component:

This is a common relationship between UIView and Calayer: View holds a layer for display, most of the display properties in view are actually mapped from a layer, and the layer's delegate here is view, and when its properties change and the animation is generated, view can Be notified. UIView and Calayer are not thread-safe and can only be created, accessed, and destroyed in the main thread.

ASDK creates the Asdisplaynode class for this purpose, wraps common view properties (such as frame/bounds/alpha/transform/backgroundcolor/supernode/subnodes, etc.), and then uses the Uiview->calayer in the same way that implements the Asnode->uiview such a relationship.

When there is no need to respond to touch events, Asdisplaynode can be set to layer backed, which means that Asdisplaynode functions as the original UIView, saving more resources.

Unlike UIView and Calayer, Asdisplaynode is thread-safe and can be created and modified in a background thread. When Node was first created, it does not create a new UIView and Calayer internally, until the first time the view or Layer property is accessed on the main thread, it generates the corresponding object internally. When its properties (such as Frame/transform) are changed, it does not immediately synchronize to the view or layer it holds, but instead saves the changed attribute to an internal intermediate variable, which is then set to the internal view or layer at a time, if necessary, by a mechanism.

By simulating and encapsulating uiview/calayer, developers can replace UIView in code with Asnode, greatly reducing the cost of development and learning, while gaining asdk of the underlying performance optimizations. For ease of use, ASDK has encapsulated a large number of commonly used controls into Asnode subclasses such as Button, control, Cell, Image, ImageView, Text, TableView, CollectionView, and so on. With these controls, developers can avoid using UIKit-related controls directly for a more complete performance boost.

ASDK Layer Pre-synthesis

Sometimes a layer contains a lot of sub-layer, and these sub-layer do not need to respond to touch events, nor do they need to be animated or position-adjusted. ASDK has implemented a technique called pre-composing to render these sub-layer compositions as a single image. At development time, Asnode has replaced UIView and Calayer, and after using various Node controls directly and set to layer backed, asnode can even avoid creating internal UIView and Calayer by pre-compositing.

In this way, a large layer is drawn to a graph by a large drawing method, and performance can be greatly improved. The CPU avoids the resource consumption of creating UIKit objects, the GPU avoids the consumption of multiple texture compositing and rendering, and less bitmap also means less memory usage.

ASDK Asynchronous concurrency Operations

Since the IPhone 4S, IDevice is already a dual-core CPU, and now the IPAD has even been updated to 3 cores. Taking advantage of the multi-core and executing tasks concurrently has a great effect on maintaining smooth interface. ASDK layout calculations, text typesetting, picture/text/graphics rendering, and so on are encapsulated into smaller tasks and executed asynchronously concurrently with GCD. If the developer uses Asnode-related controls, these concurrency actions will be performed automatically in the background without much configuration.

Runloop Task Distribution

Runloop work distribution is asdk the core of a technology, ASDK introduction video and documentation are not detailed introduction, so here I will do more analysis. If you are not familiar with Runloop, you can look at my previous article in-depth understanding of Runloop, ASDK also mentioned.

The IOS display system is driven by the VSync signal, and the VSync signal is generated by the hardware clock, which is emitted 60 times per second (this value depends on the device hardware, such as the iPhone is usually 59.97 on a real machine). After the IOS graphics service receives the VSYNC signal, it is notified via IPC to the App. The app's runloop will register the corresponding Cfrunloopsource through Mach_port to receive the clock signal notification, then the Source callback will drive the entire app animation and display.

Core Animation registered a Observer in runloop and monitored the beforewaiting and Exit events. The priority of this Observer is 2000000, below the common other Observer. When a touch event arrives, the Runloop is awakened, and the code in the APP performs some actions, such as creating and resizing the view hierarchy, setting the frame of the UIView, modifying the transparency of the Calayer, adding an animation to the view, which will eventually be captured by Calayer and Catransaction commits to an intermediate state (Catransaction's documentation is slightly mentioned, but not complete). When all of the above operations are completed, Runloop is about to enter hibernation (or exit), the Observer that is concerned about the event will be notified. At this time, the CA registered Observer will be in the callback, all the intermediate state is submitted to the GPU to display, if there is animation, the CA will be DisplayLink and other mechanisms to trigger the related process multiple times.

ASDK here simulates this mechanism of Core Animation: All modifications and commits to Asnode, some of which are required to be executed in the main thread. When this happens, Asnode will encapsulate the task in Asasynctransaction (Group) and commit it to a global container. ASDK also registered a Observer in Runloop, monitoring events like CAs, but with a lower priority than CAs. When Runloop enters hibernation and the CA finishes processing the event, ASDK executes all the tasks submitted within that loop. Specific code see this file: Asasynctransactiongroup.

With this mechanism, ASDK can synchronize asynchronous, concurrent operations to the main thread at the right opportunity, and can achieve good performance.

Other

There are also many advanced features encapsulated in ASDK, such as the preload of a sliding list, the new layout mode added by V2.0, and so on. ASDK is a very large library, it does not recommend you to change the entire App to ASDK driver, the most need to improve the performance of the area with ASDK optimization is enough.

Weibo Demo performance Optimization tips

In order to demonstrate the function of Yykit, I realized the demo of Weibo and Twitter, and did a lot of performance optimization for them, the following are some of the techniques used in optimization.

Pre-layout

When I get to the API JSON data, I will compute the data required by each Cell in the background thread and encapsulate it as a layout object celllayout. The celllayout contains the Coretext layout results for all text, the height of each control within the cell, and the overall height of the cell. The memory footprint of each celllayout is not much, so when it is generated, it can be cached to memory for later use. In this way, TableView does not consume any excess computation when it requests each height function, and when the celllayout is set to the inside of the cell, the layout is no longer in the cell.

For the usual TableView, it is important to calculate the layout results in advance in the background as a performance optimization point. To achieve maximum performance, you may need to sacrifice some development speed, do not use techniques such as AutoLayout, and less use text controls such as UILabel. But if your performance requirements are not so high, you can try to use TableView's estimated height function and cache each Cell height. Here is a team from Baidu know the Open source project can be very convenient to help you achieve this: Fdtemplatelayoutcell.

Pre-rendering

Weibo's avatar was replaced with a circle in a revision, so I followed it up a bit. When the avatar is downloaded, I will pre-render the avatar as a circle in the background thread and save it to a imagecache.

For TableView, off-screen rendering of Cell content can lead to larger GPU consumption. In the Twitter Demo, I used a lot of layer fillet properties for the sake of the diagram, and you can quickly swipe the list on low-performance devices like the IPad 3 to feel that although the list does not have a big lag, the overall average number of frames drops down. When viewed with instument, you can see that the GPU is running at full capacity while the CPU is relatively idle. In order to avoid off-screen rendering, you should try to avoid using layer of border, corner, shadow, mask and other techniques, and try to pre-draw the corresponding content in the background thread.

Drawing asynchronously

I only use asynchronous drawing on controls that display text, but it works fine. I have implemented a simple asynchronous drawing control by referring to the principle of asdk. This piece of code I extracted separately, put here: Yyasynclayer. Yyasynclayer is a subclass of Calayer, and when it needs to display content (such as a call to [layer Setneeddisplay]), it requests an asynchronously drawn task to delegate, which is UIView. When drawing asynchronously, the Layer passes a block of BOOL (^iscancelled) (), and the drawing code can call the block at any time to determine whether the drawing task has been canceled.

When the TableView is quickly sliding, there will be a large number of asynchronous drawing tasks submitted to the background thread to execute. But sometimes when the sliding speed is too fast, the drawing task may have been canceled without completing it. If you continue drawing at this point, it can cause a lot of wasted CPU resources, even blocking threads and causing the subsequent drawing tasks to be delayed. My practice is to try to quickly and in advance to determine whether the current drawing task has been canceled, before drawing each line of text, I will call iscancelled () to determine, to ensure that the canceled task can be timely exit, do not affect the subsequent operation.

At present, some third-party microblogging clients (such as Vvebo, poet, etc.), using a way to avoid the high-speed sliding Cell drawing process, related implementation see this project: Vvebotableviewdemo. The principle is that when you slide, when you release your finger, immediately calculate the position of the cell when the slide stops, and pre-draw several cells near that location, ignoring the cell in the current slide. This method is more technical, and for sliding performance is also very large, the only drawback is that there will be a lot of blank content in the fast slide. This technique is a good choice if you don't want to make the hassle of asynchronous drawing but want to keep the smoothness of the slide.

Global concurrency control

When I use concurrent queue to perform a lot of drawing tasks, I occasionally encounter this problem:

When a large number of tasks are submitted to the background queue, some tasks are locked for some reason (this is a cgfont lock) causing the thread to hibernate or be blocked, and the concurrent queue then creates a new thread to perform other tasks. When this happens, or the app uses a lot of concurrent queue to perform more tasks, the app will have dozens of threads running, creating, destroying at the same time. The CPU uses time-slice rotation to implement thread concurrency, although the concurrent queue can control the priority of threads, but when a large number of threads create run destruction at the same time, these operations still squeeze out the CPU resources of the main thread. ASDK has a Feed list of the demo:socialapplayout, when the list of cells too much, and very fast sliding, the interface will still appear a small amount of lag, my cautious speculation may be related to this problem.

This is an unavoidable problem when using the concurrent queue, but using the serial queue does not make full use of the resources of the multicore CPU. I wrote a simple tool yydispatchqueuepool, creating a serial queue with the same number of CPUs for different priorities, and polling for one queue each time a queue is fetched from the pool. I put all the asynchronous operations within the APP, including image decoding, object release, and asynchronous drawing, into the global serial queue in a different priority, so as to avoid the performance problems caused by too many threads.

More efficient asynchronous picture loading

Sdwebimage in this Demo will still produce a small number of performance problems, and some places do not meet my needs, so I myself realized a higher performance image loading library. When showing a simple single picture, the use of UIView.layer.contents is sufficient, there is no need to use Uiimageview to bring additional resource consumption, so I added Setimagewithurl on the Calayer method. In addition, I also put the image decoding and other operations through the Yydispatchqueuepool management, control the number of APP bus.

Other areas that can be improved

After these optimizations have been done, Weibo Demo has been very smooth, but in my vision, there are still some further optimization techniques, but limited to time and energy I did not realize, the following simple list:

There are a number of visual elements in the list that do not require touch events, which can be pre-drawn as a graph using the ASDK layer compositing technique.

Further reduce the number of neatline layers per Cell, replacing UIView with Calayer.

At present, each cell type is the same, but the content of the display is the same, for example, some cells have pictures, some cells are cards. Dividing cells by type, further reducing unnecessary view objects and operations within the cell, should have some effect.

The task that needs to be put into the main thread is divided into small enough blocks and dispatched through Runloop to determine the time of the next VSync in each Loop and to defer the current unfinished task until the next VSync arrives. This is just one of my ideas, and it doesn't have to be implemented or worked.

How to evaluate the smoothness of the interface

Finally, it is necessary to mention that "premature optimization is the root of all evils", when the demand is not clear, the performance problem is not obvious, there is no need to try to optimize, and to try to achieve the correct function. When it comes to performance optimization, it's also best to follow the process of modifying code, profile, and so on, to prioritize where to optimize.

If you need a clear FPS indicator, you can try the kmcgeigercounter. For CPU lag, it can be detected by the built-in Cadisplaylink, and it uses a 1x1 skview to monitor the lag caused by the GPU. There are two minor problems with this project: Skview can monitor the lag of the GPU, but the introduction of Skview itself will bring additional resource consumption to CPU/GPU, which has some compatibility issues under IOS 9 and needs to be adjusted slightly.

I wrote a simple FPS indicator myself: Fpslabel only has dozens of lines of code and only uses Cadisplaylink to monitor CPU lag. It's not as good as the tools above, but it's not too much of a problem for everyday use.

Finally, with Instuments's GPU Driver presets, you can see the CPU and GPU resource consumption in real time. In this preset, you can see almost all the data related to the display, such as the number of Texture, the frequency of the CA submission, GPU consumption, and so on, this is the best tool for the problem of positioning the interface.

IOS tips for maintaining smooth interface

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.