MST
星途 面试题库

面试题:SwiftUI中如何使用`ObservableObject`和`@Published`进行复杂状态管理

创建一个包含多个子视图的SwiftUI应用,这些子视图需要共享和响应一个复杂的数据模型,例如一个包含用户信息(姓名、年龄、地址等)的结构体数组。使用`ObservableObject`和`@Published`来管理这个状态,确保在数据更新时所有相关视图能正确刷新,并说明在这个过程中`@ObservedObject`和`@EnvironmentObject`的适用场景及区别。
11.7万 热度难度
编程语言Swift

知识考点

AI 面试

面试题答案

一键面试

1. 创建数据模型

首先,定义一个包含用户信息的结构体,并创建一个包含该结构体数组的数据模型,使用 ObservableObject@Published 来管理状态。

import SwiftUI

// 用户信息结构体
struct User {
    var name: String
    var age: Int
    var address: String
}

// 数据模型,继承 ObservableObject
class UserData: ObservableObject {
    @Published var users: [User] = [
        User(name: "Alice", age: 25, address: "123 Wonderland"),
        User(name: "Bob", age: 30, address: "456 Elm St")
    ]
}

2. 创建子视图

创建几个子视图来展示和操作这些用户数据。

// 单个用户展示视图
struct UserView: View {
    let user: User
    var body: some View {
        VStack {
            Text("Name: \(user.name)")
            Text("Age: \(user.age)")
            Text("Address: \(user.address)")
        }
    }
}

// 用户列表视图
struct UserListView: View {
    @ObservedObject var userData: UserData
    var body: some View {
        List(userData.users) { user in
            UserView(user: user)
        }
    }
}

3. 主视图和应用设置

UserData 作为环境对象传递,并展示 UserListView

@main
struct SharedDataApp: App {
    @StateObject var userData = UserData()
    var body: some Scene {
        WindowGroup {
            UserListView(userData: userData)
               .environmentObject(userData)
        }
    }
}

@ObservedObject@EnvironmentObject 的适用场景及区别

@ObservedObject

  • 适用场景:当一个视图需要直接观察某个对象的变化时使用。比如,一个视图专门用于展示和操作某个特定的数据模型实例,这个实例的变化只影响该视图及其子视图。例如,一个购物车视图,它观察购物车数据模型的变化,购物车数据的添加、删除商品等操作只影响购物车视图本身及其内部子视图。
  • 特点:视图持有对被观察对象的强引用。这意味着只要视图存在,被观察对象就不会被释放。而且,被观察对象通常是在视图内部创建或者通过初始化参数传入。

@EnvironmentObject

  • 适用场景:当多个视图在视图层级结构中不同位置需要共享同一个数据模型时使用。比如,一个应用的用户设置,在不同的视图(如设置页面、主内容页面等)都可能需要读取和修改用户设置,就可以将用户设置数据模型作为环境对象传递,这样各个视图都能访问和响应其变化。
  • 特点:视图从环境中获取对象,而不是直接持有对象。这使得数据模型可以在整个视图层级中共享,而不需要在每个视图之间通过参数传递。并且,环境对象通常在视图层级的较高位置设置,通过 environmentObject(_:) 方法向下传递。同时,视图对环境对象的引用是弱引用,不会阻止环境对象被释放。