If you want to follow along, this app with bugs is in the Starter folder of the materials folder for this lesson.
This demo app has two bugs that represent some common issues you’ll find in your own apps. First, build and run this app. Xcode can’t find anything wrong with the syntax.
As you can see, the app is a slide show of cute dogs. Tapping the forward or backward chevrons cycles through the dogs.
Tap the right chevron to cycle through the dog pictures. As you tap the third dog, the screen goes blank. The app still runs; you can tap the chevron to go to the fourth dog, but the third dog is definitely broken.
If you open the console, you’ll see some bright red errors. This tells you that the image can’t be found. In this app, the images are stored in the asset catalog.
In an iOS app, you store images, sounds, colors, and other assets in an asset catalog. This gives you one place to organize all of them and makes it easy to reference them when needed. Using the Project navigator, open the asset catalog and look at the dog assets.
You’ll see that the third dog is “daytsuk,” but the error in the console is looking for “datsuk”. Now, go to ContentView.swift and fix the spelling error in the dogImages array.
Build and rerun the app. You’ll see the picture of Daytsuk. The console also no longer shows the error.
This type of error is impossible for Xcode to catch before the app runs. You’ll hear people refer to these assets as “stringly” typed. There are ways to minimize the stringly typed code in your apps, but there will always be some, so it’s a place to pay attention to as you work.
To find the next bug, continue to click the right chevron. When Ruth is the dog, the app will crash. You’ll see in the console that Fatal error: Index out of range is the bug that caused the crash. You can also see that line 70 is where the crash happens. dogImages is the array of dog picture names, and currentIndex is the index in the array.
In the console, query currentIndex for its current value. Use po currentImage to see that the value is 6. Alternatively, you could open self in the variables area and then open currentImage to see there that the value is 6.
If you scroll up, you’ll see that there are six image names. Remember from earlier lessons arrays are zero-based, so the maximum index for this array is 5. So, the way to fix this is to correct the value of totalImages and set it to 5. At this point, you’ll notice that totalImages isn’t really a good name for this value.
You could change this name to something more appropriate, like maxIndex. However, then you need to look through all of your code to make sure you change it everywhere.
Xcode helps you in situations like this. After you change the value to 5, right-click totalImages, and from the context menu, select Refactor and then Rename. Now, Xcode will find all the places in the app that reference your symbol. Change the name to maxIndex and click the Rename button. Now, the names have changed, and you can be confident you didn’t miss one.
While the app is still paused in this crash, look at the stack frames on the left. The ones with blue person icons are frames for your code. The other icons are other system frames. You can scroll down to the ContentView.body.getter frame and see that the same error appears. Scroll all the way down and click on main. You’ll see the error again, and you’re at the very beginning of the app.
This is how errors work in general. An error occurs and then bubbles up to each frame in the stack. The code in any of the frames may be watching for errors and can react to them. As you learn more Swift, you’ll run across something called try and do-catch. Those are for watching for errors to bubble up and reacting to them.
When an error reaches the frame called main without being caught, the app will crash.
Before you run the app one last time to verify your fixes, set two breakpoints. Set one on line 45 where you have var currentImage and another on line 64 where you have if forwardIndex > maxIndex {.
Open the Breakpoint navigator, and you’ll see there are two breakpoints.
Now, run the app. Notice that the app pauses on line 45. You can see from the frame that this is the first initialization of ContentView. Click the Breakpoint navigator. See that there are now seven breakpoints on line 45. This is because when you set a breakpoint on a variable declaration during runtime, it breaks this into multiple breakpoints, one for initializing the symbol and another for the different ways the symbol is referenced.
Suppose you disable all the breakpoints except the one for setting the value, marked .setter, and run the app. Now tap the forward button. Notice that your app pauses on the breakpoint on line 64. You can see the current values in the variables view. Now, resume the app and see that the app paused on line 45.
In the stack frame, you’ll see that your code is in the first two frames. Click the frame called closure #2. This is the frame that sets the new value into currentImage.
Setting a breakpoint on a variable declaration is really helpful when you determine that something is changing the value to a bad value, but you can’t quite figure out what is changing it.
Resume the app and click the chevrons to cycle through the images. Each time the app pauses, notice how the variables are changing values.