DEV Community

Swee Sen
Swee Sen

Posted on

[2023] SwiftUI @Observable macro: Basic MVVM setup

With the new @Observable macro, setting up MVVM in SwiftUI has become much simpler. We shall explain the setup by trying to build the following page:

Image description

1. Setup ViewModel

struct User {
    let name: String
    let profileImgUrl: String
}

struct ChatMessage {
    var message: String
}

struct HomePageChat: Identifiable {
    let id = UUID()
    let sender: User
    var latestMessage: ChatMessage
}

@Observable class HomePageViewModel {

    var chats: [HomePageChat] = []

    init() {
        setupDummyData()
    }

    private func setupDummyData() {
        let userA = User(name: "Tim Cook", profileImgUrl: "https://www.apple.com/leadership/images/bio/tim-cook_image.png.og.png?1685138662136")
        let messageA = ChatMessage(message: "Hello! Tim Cook here, how are you doing?")
        let chatA = HomePageChat(sender: userA, latestMessage: messageA)

        let userB = User(name: "Craig Federighi", profileImgUrl: "https://www.apple.com/leadership/images/bio/craig_federighi_image.png.og.png?1685171686562")
        let messageB = ChatMessage(message: "I am Craig Federighi, who are you?")
        let chatB = HomePageChat(sender: userB, latestMessage: messageB)


        self.chats = [chatA, chatB]
    }
}
Enter fullscreen mode Exit fullscreen mode

Note that all we need to do is to mark our HomePageViewModel with @Observable macro to make our viewModel observable by SwiftUI views.

2. Setup Views

struct HomePageView: View {

    @Environment(HomePageViewModel.self) private var viewModel

    var body: some View {
        NavigationView {
            VStack {
                List(viewModel.chats) { chat in
                    HomePageCellView(chat: chat)
                }
                .listStyle(.sidebar)
            }
            .navigationTitle("Chats")
            .navigationBarTitleDisplayMode(.large)
        }
    }
}

#Preview {
    HomePageView()
        .environment(HomePageViewModel())
}
Enter fullscreen mode Exit fullscreen mode
struct HomePageCellView: View {

    let chat: HomePageChat

    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                AsyncImage(url: URL(string: chat.sender.profileImgUrl)) { image in
                    image
                        .resizable()
                        .scaledToFill()
                } placeholder: {
                    ProgressView()
                }
                .frame(width: 50, height: 50)
                .clipShape(Circle())
                .clipShape(Circle())
            }
            VStack(alignment: .leading) {
                Text(chat.sender.name)
                    .bold()
                    .padding(.bottom, 1)
                Text(chat.latestMessage.message)
                    .foregroundStyle(.gray)
                    .font(.system(size: 12))
                    .fixedSize(horizontal: false, vertical: true)
            }
            .padding(.leading, 6)

            Spacer()
            VStack {
                Text("Yesterday")
                    .foregroundStyle(.gray)
                    .font(.system(size: 12))
                Spacer()

            }
        }
        .padding(.leading, 0)
        .padding(.vertical, 6)
        .frame(height: 60)
    }
}
Enter fullscreen mode Exit fullscreen mode

Image of Datadog

How to Diagram Your Cloud Architecture

Cloud architecture diagrams provide critical visibility into the resources in your environment and how they’re connected. In our latest eBook, AWS Solution Architects Jason Mimick and James Wenzel walk through best practices on how to build effective and professional diagrams.

Download the Free eBook

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay