Welcome to follow the official wechat account: FSA Full stack action 👋

The problem

Trigger: Clicking a button to rotate the screen crashed

Normally the cause of the crash can be located by looking at the call stack information, but here the call stack information only shows the code that forces the screen to rotate

UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
Copy the code

This forced screen rotation method is used in many third party libraries, it is unlikely to cause a crash because of this, or how many people laugh online ~

We then click on the call stack one by one and find that they are all such assembly-related prompts 😳

positioning

Looking closely at the call stack, from top to bottom:

objc_msgSend:
CA::Layer::layout_if_needed:(CA::Transaction*)
-[UIView(Hierarchy) layoutBelowIfNeeded]:
-[UINavigationController _layoutViewController:]
Copy the code

The objc_msgSend error occurred after the second execution, so we open the second stack information and add A breakpoint on the line above the crash processing, which we call breakpoint A

Automatically continue after evaluating Actions (or evaluating actions). Automatically continue after evaluating Actions (or evaluating actions)

Add theActionDescription:

Display object information Po $x0 display method name p (char*)$x1Copy the code

In this way, when the corresponding code is executed internally, the breakpoint is skipped and automatically released, and the object information and method names are automatically printed on the console.

However, this Breakpoint will be called all over the program and will execute slowly, so you can invalidate it and add a Symbolic Breakpoint.

Add a breakpoint near where the crash occurred. For example, I added -[UINavigationController _layoutViewController:] because it’s called less often than the previous breakpoint,

The symbol description is taken from the first line of the call stack

Jumps in the breakpoint and rush to cut back the breakpoint A, need to compare the current call stack and the collapse of the call stack are consistent, if the same cut back the breakpoint A, otherwise continue to release breakpoints, here also can oneself and counting and release, confirm the NTH collapse happened, when running again, release n – 1 and cut back to the breakpoint A

After you cut back to breakpoint A, you’ll notice that Xcode’s console starts printing messages like crazy until it stops, fetching the last few messages as follows:

<CALayer:0x2820ca480; position = CGPoint (315 135); bounds = CGRect (0 0; 20 80); delegate = <xxx.JXPageControlEllipse: 0x10bdaf130; // Note that frame = (275 125; 20 80); layer = <CALayer: 0x2820ca480>>; sublayers = (<CALayer: 0x2820ca440>); opaque = YES; allowsGroupOpacity = YES; > (char *) $325 = 0x00000001e4f40ab8 "layoutSublayers" <CALayer:0x2820ca440; position = CGPoint (68 10); bounds = CGRect (0 0; 24 (4); delegate = <UIView: 0x10bdaf4e0; frame = (56 8; 24 (4); layer = <CALayer: 0x2820ca440>>; sublayers = (<CALayer: 0x28216f5c0>, <CALayer: 0x28216e6c0>, <CALayer: 0x28216d3c0>, <CALayer: 0x28216d540>); opaque = YES; allowsGroupOpacity = YES; > (char *) $327 = 0x00000001e4f40ab8 "layoutSublayers"Copy the code

You can see the name of the method called before the crash, layoutSublayers, and the frame of the view.

JXPageControlEllipse = JXPageControlEllipse = JXPageControlEllipse = JXPageControlEllipse = JXPageControlEllipse = JXPageControlEllipse = JXPageControlEllipse = JXPageControlEllipse

To solve

CA::Layer:: layout_IF_needed (CA::Transaction*) : CA::Transaction*) : CA::Transaction*) : CA::Transaction*

// MARK: - -------------------------- Update tht data --------------------------
override func updateProgress(_ progress: CGFloat) {
	.
    
    CATransaction.setDisableActions(!isAnimation)
    
    .
    
    CATransaction.commit()
}
Copy the code
override func updateCurrentPage(_ pageIndex: Int) {
    .
    
    if isAnimation {
        CATransaction.begin()
        CATransaction.setCompletionBlock {[weak self] in
            .
            
        }
        
        .
        
        CATransaction.begin()
        .
        CATransaction.commit()
        
        CATransaction.commit()
        
    } else {
        CATransaction.begin()
        CATransaction.setCompletionBlock {[weak self] in
            .
        }
        .
        CATransaction.begin()
        .
        CATransaction.commit()
        CATransaction.commit()
    }
    currentIndex = pageIndex
}
Copy the code

Catransaction.begin () and CATransaction.com MIT () need to be used in pairs. The world is fine again 😀

// MARK: - -------------------------- Update tht data --------------------------
override func updateProgress(_ progress: CGFloat) {
	.
    
    CATransaction.setDisableActions(!isAnimation)
    CATransaction.begin() // Add the content
    
    .
    
    CATransaction.commit()
}
Copy the code

reference

Deep into the bottom of iOS crash solution

If this article is helpful to you, please click on my wechat official number: FSA Full Stack Action, which will be the biggest incentive for me. The public account not only has Android technology, but also iOS, Python and other articles, which may have some skills you want to know about oh ~