Streaming is available in most browsers,
and in the Developer app.
-
Build your first app in Swift Playgrounds
Learn how you can easily prototype and build apps with Swift Playgrounds. We'll show you how to create an app from a blank project, build its interface with SwiftUI, and use Swift Package Manager to add extra functionality from an open source package. We'll also explore how you can debug issues using Previews and the console and take you through submitting an app to App Store Connect for distribution via TestFlight.
Resources
Related Videos
WWDC22
-
Download
- Welcome to "Build your first app in Swift Playgrounds." I am Collett Charlton, an engineer on the Swift Playgrounds team. - And I'm Connor Wakamo, another engineer on the Swift Playgrounds team. - Swift Playgrounds has been a great tool for learning to code in Swift, and now you can take things a step further and build apps too! Today, we're going to walk through building an app in Swift Playgrounds, starting with a blank template. We'll then show how to debug issues using previews and the console, and finally, we'll submit our app to TestFlight.
Something our team really loves is making and drinking tea. We love it so much that we want to make an app for that. Connor and I are going to build a little app to help us at tea time, giving us a list of teas to help us pick what to drink each day. Swift Playgrounds works great on Mac and iPad. I've got my Mac with me today, so I'm going to start building this app there.
Whether you are new to coding, or are an experienced developer, Swift Playgrounds offers a variety of templates and instructional content to get you started. For our tea app, we'll begin by clicking the blank App template in the bottom left corner of the screen.
Now that we have our template, let's double click to open.
Great. On the right is a live interactive preview showing the Hello World text.
Before we start coding, let's customize the app a little using the App Settings. To do this, I'll click the app settings button in the top left corner of the sidebar. Here, you can customize various project properties like the app name and the accent color. You can also add a custom or placeholder app icon, capabilities, or purpose string, and a bundleID. I'll update the app's name to Tea Time.
I'll set the accent color to brown. And I'll update the placeholder icon to the mug.
Great. Now that the important part's out of the way, let's start writing some code by selecting the template text and replacing it with our first View from the Library. The Library can be accessed by clicking the plus button in the project toolbar. It contains easy-to-use snippets of different Views, Modifiers, SF Symbols, and Colors. We'll be using a List View to display our list of teas, so I'll type list into the search field and click it to insert one.
Now that we have our List View, let's add some tea items to it. I'll start typing Text... and use the return key to accept and insert the code completion suggestion from the inline code completion panel.
Alright, now we have our List View with one tea added. Let's add some more.
Wait, it looks like I accidentally added Jasmine Green twice. In order to avoid duplicating our teas, we should store them as an orderedSet. Luckily for us, Apple's swift-collection package offers just that. So, let's add the swift-collection package to our project. To do this, let's open the File Menu and select Add Package.
I'll begin by entering the URL for the swift-collections package, and then press the return key.
After the package is fetched, we can see the package version and other products that can be added to our project. For this app, we'll only select Collections then click Add to Project.
Now we have swift-collections added to our project in the sidebar under Packages. Let's create an OrderedSet of String to store our list of teas.
Wait. It seems like we have an issue. Let's take a look by clicking the issue icon. "Cannot find type ordered set in scope." Oh, I see what the problem is. I forgot to import the Collections module in our project. Let's import that, and the issue should be resolved.
Now that we have resolved that issue, let's update our List View to use the collection we just created. To do this, we'll use a ForEach View.
Alright, there we have it-- our list of teas being displayed from our tea collection. As I'm working on this project, I'm getting more and more ideas on features to add. It would be so cool if our app could listen for whistling tea kettles to let us know when it's time to pour. I'm not going to implement this now, but let's walk through the steps we would take to explain to users why our app needs to use the microphone. To add this, let's go back into our app settings... and click Capabilities. Using the plus button in the top righthand corner, we'll get a list of capabilities we can add to our project. Let's find microphone and click it to add. For the purpose string, we'll write: "Tea Time uses the microphone to listen for whistling tea kettles." I'll click add, and then close app settings.
Alright, we've done a lot today, and I'm excited to share the project and the cool ideas I have with Connor.
I'll share it with Connor by adding it to our shared iCloud folder. But first, let's give it a better filename than My App.
Now, I'll drag it to the shared iCloud Folder.
Now that I'm done, I'm going to hand it over to Connor to finish the app. Thanks Collett. I'm going to pick things up on iPad. Since we're sharing our project via an iCloud Shared Folder, it doesn't show up in the main list of projects. But if I tap on "Locations," I can get access to projects from elsewhere in iCloud, or even from third-party document providers. I'm already in our Shared Folder, so I'll tap on Tea Time to open the project. Any changes I make will automatically be reflected in the shared project. It looks like Collett is such a good engineer that just uploading the project to iCloud added some extra features! She implemented a TabView here so we don't just have a list of teas but also an Assistant. If I tap on the Assistant tab, it's a little bit bare-bones, but it does the job. I can ask for a recommendation, and it'll give me a tea I should drink. Seems today I should have the Jasmine Green. Now I know Collett was working on a fun new way to pick teas to give this a little extra pizzaz. Let's open the sidebar to try to find it.
TeaWheelView seems promising, so let's tap on that to open it. We've got a View which takes a collection of data. Let's add a view preview so we can try TeaWheelView out before it's a part of the main app. I'll scroll to the bottom of the file...
And I'll begin typing "preview provider." I'll accept the code completion suggestion by pressing the Return key, and I'll name it TeaWheelView_Previews.
Page dots have now appeared at the bottom of the preview area, which tells me that Swift Playgrounds recognizes my preview provider. If I tap on the right chevron underneath the app preview… then I can use my view preview instead of the app preview. Right now it just says "Hello, world!" so let's add in some code to create a TeaWheelView. First I'll add an array with a few items in it as a static property so it can be used by my preview.
I'll leave the insertion point between the two square brackets and then I'll drag on the closing bracket to create placeholders for a few items.
Next, I'll replace the placeholders with a few strings that'll serve as our items.
Now that we've got a few items, let's add in the TeaWheelView. I'll select the Hello, world! example and replace it with a TeaWheelView that displays my items.
I'll also add in a little bit of padding.
Great! Now our view preview is showing a wheel, and what a beautiful wheel it is! I can spin it, and it'll pick different items based on where it lands. Let's go back to the assistant tab and add this wheel in. I'll use the sidebar to open the AssistantTab Swift file, and I'm going to delete the Button and replace it with a TeaWheelView instead.
TeaWheelView optionally takes an action closure which is called when the wheel stops spinning.
I'll use it to set last picked tea to the selected tea, and I'll set show pick alert to true so SwiftUI knows to show the alert.
Okay, great! We've got our wheel in here, so now let's try it! I'll swipe to spin it... and it told me to drink Byte's Oolong. I'll swipe it again...
And it's still Byte's Oolong. One more time.
Hmm. Something seems wrong. Even though it's landing on different spots on the wheel, it's always telling me to drink the Byte's Oolong. While that is a good tea, I'd like a little bit of variety. Let's switch back to the wheel view and try to figure out what's up.
It's not obvious from this what's going wrong, since the wheel does spin and land on different spots. Let's add a print statement into our view preview to check if the preview is broken too.
Now when I spin the wheel... A console message pops up at the bottom left of the source editor. Item one... item one…item one. Aha! Each spin gives us item one, which suggests something isn't quite hooked up right! Since it's giving me the first one every time, I'm going to use project-wide find to search for first. I'll tap in the search field at the top of the sidebar on the left hand side of the screen and then type "first" and press Return.
That result seems promising, so I'll tap on it. Ah, it looks like Collett left some debugging code in here that made it return the first item every time instead of the right result. Let's fix that up real quick and then give it another spin.
Item two... item four. Great! It seems to be working now. If we switch back to our app preview by tapping on the left chevron underneath the preview, we can try it out in the real app. I'll spin the wheel, and it's telling me to have the English Breakfast. So now we've got a working assistant. Awesome! Just to confirm the app works well at all sizes, I can run it in its own window by pressing the Run button in the upper left of the screen.
Okay, seems like everything is here. I've got my list of teas, and I've got the assistant here with the wheel and everything. I can go back to the project in Swift Playgrounds by tapping on the little Swift icon in the status bar, and then by selecting the "Show Project" button in the sheet that pops up.
I'm ready to test this app myself and with my friends and family. Swift Playgrounds makes it easy to test because you can submit directly to TestFlight from within Swift Playgrounds! If I bring up the app settings sheet and scroll to the bottom, there's an "Upload to App Store Connect" button. If I tap on that, Swift Playgrounds does all of the hard work of creating an app record and uploading my app to App Store Connect so I can distribute it on TestFlight and eventually the App Store.
Now that my app is uploaded, I can go to App Store Connect and submit it for Beta App Review. After waiting a bit, we can go over to the TestFlight app and install it from there, even on iPhone! I'll tap "Install" to install Tea Time. Now that it's installed, I'll tap "Open" to open it. I'll tap to the test notes, as well as these instructions on how to provide feedback. And there you have it-- our app is running on iPhone. What tea should I have today? Looks like I'm having the Matt P's Tea Party. Today, Collett and I showed you how you can use Swift Playgrounds on your Mac and iPad to build apps. We demonstrated using the library and code completion to insert new code, we shared our project via iCloud Shared Folders, and we used view previews and the console to debug an issue with our code. We even submitted an app to TestFlight, right from iPad! Hopefully you've learned a thing or two along the way, and we can't wait to see what you build with Swift Playgrounds. Thank you for watching, and enjoy the rest of WWDC!
-
-
3:31 - First Tea Item
Text("Jasmine Green")
-
3:39 - List Of Teas
Text("Jasmine Green") Text("English Breakfast") Text("Byte's Oolong") Text("Golden Tippy Assam") Text("Matt P's Tea Party") Text("Darjeeling") Text("Genmaicha") Text("Jasmine Green") Text("Vanilla Rooibos")
-
4:45 - OrderedSet of Teas
let teas: OrderedSet<String> = ["Byte's Oolong", "Golden Tippy Assam", "English Breakfast", "Matt P's Tea Party", "Darjeeling", "Genmaicha", "Jasmine Green", "Vanilla Rooibos"]
-
5:28 - ForEach View
ForEach(teas, id: \.self) { tea in Text(tea) }
-
8:45 - Initial Preview Provider
struct TeaWheelView_Previews: PreviewProvider { static let items: [String] = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"] static var previews: some View { Text("Hello, world!") } }
-
9:22 - Preview Provider with TeaWheelView
struct TeaWheelView_Previews: PreviewProvider { static let items: [String] = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"] static var previews: some View { TeaWheelView(items, id: \.self) .padding() } }
-
10:40 - TeaWheelView in Assistant Tab
TeaWheelView(dataSource.teas, action: { tea in lastPickedTea = tea showPickAlert = true })
-
11:55 - Preview Provider with Print Statement
struct TeaWheelView_Previews: PreviewProvider { static let items: [String] = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"] static var previews: some View { TeaWheelView(items, id: \.self) { print($0) } .padding() } }
-
-
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.