This article mainly includes three aspects:
Use console to check app status
Logging and mastering NSLog
Use the lifecycle of an object to track memory usage.
Use Console to check app status
The small black box at the bottom of Xcode is a good friend during debugging. It can output log information, error information, and other useful things to help you track errors. In addition to the information directly output by logs, during programming, we can also stay at certain breakpoints to check multiple aspects of the app.
Conditional breakpoint
I suppose you know how Breakpoints works (if you don't know, you may know after reading this article !)
It is very valuable for a program to hit a breakpoint at a specific point in time, but it is painful to make the object equal to a fixed value through a loop or recursive function. In this case, we can use conditional breakpoints!
A conditional breakpoint is a breakpoint with a conditional expression. Only when this condition is met Will the program pause. Suppose we only want to break a breakpoint when the object is in a specific State, or hit a breakpoint in the nth iteration loop.
Click 'gutter 'in Xcode editor to add a breakpoint. Right-click the breakpoint and select "edit breakpoint" to set specific conditions.
Conditional breakpoints are interrupted only when a specific situation occurs. You can provide a condition (such as I = 12) or the number of times the breakpoint should be ignored. In addition, you can add an action that can automatically occur based on the breakpoint, such as a debugger command --- print a value.
Tip: the keyboard shortcut for adding/deleting breakpoints is command + \
Another important breakpoint technique is to add an exception breakpoint (exception breakpoint ). When an exception occurs, Xcode will basically automatically go to The autorelease pool of the main method.
By setting an exception breakpoint, you can locate the specific code line that causes the exception breakpoint.
How do I add an exception breakpoint?
1. Open the exception breakpoint tab (command + 6); 2. Select the "+" button in the lower-left corner of the window; 3. Select the button and add 'exception breakpoint '.
In this way, when Xcode encounters an exception, a breakpoint will occur where the Exception Code is caused.
Manually print from the Console
Theoretically, it will show the status of all values in the current environment; in fact, sometimes there will be bugs, and no values will be listed or you will not update them when performing single-step debugging.
Generally, we add a specific breakpoint to the app code to view the object status through the 'variables view' provided by Xcode (this view is next to the console at the bottom of Xcode. Theoretically, it can display the status of all values related to the current context. In fact, sometimes there may be a small problem. Related values are not listed or related updates are not performed.
However, we can use some useful console commands to check specific objects. Enter 'po' in the console to obtain the real-time information of a breakpoint. (When processing the scalar value, we can use 'P ')
This is useful when we look at an existing object (nil is printed if the object does not exist), determine the object value, and find out the information of the array/dictionary runtime, even compare two objects. Because this command prints the memory address of the related object, you can print the two objects you think should be the same to see if their memory address is the same.
Another useful command, but the hidden command is recursiveDescription. You can simply use it to check the view.
Call recursiveDescription in view to print its inheritance relationship.
Valid Logging
Sometimes, at a specific time of the debugging program, we want to print the message to the console. In this case, the 'nslog' function allows us to print any output to the console.
In this case, you can use the NSLog function to print any output to the console. This function is useful when no breakpoint is used. The format of NSLog compliance is the same as that of the [NSString StringWithFormat] method. (You can see from below)
Tip: here we can see the String formatting information about Objective-C: String Programming Guide
NSLog
NSLog is very useful. We need to implement it intelligently. Everything printed from NSLog is converted into code, which can be seen by anyone. Connect the device to your computer, open the organiser in XCode, And you can view each log on the console, which has a great impact. Think about it. You want to print some confidential algorithm logic or user passwords to the console. Because of this, if Apple finds that too much content is output to the console in the production build, your application may be rejected by Apple.
Fortunately, here is the simplest way to perform log-through a macro, NSLog only works during debug build. Add this function to the header files that can be accessed globally. In this way, you can use log as much as possible, and the log-related code is not included in the production. The following code:
# Ifdef DEBUG # define DMLog (...) NSLog (@ "% s % @", _ PRETTY_FUNCTION __, [NSString stringWithFormat :__ VA_ARGS _]) # else # define DMLog (...) do {} while (0)
If you use DMLog, it can only be printed during debug build. _ PRETTY_FUNCTION _ can also help print the name of the function where the log is located.
Next step
NSLog is powerful, but it has many limitations:
1. Local printing only
2. Hierarchical logs (for example, dangerous logs or warnings) are not supported)
3. NSLog is very slow. when processing a large amount of data, the program running efficiency is significantly reduced.
We recommend two frameworks to avoid NSLog restrictions:
? Cocoa LumberJack-one of the well-known common Cocoa log frameworks, it is difficult to learn, but very powerful.
? An alternative to SNLog-NSLog.
Lifecycle of a trail object
Although the Automatic Reference Counting (ARC) has made memory management simple, time-saving, and efficient, tracking important events in the object's life-cycles is still very important. After all, ARC does not completely eliminate the possibility of Memory leakage, or tries to access a release object. For this purpose, we can use some processing methods and tools to help us stare at what objects are doing.
Important LOG events
There are two important methods in the life-cycle of the Objective-C object: init and dealloc, it is a good choice to log the events called by these two methods to the console-you can observe the beginning of the object's life through the console. More importantly, you can ensure that the object is released.
Static analyzer and Inspector (checker)
Xcode also has two tools to help us clean up code and reduce the chance of code errors. Static analyzer is a great tool for improving code for Xcode. For example, we can check that there are no used objects and no release objects (for Core Foundation objects, ARC still has such problems ). Select 'anlayze' from the Product menu to view related suggestions.
The checker is a very powerful set of tools. It not only checks the memory usage of programs from different angles, file System usage (add, delete, modify, etc.), and even provides automatic UI interaction methods. You can select 'profile 'from the Product menu to view these checkers.
Selecting 'profile 'opens an Instrument window, where you can select a configuration template for running. The most common templates are zombies (which will be discussed later), activity monitor, and leaks. Leaks may be the most useful template for capturing memory Leaks when running programs.
Zombies is your friend
Although it is difficult to encounter an uncomfortable EXC_BAD_ACCESS error where there is an ARC, this error will still happen under certain conditions. When processing a UIPopoverController or core foundation object, we can access an object that has been release. Generally, an object in the release memory will be destroyed. However, when Zombies is enabled, only the object is marked as release. In fact, this object remains in the memory. When we access a Zombie object, Xcode tells us that the object we are visiting is an object that should not exist. Because Xcode knows what this object is, it allows us to know where it is and when it occurs.
There are two ways to find the Zombies object. Use the Zombie configuration template in the checker or enable the Zombie diagnostic option in the 'run' build option. Click the scheme name next to the Stop button, select 'edit Scheme ', click the diagnostic tab, and select 'Enable Zombie objects '. Note: Zombie can only be used in simulator debugging and cannot be used on a real machine.
Note that Zombie mode debugging is only applicable to simulators and cannot be used on real devices.
Summary
I hope the above content can help you debug your app more efficiently, all of which are to save time for bug fixing, so that developers can spend time on more important things, or create a great application.
The list above is definitely not a comprehensive list, and there are many methods we haven't discussed, such as remote control bug reports, crash reports, and more. I hope you can share more with me.