Incompatibility with iOS 10 for iPhoneX under Xcode 9

A long time ago, I found that the test team submitted a bug, saying that some layouts are normal on iOS 11, but not normal on iOS 10. I ran the app on the iOS 11 simulator and the iOS 10.3 simulator respectively, and found that it did, as shown in the following figure:

  • Click on "Provincial and Municipal Radio Station" under iOS 11, and the buttons in the lower menu are displayed normally:

  • Under iOS 10, click "Provincial and Municipal Radio Station", and the lower-level menu is displayed as blank:

Checking the code, I found that the buttons in the lower menu are dynamically added to a scroll view in a manual layout. The frame of the button is specified when adding, the frame calculation is completely normal, and the button has been added in the subviews of the scroll view (you can confirm with the po command in LLDB). At the same time, in the process of printing subviews, it is found that the frame of these buttons has not been changed, and it is still the value set in initWithFrame, but it is not displayed under iOS 10.3, nor can it be seen with the view debugger.

It was incomprehensible. Later, I thought that Xcode 9 had made some changes to the automatic layout constraints in order to adapt to the iPhoneX, such as the concept of "safe area", so I suspected that the new iOS SDK modified some layout properties of ScrollView.

After printing the scroll view properties under the two simulators, it is found that under iOS 10/11, the contentInset properties of the scroll view are different.

In iOS 11, the value of contentInset is (0,0,0,0), but in iOS 10 it becomes (64,0,0,0).

So I tried adding a sentence to the code:

if ([UIDevice currentDevice].systemVersion.floatValue < 11.0) {
       _scrollBar.contentInset = UIEdgeInsetsZero;
   }

It is found that the menu is actually displayed under iOS 10!

Although this method solves the problem to a certain extent, it is not completely. In the test, it is found that the layout problem under iOS 10 still occasionally occurs (especially when the view controller is loaded for the first time). Because the secondary menu requires a network load, the loading speed may be fast or slow, so after the first page display is completed, it is possible that the secondary menu has been displayed, and the automatic layout engine has not completed the calculation. It is possible to modify the scroll view's contentInset value again, since when the page first loads, the menu doesn't show up.

To solve this problem, other ways must be considered. Such as UIScrollViewDelegate protocol.

First declare the view controller to implement UIScrollViewDelegate:

<UIScrollViewDelegate>

Set the scroll view's delegate delegate:

_scrollBar.delegate = self;

Then implement the scrollViewDidScroll delegate method:

// MARK: - UIScrollViewDelegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    if (scrollView == _scrollBar && scrollView.contentOffset.y != 0){
        _scrollBar.contentInset = UIEdgeInsetsZero;
    }
}

Run the app, this time the problem is solved perfectly.

Note: All UIScrollView subclasses have this problem. If you use IB for layout, when using Align to Edges, you need to pay attention to aligning the four edges to the superview, not the default Safe Area, otherwise this problem will occur.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324773375&siteId=291194637