Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
An iOS Developer's Guide to SwiftUI

You're reading from   An iOS Developer's Guide to SwiftUI Design and build beautiful apps quickly and easily with minimum code

Arrow left icon
Product type Paperback
Published in May 2024
Publisher Packt
ISBN-13 9781801813624
Length 446 pages
Edition 1st Edition
Languages
Tools
Concepts
Arrow right icon
Author (1):
Arrow left icon
Michele Fadda Michele Fadda
Author Profile Icon Michele Fadda
Michele Fadda
Arrow right icon
View More author details
Toc

Table of Contents (25) Chapters Close

Preface 1. Part 1: Simple Views FREE CHAPTER
2. Chapter 1: Exploring the Environment – Xcode, Playgrounds, and SwiftUI 3. Chapter 2: Adding Basic UI Elements and Designing Layouts 4. Chapter 3: Adding Interactivity to a SwiftUI View 5. Part 2: Scrollable Views
6. Chapter 4: Iterating Views, Scroll Views, FocusState, Lists, and Scroll View Reader 7. Chapter 5: The Art of Displaying Grids 8. Part 3: SwiftUI Navigation
9. Chapter 6: Tab Bars and Modal View Presentation 10. Chapter 7: All About Navigation 11. Part 4: Graphics and Animation
12. Chapter 8: Creating Custom Graphics 13. Chapter 9: An Introduction to Animations in SwiftUI 14. Part 5: App Architecture
15. Chapter 10: App Architecture and SwiftUI Part I: Practical Tools 16. Chapter 11: App Architecture and SwiftUI Part II – the Theory 17. Part 6: Beyond Basics
18. Chapter 12: Persistence with Core Data 19. Chapter 13: Modern Structured Concurrency 20. Chapter 14: An Introduction to SwiftData 21. Chapter 15: Consuming REST Services in SwiftUI 22. Chapter 16: Exploring the Apple Vision Pro 23. Index 24. Other Books You May Enjoy

Exploring changes in the binding mechanisms

  1. With iOS 17, iPadOS 17, macOS 14, tvOS 17, watchOS 10, and visionOS 1.0, SwiftUI bindings have been simplified. To support these changes, you should perform the following tips on any existing code you want to modernize:
    • Rather than using ObservableObject and StateObject, it is now possible to use the Observation pattern (https://developer.apple.com/documentation/observation/). If you already have code that was written for previous versions of the operating systems, you should replace classes inheriting from ObservableObject and StateObject with classes marked with the @Observable macro.

      You should perform this change incrementally; it is not wise to change all your code base in one go. Notice that the @Observable macro can only be applied to classes, not value types such as enums and structs.

      The properties of an @Observable class, if they are visible, are all observable. They don’t need any more to be marked as @Published; the accessibility of the @Observable class will instead determine which of the properties are observable.

    • If you don’t want a specific property to be tracked, you can use the @ObservationIgnored macro to mark that property to be ignored.
    • In SwiftUI, when a bound variable changes, the views that depend on that will get re-rendered on the screen. Due to performance improvements, now the view depending on that value will get re-evaluated only if the affected view actually needs to be redrawn and is affected by this change; if the bound variable change does not affect the view, the redraw of that view won’t get triggered.

Thankfully, these changes in binding mechanisms lead to a reduction of complexity in programming. Now, rather than having to deal with six different choices, to be used in different situations, we have just three: @State, @Bindable, and @Environment.

Let’s look at these in greater detail:

  • @State is unchanged and is still used to bind a variable to the view that contains it. As a best practice, @State variables should be declared private, to make it apparent that they are used to bind the private state, that is, local, belonging to a view, and not exposed outside it.

Additional reading

@State is explained in full in the developer documentation: https://developer.apple.com/documentation/swiftui/state/.

  • @Bindable is instead used to mark those properties of an @Observable class that you want to bind bi-directionally, that is, they are mutable. As before, you will need to mark each name of these properties with a dollar sign ($) prefix when you reference them. You can use @Bindable on the properties of an @Observable object.
  • The main difference between @Bindable and the old @Binding is that while @Binding can only refer to an external variable to the view, @Bindable can reference any property in an @Observable, including any bindings to a SwiftData data model, global variables, properties that exist outside of SwiftUI types, or even local variables.

Additional reading

@Bindable is explained in full in the developer documentation: https://developer.apple.com/documentation/swiftui/bindable#.

  • @Environment now works both for values that need to be bound globally, whether these are defined by the user, which previously required EnvironmentObject, and if they are provided by the system (the old Environment).

Additional reading

You will find a complete explanation of @Environment here: https://developer.apple.com/documentation/swiftui/environment.

StateObject was used before iOS 17 to preserve the state of an observable object when a view gets re-rendered. Achieving this with @Observable requires ensuring that the same instance of the @Observable class is used whenever the view is re-rendered.

The following code example shows the use of @Bindable:

import SwiftUI
@Observable
class Illumination {
      var isOn: Bool = false
}
struct MyView: View {
      @Bindable var lightBackground: Illumination
      var body: some View {
            VStack{
                  Spacer()
                  Toggle(isOn: $lightBackground.isOn) {
                        Text("Lights")
                  }.fixedSize()
            }
      }
}
struct ContentView: View {
      @State private var light = Illumination()
      var body: some View {
            VStack {
                  MyView(lightBackground: light)
                  if light.isOn {
                        Text("On")
                  }
                  else {
                        Text("off")
                              .colorInvert()
                  }
                  Divider()
                  Text("Example of a bindable var")
                        .foregroundStyle(light.isOn ? .primary : Color.white)
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(light.isOn ? Color.white : Color.blue)
      }
}
#Preview {
      ContentView()
}

You can declare a variable inside the view as @Bindable. A variable, to be @Bindable, needs to conform to Sendable and Identifiable. The result is shown in the following screenshot:

Figure 14.1 – An example of @Bindable

Figure 14.1 – An example of @Bindable

In the next section, I will explain how a data model is created in SwiftData.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image