“I only have an iPad. Can I use it to develop iOS apps?”
This is one of the most common questions for beginners. My answer is always “No, you need a Mac to run Xcode for iOS app development.”
“But how about Swift Playgrounds for iPad? Can I use the app to learn Swift and app development?”
I believe you know Apple released an app called Swift Playgrounds for iPad. The first version of the iPad app was released in September 2016 with the aim to make it easy for everyone to learn the basics of programming, in particular, the Swift programming language. And, thanks to the release of Catalyst. Apple has built a Mac version of Swift Playground from its iPad app and released it last month. You can now run Swift Playgrounds on both iPad and macOS.
Personally, I don’t use to recommend Swift Playgrounds for iPad as the learning tool of iOS programming if your goal is to build a real app and make it available on the App Store. Don’t get me wrong. Swift Playgrounds is a great education app for newbies to get a taste of what Swift programming is and learn the basic programming concept. However, it’s not the real development tool. Most of the Swift Playgrounds’ lessons do not prepare you to build a real world app.
Jason Cross from MacWorld wrote a great piece sharing his experience with Swift Playgrounds. He mentioned that the app did teach him the programming concept in an engaging way. But he also highlighted one main issue of Swift Playgrounds.
Swift Playgrounds teaches concepts and uses real Swift structure, but it’s not real code. It doesn’t make an app, it just guides Byte around and solves puzzles. Swift doesn’t have a real command called collectGem() after all.
Swift Playgrounds can satisfy your curiosity about what coding is and how it works, but it doesn’t really let you write apps. Not even a super-simple basic one. The code you write can’t leave the app; it can’t even leave that particular puzzle page!
More importantly, there is a gap between Swift Playgrounds for iPad and Xcode on Mac.
If Apple wants to really inspire people—both kids and adults—to write code instead of just learning what code is, it needs to bridge the gap between the colorful puzzle-solving of Swift Playgrounds and Xcode’s developer-centric environment.
What you’ve learned using Swift Playgrounds doesn’t directly apply to Xcode. You still need to get familiar with the development environment, learn how to use Interface Builder, and understand how to use the APIs provided by the iOS SDK. The gap between the iPad app and Xcode is quite large. This is why I recommend my students to jump right into Xcode and learn the programming concept along the way. Even if you just want to try out Swift, use the Playgrounds tool that come with Xcode. It would give you a more realistic programming experience.
Earlier, we published a new book on SwiftUI. Once again, we got a similar question:
“Can I learn SwiftUI on iPad?”
Since the release of Swift Playgrounds v3.1, Apple added the support of SwiftUI. While I still recommend to get a Mac and learn to write code in Xcode, I’m also curious about the possibility of learning SwiftUI with this educational tool. To find out the answer, the best way is to experiment it. I tried to write a simple Swift UI demo entirely using Swift Playgrounds for iPad and see if it works.
If you have an iPad, I encourage you to follow the procedures to create the app too and share your experience in the comment section.
Here are what we are going to cover in this tutorial:
- How to run SwiftUI apps on Swift Playgrounds
- Write a SwiftUI demo app using Swift Playgrounds for iPad
- Run the same app on Swift Playgrounds for Mac
- Limitation of Swift Playgrounds for iPad and Mac
Okay, let’s get started.
The Demo App
First, what are we going to build? It’s a very simple demo that showcases some of the blend modes. We will overlay two images together and apply different blend modes to see the effect. If you’ve used Photoshop or other photo editing apps before, blend modes shouldn’t be new to you. By blending two layers together, you can easily create some amazing image effects.
SwiftUI provides built-in support for various blend modes such as hardlight, multiply, darken, and saturation. The demo app will showcase some of them.
Writing SwiftUI apps Using Swift Playgrounds
Assuming you’ve installed Swift Playgrounds on your iPad, let’s start by creating a blank project to try out SwiftUI. If you haven’t installed Swift Playgrounds for iPad, please first download and install it from here.
Once you open Swift Playgrounds, it provides you with various lessons and templates. We will start with the Blank template (under the Starting Points section).
After you install the template, the app creates a blank project for you with the default name “My Playground” (or something like that). Tap to open the project and you will see a blank editor. Simply tap the screen to start coding and type the following code:
import SwiftUI
import PlaygroundSupport
struct ContentView: View {
var body: some View {
Text("Hello SwiftUI!")
.font(.system(.largeTitle, design: .rounded))
.bold()
}
}
PlaygroundPage.current.setLiveView(ContentView())
Thanks for Paul for the tip. The trick to run and preview SwiftUI is to import the PlaygroundSupport
module and write the last line of code. This allows you to set the live view and show the visual results of running the code on the playground page.
Swift Playgrounds for both iPad and Mac has a built-in support for code completion. While you type the code, it continues to suggest completions. On iPad, the suggestions appear in the software keyboard. You tap the suggested keyword to add it to the editor. The code completion works pretty well. It’s easier than I thought to type all the code entirely using the built-in keyboard.
If you use Swift Playgrounds for Mac, the code completion works even better. You can press ENTER/return to accept the suggestion.
Assuming you’ve written the code, you can tap the Run My Code button to see the result. Swift Playgrounds will then execute the code and display the visual result on a separate pane.
The code you’ve written makes use of the SwiftUI framework and displays a text label on screen. SwiftUI provides various modifiers to customize the UI components. In the code, we use the .font
and .bold
modifiers to change the font style. Actually, when you type “.” after instantiating the Text
view, Playgrounds automatically shows all the available modifiers in the keyboard. Say, you can add the .foregroundColor
modifier to change the text color.
That’s how you can use SwiftUI in Swift Playgrounds for iPad. I’m not going to explain other text modifiers. If you love to learn more, check out this tutorial on SwiftUI text.
Now let’s try to build something more complicated and see if Swift Playgrounds can handle other UI components such as Image
, ZStack
, and gestures.
Building the Demo App
As mentioned earlier, we would create a simple app that demonstrates the effect of blend modes. First, we need to prepare two images. In fact, any images would work but I’d recommend you to download the following images and save them to your photo album.
Adding Images on Swift Playgrounds for iPad
Now switch back to the Playgrounds project and delete all the code related to Text
. And, then start writing the code to overlay the two images like this:
To display an image using SwiftUI, you use an Image
view. It’s a bit tricky to import the image into the Playgrounds project. Instead of loading the image using the filename, we initialize it with uiimage
. Once you type the code above, you should see the image icon on the software keyboard. Tap that icon and then choose Photo Library -> Recently Added to select the first image (the one with tables).
Swift Playgrounds will then import the image into the project. And, you should see that UIImage
is now replaced with a thumbnail of the selected image. Continue to type the following code to add some modifiers and overlay the second image over the first one:
In SwiftUI, you use a ZStack
to overlay one image on top of the other. The resizable
and scaleToFill
modifiers are used to resize the image to fit the preview pane. If you run the code, you will only see the second image. The first image is actually there but just covered by the second one.
Applying Blend Modes
SwiftUI provides a modifier called blendMode
to control how these two images are blended with each other. Let’s do a quick test and you will understand what this means.
Insert the blendMode
modifier for the second image and then hit Run My Code to see the effect:
There are a total of 21 blend modes provided by SwiftUI such as color, colorBurn, and difference. In the example above, we apply the color blend mode, which preserves the brightness of the bottom image, while adopting the hue and chroma of the top image.
Using Shared Code and Modules in Swift Playgrounds
Now that you should understand what blend modes mean, let’s try out another feature in Swift Playgrounds and make the app demo interactive. We will let users tap on the image and switch to another blend mode.
Swift Playgrounds allows developers to create sharable modules such that the code can be shared across all the Playgrounds pages. To simplify your work and demonstrate this code sharing feature, I already wrote some of the code for you. You will just need to copy & paste it into your shared module and then use it directly.
To place the code in a module, tap the document icon in your Playgrounds project and select UserModule -> SharedCode.swift. You are allowed to create your own module and files. For this demo, however, we simply use the default module.
Once SharedCode.swift
is opened, copy & paste the following code in the file:
import SwiftUI
public enum ImageEffect: CaseIterable {
case normal
case color
case colorBurn
case difference
case multiply
case luminosity
case saturation
public func next() -> Self {
let allCases = Self.allCases
let currentIndex = allCases.firstIndex(of: self)!
var nextIndex = currentIndex.advanced(by: 1)
if nextIndex == allCases.endIndex {
nextIndex = allCases.startIndex
}
print(nextIndex)
return allCases[nextIndex]
}
public func previous() -> Self {
let allCases = Self.allCases
let currentIndex = allCases.firstIndex(of: self)!
var prevIndex = currentIndex.advanced(by: -1)
if prevIndex < allCases.startIndex {
prevIndex = allCases.endIndex - 1
}
print(prevIndex)
return allCases[prevIndex]
}
}
extension ImageEffect: RawRepresentable {
public typealias RawValue = BlendMode
public init?(rawValue: Self.RawValue) {
switch rawValue {
case BlendMode.normal: self = .normal
case BlendMode.color: self = .color
case BlendMode.colorBurn: self = .colorBurn
case BlendMode.difference: self = .difference
case BlendMode.multiply: self = .multiply
case BlendMode.luminosity: self = .luminosity
case BlendMode.saturation: self = .saturation
default: return nil
}
}
public var rawValue: BlendMode {
switch self {
case .normal: return BlendMode.normal
case .color: return BlendMode.color
case .colorBurn: return BlendMode.colorBurn
case .difference: return BlendMode.difference
case .multiply: return BlendMode.multiply
case .luminosity: return BlendMode.luminosity
case .saturation: return BlendMode.saturation
}
}
public var text: String {
switch self {
case .normal: return "Normal"
case .color: return "Color"
case .colorBurn: return "Color Burn"
case .difference: return "Difference"
case .multiply: return "Multiply"
case .luminosity: return "Luminosity"
case .saturation: return "Saturation"
}
}
}
You may not fully understand the code, especially if you are new to Swift. In brief, we create an Enum
named ImageEffect
. This piece of code defines some of the blend modes we want to showcase, gives them a default name, and makes it easy for you to navigate between different modes.
When you open another Swift file in Playgrounds, the app opens a separate tab for you to edit the file. To switch it back to the original file, tap the Book icon.
Now we will modify the code to detect users’ touch and switch between various blend modes. First, declare a state variable to hold the current blend mode (see the below figure if you don’t know where to place it):
@State private var currentBlendMode: ImageEffect = .normal
Next, change .blendMode(.color)
to use the currentBlendMode
variable like this:
.blendMode(currentBlendMode.rawValue)
We set the default blend mode to .normal
which means the top image completely covers the one beneath. So, when you first run the code, you will only see the top image without any blend effect.
SwiftUI has made it pretty easy to detect users’ touches. To recognize a tap gesture, you can attach a .onTapGesture
modifier to the second image and place it after .blendMode
:
.onTapGesture {
self.currentBlendMode = self.currentBlendMode.next()
}
When a tap is detected, the code in the code block will be executed. We then switch the blend mode to the next blend mode. The next()
function can be found in the shared code, which was the code snippet you added earlier.
Now if you run the code again, you can switch to the next blend mode and see the effect by tapping the image.
The app already works, but you can make it better by displaying the current blend mode on screen. To overlay a text label at the bottom part of the image, insert the following code in the ZStack
:
VStack {
Spacer()
Text(currentBlendMode.text)
.font(.system(.title, design: .rounded))
.bold()
.foregroundColor(.white)
.padding()
.background(Color.yellow.opacity(0.5))
.cornerRadius(5.0)
}
.padding(.bottom, 100)
After you made the change, you should see a yellow label which displays the current blend mode. The padding
modifier in the code above is used to add some space between the label and the bottom edge. If you don’t know where to place the code above, please refer to the image below:
That’s it! You’ve built a SwiftUI demo entirely on iPad. Is it easier than you think?
Error Handling and Print to Console
There are a couple of things that are worth to mention about coding on iPad:
- How does Swift Playgrounds handle coding errors?
- Where is the console message?
When a compilation error is detected, Swift Playgrounds indicates the line of code with a red dot. Tapping the red dot will give you some more information about the error. In some cases, it even suggests the possible fix, similar to that on Xcode. To reveal all the issues in the Playgrounds file, you can also tap the red dot at the top-right corner.
It’s very common to use the print()
function to output the value for debugging purpose. In Xcode, the message appears in the console. So, how about Swift Playgrounds for iPad? Where is the console?
There is no console for Swift Playgrounds. But you can still reveal the output by using a built-in viewer. If you want to give it a try, open the SharedCode.swift file and run the code. There is a print
statement in the next()
function. While running the app, you should see a counter at the end of the print
statement. Tap the counter and then you’ll see the output value. Optionally, you can choose the Add viewer option to place a viewer right below the print
statement.
Since Swift Playgrounds is designed for educational purpose, sometimes you don’t even need to use the print
function to reveal the value of a variable. Say, if you don’t understand what Self.allCases
means, you can tap the counter and find out what’s in allCases
.
Limitations of Swift Playgrounds for iPad and Mac
While we’ve built a demo app entirely using Swift Playgrounds for iPad, does it mean it can completely replace Xcode for learning SwiftUI? One major limitation of Swift Playgrounds is that not all SwiftUI components work well in the preview canvas of the iPad app. I didn’t test all the built-in components but just try out a few. Say, for example, Swift Playgrounds for both Mac and iPad can’t present a modal view using the .sheet
modifier. The same piece of code works on Xcode but functions differently on Swift Playgrounds. This would definitely affect your learning experience. You just don’t know whether you did something wrong or it’s a limitation of Swift Playgrounds.
The other limitation is that Swift Playgrounds doesn’t come with built-in simulators. All the visual results are presented in a rectangular canvas. On Xcode, you can choose which simulator to use for rendering the result. For example, the same piece of code above is rendered like a split view on Swift Playgrounds. But if you run it on Xcode, it’s rendered on an iPhone simulator like this:
And, as you may notice, there is a blue rectangle around the navigation view. This is one of the great features you can’t find on Swift Playgrounds. Added to that is the instant preview which is also missing on Swift Playgrounds.
That said, with SwiftUI, it does narrow the learning gap between Swift Playgrounds and Xcode. Everything you learn about SwiftUI on Playgrounds is transferable to Xcode. Take the demo app we developed earlier, you can reuse all the code in the Xcode project and create the iPhone app.
Of course, you still need to familiarize yourself with the Xcode development environment (like how to use asset catalog to manage images) and learn how to preview the UI. But the thing is it’s already a huge improvement as compared to the past without the SwiftUI framework. The gap between Xcode and Swift Playgrounds is closing.
What’s Next?
I hope this article gives you an idea about using SwiftUI on iPad. So, what if you only own an iPad and want to learn SwiftUI? My recommendation is download Swift Playgrounds and start coding SwiftUI on iPad. Once you feel comfortable with the basics and are really serious about iOS programming, invest a Mac and continue the learning on Xcode.
If you are interested in learning more about SwiftUI, here are some of the free tutorials:
- Working with Text in SwiftUI
- How to Create Star Wars Animated Text Using SwiftUI
- How to Create a Card View with Stacks
- Working with SwiftUI Gestures and @GestureState
And, if you’d like to dive even deeper, check out our Mastering SwiftUI book.
Lastly, I really want to hear your feedback on your learning experience with Swift Playgrounds for iPad. Please feel free to leave me comment and share your experience.