Monday 2 July 2018

Fix 07_BoggieBot.playground errors "Cannot call value of non-function type 'NSGraphicsContext?" and "Cannot convert value of type 'NSApplication.ModalResponse' to expected argument type 'Int'"

Problem:

When trying to learn from 07_BoogieBot.playground alongside Apple's Everyone Can Code "Intro to App Development with Swift", I get errors similar to:
07_BoogieBot.playground/Sources/Recorder.swift:26:51: Cannot call value of non-function type 'NSGraphicsContext?'
07_BoogieBot.playground/Sources/Recorder.swift:33:99: Cannot call value of non-function type 'NSGraphicsContext?'
07_BoogieBot.playground/Sources/Recorder.swift:70:31: Cannot convert value of type 'NSApplication.ModalResponse' to expected argument type 'Int'
The console shows me the following:
Playground execution failed: error: /var/folders/1g/_b7g8rjd71j_mwjxdj29vllc5x9cxx/T/playground11-16e897..swift:3:8: error: no such module '_7_BoogieBot_Sources' import _7_BoogieBot_Sources
I am using XCode 9.4.1 and macOS 10.13.5

Before you start:

You'll want to make a backup of lesson 7's code first. Just make a copy of the folder in Finder. We'll be editing the code that runs the playground, so this way you can undo by restoring the backup if you've forgotten what you changed and introduced a bug.

Workaround:

You're learning coding for the first time, and you've been given a chance to debug the playground you're learning from. Cool!

Here's a few quick steps to get your BoogieBot lesson going!

Step: Have a look at the errors

In XCode you can view what errors have broken your code. In our case, click here:
You'll see a list of errors appear in the navigator in red. Try to click one:
Wow, that's more code that you've seen in the previous lessons. No worries. Just focus on the problem you're trying to solve and ignore the rest.

Step: Fix the 'context' bug

For the lines that have:
if let context = NSGraphicsContext.current()?.cgContext
Remove the (), so they look like:
if let context = NSGraphicsContext.current?.cgContext
If you save the file and the 2 errors go away, you've made progress. Congrats on debugging so far!

Why does this code change work?

Someone at Apple had changed NSGraphicsContext.current from a function to a property.

As you recall from an earlier lesson, programmers will often have to build on code made by others. In this case the code happens to be from those who worked on part of the graphics programming for macOS 10.13. These are changes you'd see if coding in XCode 9 (instead of XCode 8).

Step: Fix the Modal.Response bug

For the code that looks like:
if (savePanel.runModal() == NSFileHandlingPanelOKButton) {
Change it to look like:
if (savePanel.runModal() == .OK) {

Why does this code change work?

Without getting too technical, essentially someone at Apple had changed the way this test should work.

IF you're really curious and aren't learning to code for the first time, have a look at https://developer.apple.com/documentation/appkit/nsapplication/modalresponse

Step: Go back to the BoogieBot Playground

Now that you've debugged the code and saved it, check that no errors still exist. (The yellow warnings won't block you from lesson 7.)
Cool. Now you can return to learning about BoogieBot by clicking here and going back to your playground:
Happy boogie-ing!

Notes

This how-to was tested to work using XCode 9.4.1 and macOS 10.13.5. The bug was seen in the playground downloaded sometime June 2018. Your results may vary depending on versions, and if Apple fixed the playground by the time you read this post. Code can change pretty quickly in real life.

If you ran into this bug, hopefully you were able to fix it and learn how to make your boogie bot dance using Swift!