I would like to discuss the influence of navigation on FSP and how best to use it. If you’re familiar with iOS development, you’ll probably be familiar with the Navigation framework. To put it simply, the birth of navigation makes AutoLayout more elegant to use and facilitates the layout of widgets. Dialectically speaking, all things will have two sides, and the use of Masonry is no exception. Improper use of the navigation framework will directly affect the FPS performance of the UI. Today we’ll discuss some of the pitfalls of using navigation and see how it might affect performance. In this blog post we will still rely on the Demo to cover some of the things.

I’ve written an article about the source code of the framework for NAVIGATION. For details, please refer to the source code analysis of the FRAMEWORK for iOS navigation.

 

I. Overview of Demo

1. Operation effect

First, the content of this blog is still based on the Demo we created specifically for this blog. First, let’s take a look at how the Demo works. Through the Demo, we can see the problems and how they are solved. Below is the Demo we covered in this blog post.

Judging from the operating effects below, we would like to observe and judge the influence of various methods of navigation on FPS. Six SegmentControls are used to switch the layout of the Cell. Of course, each layout renders the same Cell. This is also the principle of keeping the experiment changing the other things when you do the experiment. We can use the FPS indicator in the lower right to get a sense of the FPS trend. The FPS display control below was taken from our previous Demo. The previous Demo was also about FPS optimization, but it was about FPS optimization for highly dynamic Cell computation. For details, see UI Fluency Analysis of Various Cell Highly Adaptive Implementations for iOS Development.

The data displayed in the lower Cell is randomly generated, and the Image on the left is also randomly selected. The Title and Detail on the right are NSAttributedString and some of the Detail down there might be empty. If a Detail is empty, the layout of everything below that Detail moves up. The Demo and its technical points will be covered in more detail later.

      

 

2. Simulate network requests

The data shown in the above Cell is obtained by simulating network data, and the code of simulating network layer is shown below. After all, it is a Demo, and the Demo focus is not on the network layer, the following is simple to write, the code is relatively simple. It is a singleton + a method that simulates the random generation of data and then calls the randomly generated data back to the user of the network layer via Block. The specific code is as follows:

    

 

XBaseTableViewCell (XBaseTableViewCell

The cells in each Segment above are a separate Cell type, but they have a common parent class. The parent class handles the logic shared by the cells. The XBaseTableViewCell below is the base class for all the cells shown above. It declares and initializes all controls on the Cell. Methods for setting values are also provided.

As you can see from the code below, there are two methods that need to be subclassed. One is the addLayoutSubviews method that adds the layout to the control, and the other is the updateLayoutSubviews method that updates the layout. These two methods are overridden and laid out differently in each subclass.

  

 

4. Switch Cell code in Segment

Below is the logical code for clicking SegmentControl in the corresponding VC. Clicking on different segments will select different cells and refresh the TableView. The code is relatively simple, so I will not do too much verbose.

  

 

 

Second, the above various layout methods are analyzed

The next thing to do is to analyze the impact of each layout method on the FSP. We will use Instrument to analyze the different layout conditions and look at the specific data. The next section discusses how to retrieve the next item only, which is held for Update, Frame, and Make.

1, the update

First let’s look at the UPDATE operation. Assign values directly to the control using update, which is a lazy operation. In our Demo, the UI layout of some controls would be updated when setting the cell value. Therefore, we would simply use the post update to add constraints to the controls. The navigation update operation will enable you to find a constraint in the navigation array, and then update it. If you cannot find a constraint, install will add it. This update feature is inefficient.

Can I just have a look at the code realization, in subclasses XUpdateLayoutTableViewCell, rewrite the addLayoutSubviews and updateLayoutSubviews two methods. In the updateLayoutSubviews method, update all controls to add constraints. This will call the updateLayoutSubviews method below every time a value is set. This will update the layout of all controls on the cell. Of course, this is not recommended because it will update constraints that do not need to be updated. The reason for listing it today is that there are real issues in development below, perhaps due to time constraints or other reasons for the code implementation below.

  

 

Let’s run the above Demo using Instruments and get a feel for the Demo’s Core Animation. Below is the corresponding FPS data when we switch the SegmentControl to Update. As you can see from the data below, adding the Update constraint directly with Update will affect the FPS more. Of course, property strings are also used in cells, which we’ll discuss later.

  

 

We can run the Time Profile in the Update state. As shown in the following figure, when the Cell updates data, two operations are time-consuming. One would be the update operation for the navigation, and the other would be the NSAttributedString setting for the Label. Because each Label we use will assign an attribute string, this is a time-consuming operation. It should also be noted that property strings do not take much Time to create and generate, whereas property strings take a lot of Time to assign and render, as can be seen in the Time Profile below.

  

 

2, remake

This is held to work with the Update operation, as seen in the Core Animation below. The lower FPS is slightly lower than the remake, which is used to remake itself, literally removing a constraint when it has been added before, and then adding a new one.

   

 

Spares 66.6% of the Time consumed for layout updates, and uninstall accounts for about 10% of the Time consumed for 33% of install. This is the lowest sphereefficiency in navigation. We’ll continue this discussion later.

  

 

3, make + update

After discussion of update and spiced for navigation, we’ll discuss the conventional way to use it. Make is used to initialize the layout of the controller and update is used to update the constraints. Because the code is relatively simple, I’m not going to paste it, but it’s worth running around using Instrument. Below is the result of the make + Update Core Animation. This is held to be a little better than the update or remake for FSP, which is not high in the data below. This data will be refined later.

This part of the Time Profile does not run, because when setting values we still use Update to Update constraints, but instead of updating all constraints, we Update those that only need to be updated. Because the number of constraints updated will be smaller, all FPS will perform better than if all constraints were updated before. Make + Update will make the FPS slightly better, but as you can see from the figure below, it’s not that much better.

  

 

4. Frame + frame

Next, we will not use the layout for navigation, we will use the Frame layout. Since Autolayout will still eventually be converted to a Frame layout, it is clear that a Frame layout is better than an Autolayout layout in terms of performance. Now we’re going to use the Frame layout and then use the Frame update. The bottom FPS is ok, but not full, mostly because of NSAttrubitedString.

   

 

We can look at the updated Frame Time Profile, as shown below. From the screenshot below, we can see that the time to update the frame is only 2.5%, and the previous update constraints are around 60%, which shows the benefits of using the frame layout. As you can see from the analysis below, the main factor affecting FPS has now shifted from the updated layout to the setting of the AttributeString. This is why the above FPS is not full.

  

 

6, make + frame

The first thing I would like to retrieve is to facilitate the layout of controls. The layout of frames is not flexible enough, so it will be difficult to fit. That’s why AutoLayout comes into being. But while AutoLayout is a handy screen fit, its performance isn’t particularly good. So can we combine the two. That is, use make to initialize the controller layout and use Frame to update the layout. Of course, this process is not simply to update the Frame when setting the value, because it is useless to update the Frame when setting the value of the Cell, because after updating the Frame, the rendering will still be displayed according to the AutoLayout layout. All we need to do is place the Frame layout after the Autolayout layout, and all we need to do here is place the code that updates the Frame in the next Runloop. Update the Frame code as follows:

  

 

In the cell, “make” initiates the layout of the controller, and “Frame” will be used to update the layout. The method is the same as “Frame+Frame”, but when loading the first screen, the layout will be inferior to the “Frame” layout. Later updates will be the same. Below is the result of a Core Animation using the navigation +Frame format. Although the effect will be slightly worse than the previous part, but the final effect is still Ok.

  

 

 

Third, summary

This post will only discuss the effects of layout on the FPS, so I won’t go into the NSAttributeString. If the business needs a lot of rich text display that affects the FPS, there are other ways to optimize the display, such as using related nodes provided by AsynDisplayKit, etc. At the end of this blog, it’s worth summarizing.

This is held to be the worst performance in the data in the code below, so we would like to use less of this data when using the navigation. It would be a bad idea to only use updates for widgets. If you would like to use the navigation framework to enable layout updates for widgets, it would be best to separate the unchangeable constraints from the ones you would like to Update. Use make to add related constraints and update to modify the constraints that need to be updated. Of course, the performance is better with a Frame layout, but the layout process is too cumbersome for screen adaptation. You can also use the Frame layout to update the layout. Note that the Frame layout should be updated after the loading of Autolayout.

Below is a unified data statistics, of course, for the corresponding Demo of this blog. The average time used to Update the cell layout in different ways is calculated in the table below, which is the most used for crude Remake of the layout, consuming 12+ms, and 9+ms for updating all constraints. It takes 7+ms to update only the layout that needs to be updated, which is slightly better than updating all of the layouts. Of course, it takes the least time to directly modify the Frame, only 0.06+ms. From this data, we can intuitively feel the efficiency of the Frame layout.

And also gives an attribute of the string on the right to create and assign unavailable, which we can see that the attribute string create time is not too much, but more time-consuming is attribute the assignment of the string, each assignment occupies 0.7 ms, if is 10, so time is 7 ms assignment, the content of the string if the attribute complex again, So the time is definitely going to be higher than that. Of course, we can use some controls and methods provided by third parties to optimize this part of time, which can be discussed later.

I would like to post a post for you today. The purpose of this blog is to use Frame layouts properly when using navigation.

  

 

Demo – Github share link: github.com/lizelu/FPSP…

 

The copyright of this article belongs to the author and the total blog garden, welcome to reprint, but without the consent of the author must retain this statement, and give the original link in the obvious position of the article page, otherwise reserve the right to pursue legal responsibility. If there are any mistakes in the article, please point them out. Lest more people be misled.