With iOS 10, Apple came out with an app for iPad called Swift Playgrounds, that has fun coding books that helps learn to code in Swift.
For WWDC 17, Apple's student scholarship asks students to create their own Swift Playground files that are "visually interactive". Since not all students have iPads to develop on, they can also create an Xcode playground, which will run in both Swift Playgrounds and Xcode Playgrounds.
I decided to apply for this scholarship and create my first Swift Playground. I ran into a few issues along the way, and I have documented them here.
You can check out my submission here!
File formats
The first major issue I ran into that was not immediately obvious to me is that there are two separate file formats: Xcode Playground and Playground Book, with the .xcplayground
and .playgroundbook
file extensions, respectively.
The differences between these are not documented well, but are very important to know about before deciding which one to develop.
Xcode Playgrounds
Playgrounds in Xcode came out before Playground Books, so this is an older format. Xcode playgrounds can be developed within Xcode on the Mac, and run on both Macs and iOS devices. They can be created easily through Xcode with a wizard.
They can target macOS, iOS, and tvOS, with access to the entire SDK for each platform.
Playground Books
Playground Books are specific to the Swift Playgrounds app on iOS, and only run on-device. Xcode is unable to provide any support while developing a Playground Book on your Mac, including nice things like code completion and compiler warnings / errors.
However, Playground Books are much more interactive and customizable. They include the following unique features compared to Xcode Playgrounds:
- Animated cut scene pages built in HTML5
- Full width live views (borderless)
- Hidden code on each page (for hidden setup, teardown, and other interactivity code)
- Custom auto-complete in the keyboard
- Chapters of pages
- Editable areas (restrict editing to a certain portion of code on the page)
- Placeholders
- Glossaries (add a list of terms and definitions viewable when tapping a term)
- Each page can be assessed on a pass/fail basis.
- Changes are tracked to each page and the page can be reset back to default by the user
- Data can be stored in an
NSUserDefaults
-like key value store.
PlaygroundSupport
When developing a playground, there is a framework you can use to do helpful things, called PlaygroundSupport. This framework helps you to:
- Access a playground page and manage its execution
- Display and dismiss live views
- Share and access persistent data
PlaygroundSupport
was added in iOS 8, and it used to be called XCPlayground
before that.
The live view you display on the right can be either a UIViewController
or UIView
.
Differences
While easier to create and cross-platform, Xcode Playgrounds are more limited in interactivity compared to Playground Books.
When I started my work for this scholarship, I did not realize that Playground Books use a separate format, so I started out creating an Xcode Playground and ended up switching mid-project.
I followed the Playground Book package hierarchy in the documentation and copied my code into a new book. Everything worked for the most part, except I had to change/separate some code because:
- In a Playground Book, each page can consist of both a
Contents.swift
andLiveView.swift
. Xcode Playgrounds only have aContents.swift
.LiveView.swift
should contain code setting up the live view when the page is opened. You can set thePlaygroundPage.current.liveView
in either file, but the code inLiveView.swift
will be executed when the page opens, not when theRun My Code
button is pressed. - Live views run isolated from the content and communication must be done through messages.
- To support this communication, the PlaygroundSupport framework in Swift Playgrounds has many more utilities you should look at, including
PlaygroundValue
andPlaygroundViewLiveMessageHandler
. These are specific to Playground Books. ThePlaygroundSupport
framework in Xcode does not contain these.
- To support this communication, the PlaygroundSupport framework in Swift Playgrounds has many more utilities you should look at, including
Learning by Example
The best way to learn how to write a Playground Book is by examining Apple's books. Download a book in Swift Playgrounds from the Featured
page. Tap the share button at the top left and AirDrop it to your Mac. From there, you can right-click the .playgroundbook
file and select Show Package Contents
. Explore the code and layout of those. It will help you tremendously.
Developing a Playground Book
I've been writing my code in Xcode. Open your .playgroundbook
in Xcode, and press cmd+1
to show the files/folders.
To run my book, I use AirDrop to transfer the file from my Mac to my iPad and run it there.
This is definitely not the best, but it's the most efficient method I've found.
Code completion
Some have suggested writing an Xcode playground and moving your files in between it and your Playground Book to get code completion. See here. This may work for simple projects, but for instances where you are using more advanced features in PlaygroundSupport
, you will run into compiler errors, since PlaygroundSupport
is different in Swift Playgrounds than in Xcode.
I have not found a reliable way to get code completion yet.
Debugging a Playground Book
There is no way to set breakpoints in either type of playground. Because of this, I was debugging via print statements. This got a lot harder when running a Playground Book since there is no console to look at.
Here's the solution I've found that works:
- Use
NSLog()
instead ofprint()
. - Plug your iPad into a Mac using USB.
- Open Console at
/Applications/Utilities/Console.app
. - Select your iPad from the
Devices
section on the left sidebar. - In the search bar, type the following:
- process:Playgrounds process:ExecutionExtension process:CompilerExtension
- Press
Enter
- You should see logs from both the Swift Playgrounds app and your own Playground in the console window.
Typically, when something crashes, you can see at least the description of the exception in Console, instead of a generic error that is displayed on screen.
You'll also now see constraint warnings and other warnings.
Cut Scenes
A cut scene is a special kind of page that renders HTML that is bundled into the playground. Apple used an app called Hype to create their animations for Learn to Code
, but any HTML page will do.
Believe it or not, Apple built this in HTML5, not in UIKit.
Navigating between pages
In a cut scene, it is important to add a button to go to the next page. In order to do this, make your button a link to the URL @next
. When clicked, this will tell Playgrounds to go to the next page. Likewise, you can add a @previous
link to go back.
Conclusion
If Apple wants people to create and distribute Playground Books, they NEED to allow Xcode to create them. It was a major pain creating my book without code completion or compiler warnings. Waiting to run on-device to see if what I did worked was no fun either. Thankfully AirDrop allows quick wireless transfer of Playground Books to my iPad, but even then, each time I sent an updated version to my device, it was copied along-side existing playgrounds, so pretty soon I ended up with hundreds of the same book from each iteration I pushed.
Even though the documentation is available, it is sometimes outdated and incomplete. I've filed two radars already with typos and incorrect information in the Playground Book documentation.
Hopefully, this experience improves in the future.