read

I am getting started with SwiftUI, and there’s so much to learn, all over again.

Luckily, there are plenty of articles and videos.

Here are some random stuff that I learnt in the first few days as I try to build a new app. The last section will have more links to resources, and kind of cheat sheet.

I might just add more to this post as I learn, or might write new blog post specifically on some tricks even around the most common of things..

Let’s watch how to build Instagram feed

Watch on YouTube part 1 & part 2 where DeLong interactively teach SwiftUI while he replicates Instagram UI.

There are some framework designs that sucks eg. he doesn’t like NavigationView and how nav links work. A hideous design about nav link is that all the destination views will be initialized!

It is so common to not get nav link working. It seems like they are designed to be used only in List, or nav bar. You might need to use the isActive trick if the nav link is in a VStack or etc.

A workaround is to use a hidden nav link.

Present a modal sheet

You need to 1. declare @State isPresented = false, 2. passing it to .sheet(), and 3. button action to set isPresented = true. Sorry it is long and ugly.

2 ways to dismiss (eg. sheet)

Use environment, or pass a binding to the sheet’s isPresented.

How to observe an @State or a control?

You will often have a @State and pass it to a control such as Toggle or TextField. But you can’t just observe the state with didSet. Instead, you need to create a binding like this.

Modifiers

The concept is used throughout, applying modifier after modifier repeatedly. It is using Builder design pattern.

SomeView(...)
    .multilineTextAlignment(.center)  // Modifier 1
    .padding(.all)                    // Modifier 2
    .foregroundColor(.green)          // Modifier 3

It tends to get messy and with many lines. A trick here is to create customer modifiers.

Custom Modifiers

struct CustomModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
          .multilineTextAlignment(.center)  // Modifier 1
          .padding(.all)                    // Modifier 2
          .foregroundColor(.green)          // Modifier 3
    }
}

With that, we can now use it on any View by applying 1 modifier.

SomeView(...)
    .modifier(CustomModifier())

View Extension

Custom modifier is a good way to refactor your code. Another way is by extending View.

extension View {
    public func customModifier(color: Color = .green) -> some View {
        return multilineTextAlignment(.center)  // Modifier 1
        .padding(.all)                    // Modifier 2
        .foregroundColor(color)          // Modifier 3, with `color` passed in
    }
}

You can even do conditional modifier (advanced).

When do you use ViewModifier and when do you use View extension? ViewModifier is more powerful because it can have instance variables and @State, so use it if that’s needed.

Applying modifiers to a group of views

Group is a logical grouping, without any layout specific layout like HStack or Form. When you apply a modifier to a group, it will apply to every view in the group.

View Erasure

Because SwiftUI need to know the view type during compile time, there will be times you need to erase the type eg. to make 2 views they same type. AnyView will do that.

Alert with multiple custom buttons

Alert now supports only 2 buttons, and will possibly make it more flexible. Alternatively, ActionSheet.

Animation & Transition

Add animation() to a binding, or use withAnimation() with state, to animate the view changes.

The default transition is fade. To change, use the transition() modifier.

Resume the live preview

Because Xcode will pause the live preview when there is significant update, it is useful to know the shortcut to resume Option+Cmd+P.

Sample PreviewProvider

Group {
    MyView()
    MyView()
        .environment(\.colorScheme, .dark)
        .environment(\.sizeCategory, .extraExtraExtraLarge)
        .previewDevice("iPhone 8") // Or .fixed
}

The Group displays 2 devices. You can have more, and configure as desired.

Refactor the views

Because of the way it is designed, a complex view would have deeply nested code, with lots of modifier. To refactor relentlessly, a shortcut is to Cmd+Click on a view > Extract subview.

Semantic Colors

Some examples:

.foregroundColor(Color.accentColor)
.foregroundColor(Color.pink)
.foregroundColor(Color(.label)) // Notice this uses an initializer
.foregroundColor(Color(.secondaryLabel))
.background(Color(.systemBackground))

More Resources


Image

@samwize

¯\_(ツ)_/¯

Back to Home