Intermediate Debugging with Xcode 8
Learn some intermediate debugging techniques with Xcode 8, such as breakpoint logging, conditional breakpoints, basic LLDB usage, and more. By George Andrews.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Starting Up by Tearing Down
When developing data driven apps, it’s often important to wipe the data store clean. There are a number of ways of doing this, from reseting the iPhone simulator to locating the actual datastore on your computer and deleting it. Doing this over and over can be a bit tedious, so get a little lazy and have Xcode do it for you.
You’ll start by creating a shell script. A shell script is a list of commands that automate some actions of the operating system. To create a shell script, create a new file from the application menu. Click File\New\File or Command-N. From the category listings, select Other and then select Shell Script as the type.
For the name, put wipe-db.sh.
In order to wipe out the actual datastore, you need to use the remove
command along with the full path to the data store (including the name for the current user). You could use Finder or Terminal to find the data store and then copy/paste its path into the shell script, but in Xcode 8, the name of the folder that contains the data store will continuously change each time you build and run the application.
To overcome this issue, you can use the whoami
command to output the current user and the wildcard character *
to provide for the changing folder names.
So enter the following into your script:
rm /Users/$(whoami)/Library/Developer/CoreSimulator/Devices/*/data/Containers/Data/Application/*/Library/Application\ Support/GiftLister.sqlite
Save the shell script and close it.
By default, shell scripts are read-only. You can use Terminal to set this script as executable.
If you don’t know where Terminal is located, you can find it in your Application folder inside of the Utilities folder.
Start Terminal and change your location to your home directory by entering the following:
YourComputer$ cd ~
Now, list the contents of the directory by typing:
YourComputer$ ls
You will have to navigate to the location of your project folder. If you placed it on your desktop, you would navigate to it by typing:
YourComputer$ cd Desktop YourComputer$ cd GiftLister
If you have to navigate up a directory, type the following:
YourComputer$ cd ..
After a long crawl through Terminal, you should see all the project files. To make the shell script executable, type the following:
YourComputer$ chmod a+x wipe-db.sh
chmod
changes the permissions of a file. a+x
allows the file to be executable for all users, groups, and others.
Wow… that was a lot. Take a breather. You deserve it. Sometimes being lazy takes a lot of work. :]
Close Terminal and return to Xcode. Open AppDelegate.swift.
Set a breakpoint on the first line of didFinishLaunchingWithOptions
. Right-click or Control-click the breakpoint and select Edit Breakpoint. Add an action and select Shell Command. In the next dialog, click Choose and select the shell script you just created. Click the Automatically continue after evaluating checkbox, and click away.
Stop the simulator if it is running.
Now build and run; the database has been deleted.
The simulator tends to cache a lot of data, so I find the best thing to do is perform a clean build by selecting Clean from Xcode’s product menu, then build and run. Otherwise, you can run the app, stop it, then run it again. The cached data will be gone with a brand-spanking new database.
While it did take some bit of work to setup, clearing out the database can now be performed with the press of a button. When not in use, simply disable the breakpoint.
Note: You just created a shell script and wrote a simple Unix command to delete the file. You could just as easily have loaded a PHP file within the shell script to do the same thing. You could also launch a Java program, Python script, or any other program on the machine. The key point is that you don’t need to learn shell scripting to manipulate the underlying operating system through a breakpoint.
Note: You just created a shell script and wrote a simple Unix command to delete the file. You could just as easily have loaded a PHP file within the shell script to do the same thing. You could also launch a Java program, Python script, or any other program on the machine. The key point is that you don’t need to learn shell scripting to manipulate the underlying operating system through a breakpoint.
Bonus Material: Sounding Out Your Save Methods
At this point, you should have plenty of data in the app. It’s time to save it all.
With apps like this, saving should be done frequently so that nothing is lost. That’s not the case with this app. It only saves when the user exits the application.
If you aren’t already there, click Back on the navbar to return to the root view controller, then simulate a Home button press. You can do this from the Simulator’s menu by selecting Hardware\Home or by pressing Shift-Command-H.
Now stop the program from Xcode, and build and run. The tableview is empty. The app failed to save anything. Hm.
Open AppDelegate.swift. In applicationDidEnterBackground
, you should see the problem at once in doLotsOfWork
. The work isn’t being finished in time, so iOS is terminating your app before it finishes its cleanup. The result of this early termination is that saveData
is not being called.
You’ll need to make sure that data is saved first. In applicationDidEnterBackground
, move the saveContext
call above doLotsOfWork
call like so:
saveContext() doLotsOfWork()
Now, add a breakpoint on the doLotsOfWork
line. Right-click or Control-click the breakpoint and select Edit Breakpoint. Select a sound action and choose Submarine as the sound. When dealing with sound actions, I try to avoid system sounds, as I may easily overlook them.
Next, click the checkbox next to Automatically continue after evaluating.
Finally, click build and run.
When the app starts again, add a new user then press the Home button in the simulator. Just after the app closes, you should hear the submarine sound, indicating that the data has been saved.
Stop the app in Xcode, then press Run. You should see the data in all its glory.
Playing a sound is a good way to know if a certain code path has been reached without having to look through the logs. You can also provide your own custom sounds in case you want to play an explosion for a particularly bad crash.
To do so, just drop your sound files in this folder:
YOUR_HOME_DIRECTORY/Library/Sounds
You’ll have to restart Xcode before you can use them, but think of all the potential shenanigans. :]
Time for one last bit of fun. Find your first breakpoint in FriendSelectionViewController
and Control-click or right-click the breakpoint. Click Edit Breakpoint from the menu. In the dialog, click the plus button; this lets you add multiple actions to a single breakpoint.
Select the Log Message action, only this time, type To be, or not to be. Select the Speak Message radio button, then click Done. The dialog should look like this:
Now build and run and enjoy the performance!
Note: Novelty aside, this feature can be quite useful! Audio messages can be especially useful when debugging complicated networking code and the like.
Note: Novelty aside, this feature can be quite useful! Audio messages can be especially useful when debugging complicated networking code and the like.