FREE TRIAL: Accelerate your app development career with Hacking with Swift+! >>

Building our basic UI

Paul Hudson    @twostraws   

The first step in our project is to build the basic user interface, which for this app will be:

  1. A NavigationView so we can show our app’s name at the top.
  2. A large gray box saying “Tap to select a picture”, over which we’ll place their imported picture.
  3. An “Intensity” slider that will affect how strongly we apply our Core Image filters, stored as a value from 0.0 to 1.0.
  4. A “Save” button to write out the modified image to the user’s photo library.

Initially the user won’t have selected an image, so we’ll represent that using an @State optional image property.

First add these two properties to ContentView:

@State private var image: Image?
@State private var filterIntensity = 0.5

Now modify the contents of its body property to this:

NavigationView {
    VStack {
        ZStack {

            // display the image
        .onTapGesture {
            // select an image

        HStack {
            Slider(value: self.$filterIntensity)

        HStack {
            Button("Change Filter") {
                // change filter


            Button("Save") {
                // save the picture
    .padding([.horizontal, .bottom])

There are lots of placeholders in there, and we’ll be filling them piece by piece as we work through this project.

For now, I want to focus on this comment: // display the image. This is where we need to show the selected image if we have one, but otherwise we should show a prompt telling the user to tap that area to trigger image selection.

Now, you might think this is a great place to use if let and try replacing that comment with something like this:

if let image = image {
} else {
    Text("Tap to select a picture")

However, if you try building that you’ll see it doesn’t work – you’ll get a fairly obscure error message along the lines of “Closure containing control flow statement cannot be used with function builder ViewBuilder”.

What Swift is trying to say is it has support for only a small amount of logic inside SwiftUI layouts – we can use if someCondition, but we can’t use if let, for, while, switch, and so on.

What’s actually happening here is that Swift is able to convert if someCondition into a special internal view type called ConditionalContent: it stores the condition and the true and false views, and can check it at runtime. However, if let creates a constant, and switch can have any number of cases, so neither can be used.

So, the fix here is to replace if let with a simple condition, then rely on SwiftUI’s support for optional views:

if image != nil {
} else {
    Text("Tap to select a picture")

That code will now compile, and because image is nil you should see the “Tap to select a picture” prompt displayed over our gray rectangle.

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for iOS devs who want to become complete senior developers — from October 18th to 24th. Learn how to apply iOS app architecture patterns through a series of lectures and practical coding sessions.

Learn more

Sponsor Hacking with Swift and reach the world's largest Swift community!

Buy Pro Swift Buy Swift Design Patterns Buy Testing Swift Buy Hacking with iOS Buy Swift Coding Challenges Buy Swift on Sundays Volume One Buy Server-Side Swift (Vapor Edition) Buy Advanced iOS Volume One Buy Advanced iOS Volume Two Buy Advanced iOS Volume Three Buy Hacking with watchOS Buy Hacking with tvOS Buy Hacking with macOS Buy Dive Into SpriteKit Buy Swift in Sixty Seconds Buy Objective-C for Swift Developers Buy Server-Side Swift (Kitura Edition) Buy Beyond Code

Was this page useful? Let us know!

Average rating: 4.8/5

Unknown user

You are not logged in

Log in or create account

Link copied to your pasteboard.