Troubleshooting with Xcode
- 2.5 hours on-demand video
- 1 downloadable resource
- Full lifetime access
- Access on mobile and TV
- Certificate of Completion
Get your team access to 4,000+ top Udemy courses anytime, anywhere.Try Udemy for Business
- Solve common bugs in Xcode and see how to troubleshoot these bugs.
- Avoid memory leaks by understanding internal memory management using instruments
- Explore various methods to troubleshoot bugs in our source code
- Measure the performance of code using profiling
- Prevent common developer mistakes that can cause malfunctions and crashes
- Embrace better coding practices to ensure your app delivers on performance
Print statements are the most basic form of debugging because they allow us to peek inside of a variable or any objects. Most objects have a description property, so by using a print statement, it’s possible to know what the code is doing at that point. Using print statements can be enough in some cases to debug Xcode issues. It is also possible to print file and function names and line numbers.
Print the content of an array of fruits
Print multiple objects using one print statement
Print filename, function name, and line number
Whenever there are bugs in the project, Xcode will print some information that are related to the bug in in the debug area. It’s not always the case that the information will be completely descriptive, but in some cases the details as to why the app crash will be provided.
Introduce a bug into the project to get a crash
Read the descriptive crash details in the debug area
Introduce new bug by removing the initial view controller
In the previous video we were able to fix Xcode issues by reading the debug messages in the debug area. However, in some cases, the debug messages will not be useful because the user will not be able to deduce what the bug is by reading the debug messages. We are going to see how to deal with these kinds of bugs in the future videos.
Delete a tableview with IBoutlet to introduce a bug
Introduce another bug by deleting an IBoutlet declaration
Fix the bugs and re-run the app
Build warnings are less serious in that they do not crash the app but they put the app in an unstable state. Whenever there are build warnings, Xcode will inform us in the debug area what has caused the warning and may also suggest some solutions to get rid of the warnings. Warnings do not prevent us from running or even releasing the app but they should always be addressed.
Introduce a layout constraint conflict warning into the project
Introduce another warning by running a UI code in background
Resolve the issues by fixing the codes that caused warnings
As you are building your app, there will be some unideal code or UI objects and Xcode will continue to call your attention to these issues. Issues are usually not as serious as a warnings or bugs but they are still important to address. Xcode will show you the number of issues you have in your project, and will inform you of a possible solution to fix the issue, and sometimes Xcode will give you an option of a one click fix.
Introduce an issue by moving a UI object from its original location
Create more issues by creating unused and unmutated variables
Learn how you can treat your issues as errors in your project
Low level debugger, as the name suggests, allows debugging at a lower level using a command line interface. It’s one of the most powerful debugging tool available in Xcode. The second powerful debugging tool is known as Breakpoints. Breakpoint allows the execution of the program to be paused at a particular point. This gives the ability to slowly examine what is happening in the program.
Bring up the low level debugger by crashing the app
Use breakpoint to pause the program execution
Print thread information to get insight into the crash
Whenever we run a program, functions are called. These function calls happen in a part of memory called the stack. As one function calls another function, they are placed on top of the stacks. Call stacks is very useful because it gives us a deep insight as to how our program functions are calling one another. We are able to see the functions that are called and in which order.
Create 4 functions and make a call within each function
Introduce a bug to see call stacks in debug navigator
Use the LLDB to print the back trace information
Sometimes there are variables in the program that are changed in different parts of the program. There must be a way to be able to debug if we run into issues where we are not sure how the values are changing. Breakpoints allows us to pause our program in multiple places, and then jump to all these different places in order, which will then allow us to inspect the values of the variable whenever the application is paused.
Create new variable and change the value in the function calls
Add multiple breakpoints in different parts of the code file
Use the variable view to inspect the value of the variable
The debug bar has various options such as the ability to step over a particular line or function which means the line/function will be executed. Other option include stepping inside of a function to take a closer look, and once done we can also step out and return to the original caller. These breakpoint tools make finding bugs a lot easier.
Modify the function calls to only change variable value
Add a breakpoint to pause the program execution
Use the debug bar to step over, step in and step out
Sometimes it’s easier to use the command-line interface to see what is going on. When the program is paused and the LLDB is available, we can get access to the program variables and use the console to print some of the variables, print view objects and even make function calls. This can be a very useful debugging method to find bugs.
Add multiple breakpoints to the program
Use the console to print the value of the variable
Use the po command to see function calls and view objects
Sometimes in our code exceptions are thrown, these exception can be anything from a file not being found or when trying to present a view controller that does not exist. When exceptions are thrown, the application will crash and the app will present the AppDelegate file. By default when exceptions are thrown, Xcode does not take us to the code that raised the exception. However by adding the Exception breakpoint to the project, the app will pause on the line of code just before the exception is thrown. This can be very useful to debug our app.
Present a new view controller from the storyboard
Introduce an exception into the code to crash the app
Add an exception breakpoint to catch the exception
Swift error breakpoints are used to catch any error thrown in your app. The error that are caught by this breakpoint are the errors that the user throw in the code. When error are thrown in your code, they can propagate to other places and they are continue to be thrown until the compiler can no longer throw them. This will result in a crash, and the app will pause in a different place than where the original error occured. Swift Error breakpoint pauses the app just before the error is thrown, thereby helping to debug the code better.
Use a do...catch statement to handle code that may throw error
Remove the do...catch statement to crash the app
Add Swift Error breakpoint to catch the error
The symbolic breakpoint is another generic breakpoint that can be used to find functions or methods in the entire project. Let’s say we have a function or method that we want to know when it’s called in the project, rather than go into many files and place a breakpoint on a particular line in a code file, we can simply provide the name of the function in a symbolic breakpoint so that anytime this function is called in our project, the breakpoint is triggered. This is also useful in situations where we do not have access to the underlying code.
Add a symbolic breakpoint from the Breakpoint Navigator
Provide the name of the function that you want to find
Run the project to trigger the symbolic breakpoints
One of the common errors in Xcode is when two layout constraints cannot be simultaneously satisfied and Xcode will make attempt to break one of the constraints. The error message will be logged to the console. Constraint error breakpoint can be used to trap any constraint error in our project, but unfortunately this feature is available only when developing MacOS app in Xcode.
Introduce constraint error and analyse the error message
Add Constraint Error breakpoint to attempt to catch the error
Reduce the constraint priority in order to resolve the breakpoint error
There are situations where we have multiple view objects with the same properties, and we need to quickly identify which of the view object has a constraint issue. There’s an LLDB command that we can execute in order to change the background color of the object. This makes it easy to visually see the object that needs to be resolved. Another way to identify the constraint that need to be resolved is to use a constraint identifier.
Add more buttons to the scene with the same heights
Use LLDB expression to change the background color
Use constraint identifier to identify which button’s height has issue
View hierarchy debugger is a visual debugging tool that allows us see all our views on a particular view controller in 3D mode. We’ll be able to interact with each view object in 3D mode. It’s even possible to hide some top/bottom views in order to get access to the required view. View hierarchy debugger is very useful when a view is not behaving in the way that we expect and we want to get more details on that view.
Add two UIView objects on top of the buttons with constraint error
Change the color of the button with constraint error
Use view hierarchy debugger to interact with the view objects
The app gauges give us information on how much resources on the device our app is using in real time. We get access to information such as the CPU, RAM, network access, location, disk access etc. These are useful debugging information because if the app is using excessive memory in certain parts of our app, the iOS system can kill the app, so it is very important to pay attention to codes that may be consuming resources unnecessarily.
View the App Gauges in the Debug Navigator
Create a CPU intensive function that generate random numbers
Load more values in table view, check performance in App Gauges
Color Blended Layers option allows us to see on the simulator which of our views are optimised for blending. Blending happens between two views when one of the view object has a transparency property. Because a transparent view requires the color of the view below it to blend through, the GPU has to do more work in order to render the views. By enabling the Color Blended Layers option, we can visually see which views are optimised for blending and which aren’t.
Enable the option from the Debug menu of the simulator
Set the background color of the cell text label to white
Remove the alpha property of the image to avoid blending
The Quick Look option on Xcode is similar to what we have on MacOS where it is possible to take a peek of a file content without having to launch the app. Inside the variable view, it is possible to get a preview of a view object, a URL, location object, and even a UIColor object. This allows us to get a visual representation of what a variable/object looks like while in the debugger.
Pause app execution to bring up the variable view
Use the Quick Look option to show the table view object
Use the Quick Look option to view other interface objects
Most times as a developer, while trying to debug our program, we tend to use lots of print statements to get more information on an object or a variable. Having too many print statements can be a mess, this is why using the breakpoint log message feature is a better solution than using a print statements.
Create function to add, subtract, multiply and divide a value
Use print statements to print the values of the variable
Use breakpoint log message to replace the print messages
While debugging a program, it is sometimes required to know how many times a function has been called, especially if that function is modifying a variable. There’s a feature of breakpoint that will tell us the name of the function where the breakpoint was added and how many times the function was called. This is very useful information for debugging.
Use the function name placeholder in the breakpoint log message
Use the hit count placeholder in the breakpoint log message
Replace all breakpoint log messages with placeholders
Every breakpoint we have looked at so far in this course has been hit, but sometimes we don’t want a breakpoint to be hit until a certain condition has been met. For example let’s say we only care about certain values in our project and only when these certain values are met only then we want the breakpoint to be executed. This is when we set breakpoint conditions.
Create a function that store the odd numbers in array
Print every values that are divisible by 5 within the loop
Add a condition to the breakpoint to replace the code
So far we have added a single action to our breakpoint in the form of message logging. Sometimes we may want to perform more than a single action to a breakpoint just so we can get more information from the breakpoint. Actions that can be added include playing a sound, or using LLDB commands and so on.
Add another breakpoint action to run a debugger command
Add another action to the breakpoint to play a sound
Skip the first breakpoint when the condition is met
All of the breakpoints that we have added to the project so far have been through the Xcode user interface. Sometimes we may want to work with breakpoints in the console, by adding new breakpoints, deleting existing breakpoints, enable and disable breakpoints and so on. Xcode also gives the options of using shortcut so that we don’t have to type lots of commands in the console.
List all breakpoints in the project using the LLDB
Enable, disable and delete some commands from the console
Learn how to use the shortcuts for the breakpoint commands
Xcode instruments consist of lots of tools for profiling the performance of the app. There are different templates that can be used to measure different aspects of app performance such as memory, CPU, network access, game performance and so on. Instruments is not only to find bugs but to find any bottlenecks where we might be able to improve the app performance.
Launch Instrument from Xcode Menu
Learn how to select other useful profiling templates
Use the activity monitor template to see some app stats
Memory allocation profiling template can be used to see in real time how much memory space is allocated to objects. This is useful because it allows us to see when too much memory is used in certain parts of the app.
Use the debug navigator to examine app memory usage
Use Instruments Allocations profile template to measure app
Debug and identify the line that use the most memory
There are many things that can result in a memory leak but one of the most common form is when there is a retain cycle. A retain cycle happens when two objects have a strong reference to each other and the operating system is not able to reclaim the memory space used by these two objects.
Introduce a memory leak into the project
Use the Instruments profiling template to find memory leak
Fix the memory leak and confirm the issue was solved
Sometimes there’s an area in our app that might be using excessive processing time, which means the user interface may be affected. Time profiler allows us to find the CPU bottlenecks in our app so we can optimize the codes in these parts.
Launch Instruments and select Time Profiler template
Run a CPU intensive code on the main thread
Debug to find the exact line of the CPU bottleneck
In this video we discuss some general tips to improve the performance of your app. These include using background thread for CPU intensive tasks, avoiding retain cycle, using instruments to measure app performance, data caching, reusing views and so on.
Go through some tips to improve the performance
- Prior Swift programming knowledge is assumed.
Xcode is an integrated development environment (IDE) for MacOS containing a suite of software development tools developed by Apple for developing software for MacOS, iOS, watchOS, and tvOS.
With this course, you will learn how to implement some practical and proven techniques to improve your debugging techniques using Xcode. This course will show you how to overcome common development bugs and issues and how to optimize your app for better performance. By the end of this course, you will be proficient at using Xcode 10 in solving common problems faced during development, you will become familiar with many built-in tools that can be used for solving common bugs in any Xcode project.
About The Author
Dee Aliyu Odumosu has developed over 120 apps for clients, including both individuals and start-ups, from around the World. The apps, some of which can be found on his website, range from basic to very complex. Dee’s passion for computer programming began in 2006 with his first contact with the Java programming language. He continued to learn different languages, including Microsoft ASP.NET, Ruby on Rails, C#, some PHP, HTML, and CSS. Dee briefly pursued a MCSE (Microsoft Certified System Engineer) certification before he decided he wanted to become a full-time programmer. He achieved Microsoft Certified Professional status. For the last 5 years, Dee has been programming on the iOS platform using Objective-C and Swift.
- This course aims to give iOS developers new possibilities for iOS application development using Xcode. They are now keen to learn some useful, interesting ways to further improve their Xcode debugging skills to solve common issues and to build powerful iOS applications in a much more unique and easy way.