BLACK FRIDAY SALE: Save big on all my Swift books and bundles! >>

Building a basic layout

Paul Hudson    @twostraws   

This app is going to allow user input with a date picker and two steppers, which combined will tell us when they want to wake up, how much sleep they usually like, and how much coffee they drink.

So, please start by adding three properties that let us store the information for those controls:

@State private var wakeUp = Date.now
@State private var sleepAmount = 8.0
@State private var coffeeAmount = 1

Inside our body we’re going to place three sets of components wrapped in a VStack and a NavigationView, so let’s start with the wake up time. Replace the default “Hello World” text view with this:

NavigationView {
    VStack {
        Text("When do you want to wake up?")
            .font(.headline)

        DatePicker("Please enter a time", selection: $wakeUp, displayedComponents: .hourAndMinute)
            .labelsHidden()

        // more to come
    }
}

We’ve asked for .hourAndMinute configuration because we care about the time someone wants to wake up and not the day, and with the labelsHidden() modifier we don’t get a second label for the picker – the one above is more than enough.

Next we’re going to add a stepper to let users choose roughly how much sleep they want. By giving this thing an in range of 4...12 and a step of 0.25 we can be sure they’ll enter sensible values, but we can combine that with the formatted() method so we see numbers like “8” and not “8.000000”.

Add this code in place of the // more to come comment”

Text("Desired amount of sleep")
    .font(.headline)

Stepper("\(sleepAmount.formatted()) hours", value: $sleepAmount, in: 4...12, step: 0.25)

Finally we’ll add one last stepper and label to handle how much coffee they drink. This time we’ll use the range of 1 through 20 (because surely 20 coffees a day is enough for anyone?), but we’ll also display one of two labels inside the stepper to handle pluralization better. If the user has set a coffeeAmount of exactly 1 we’ll show “1 cup”, otherwise we’ll use that amount plus “cups”, all decided using the ternary conditional operator.

Add these inside the VStack, below the previous views:

Text("Daily coffee intake")
    .font(.headline)

Stepper(coffeeAmount == 1 ? "1 cup" : "\(coffeeAmount) cups", value: $coffeeAmount, in: 1...20)

The final thing we need is a button to let users calculate the best time they should go to sleep. We could do that with a simple button at the end of the VStack, but to spice up this project a little I want to try something new: we’re going to add a button directly to the navigation bar.

First we need a method for the button to call, so add an empty calculateBedtime() method like this:

func calculateBedtime() {
}

Now we need to use the toolbar() modifier to add a trailing button to the navigation view. We used this previously along with ToolbarItemGroup to place a button next to the keyboard, but here our needs are much simpler: we just want a single button in the navigation bar, which can be done by adding a button directly to the toolbar.

While we’re here, we might as well also use navigationTitle() to put some text at the top.

So, add these modifiers to the VStack:

.navigationTitle("BetterRest")
.toolbar {
    Button("Calculate", action: calculateBedtime)
}

Tip: Our button will automatically be placed in the top-right corner for left-to-right languages such as English, but will automatically move to the other side for right-to-left languages.

That won’t do anything yet because calculateBedtime() is empty, but at least our UI is good enough for the time being.

Hacking with Swift is sponsored by RevenueCat

SPONSORED In-app subscriptions are a pain to implement, hard to test, and full of edge cases. RevenueCat makes it straightforward and reliable so you can get back to building your app. Oh, and it's free if your app makes less than $10k/mo.

Learn more

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

BUY OUR BOOKS
Buy Pro Swift Buy Pro SwiftUI 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 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 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.