MST

星途 面试题库

面试题:Swift中SwiftUI与Core Data集成 - 数据更新与一致性

在SwiftUI与Core Data集成场景下,当多个视图同时对Core Data中的同一数据进行操作时,如何保证数据的一致性?例如,一个视图更新了待办事项的完成状态,其他视图需要实时反映这一变化。阐述你所知道的实现方法,并举例说明代码实现思路。
26.0万 热度难度
编程语言Swift

知识考点

AI 面试

面试题答案

一键面试

实现方法

  1. 使用@FetchRequestObservableObject
    • @FetchRequest用于从Core Data获取数据,并自动监听数据变化。当Core Data中的数据发生改变时,SwiftUI视图会自动重新渲染。
    • ObservableObject用于定义数据模型,并且通过@Published属性包装器标记需要监听变化的属性。
  2. 使用NSFetchedResultsController(在UIKit和SwiftUI混合场景或更复杂场景下也常用):它可以监控Core Data数据的变化,并提供一种机制来更新UI。在SwiftUI中可以将其与ObservableObject结合使用。
  3. 使用NotificationCenter:Core Data会发布一些通知,例如NSManagedObjectContextDidSave通知,我们可以监听这些通知,在数据保存后手动更新视图。

代码实现思路示例(以@FetchRequestObservableObject为例)

  1. 定义Core Data数据模型: 假设我们有一个简单的待办事项数据模型TodoItem,它有一个标题title和一个完成状态isCompleted
import CoreData

@objc(TodoItem)
public class TodoItem: NSManagedObject {
    @NSManaged public var title: String
    @NSManaged public var isCompleted: Bool
}
  1. 创建视图模型
import SwiftUI
import CoreData

class TodoViewModel: ObservableObject {
    @Published var todoItems: [TodoItem] = []

    let viewContext: NSManagedObjectContext

    init(viewContext: NSManagedObjectContext) {
        self.viewContext = viewContext
        fetchTodoItems()
    }

    func fetchTodoItems() {
        let fetchRequest: NSFetchRequest<TodoItem> = TodoItem.fetchRequest()
        do {
            todoItems = try viewContext.fetch(fetchRequest)
        } catch {
            print("Error fetching todo items: \(error)")
        }
    }

    func updateTodoItem(_ item: TodoItem, isCompleted: Bool) {
        item.isCompleted = isCompleted
        do {
            try viewContext.save()
            fetchTodoItems()
        } catch {
            print("Error saving changes: \(error)")
        }
    }
}
  1. 创建视图
struct TodoListView: View {
    @ObservedObject var viewModel: TodoViewModel

    var body: some View {
        List(viewModel.todoItems) { item in
            HStack {
                Toggle(isOn: Binding(get: { item.isCompleted }, set: { self.viewModel.updateTodoItem(item, isCompleted: $0) })) {
                    Text(item.title)
                }
            }
        }
    }
}
  1. SceneDelegate中设置上下文并展示视图
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }

        let viewContext = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        let viewModel = TodoViewModel(viewContext: viewContext)

        let contentView = TodoListView(viewModel: viewModel)

        self.window = UIWindow(windowScene: windowScene)
        self.window?.rootViewController = UIHostingController(rootView: contentView)
        self.window?.makeKeyAndVisible()
    }
}

在上述代码中,TodoViewModel通过@Published属性todoItems来监听待办事项数据的变化。当一个视图更新了待办事项的isCompleted状态并保存到Core Data后,fetchTodoItems方法会重新获取数据,触发@Published属性的变化,从而使SwiftUI视图自动更新,保证了多个视图间数据的一致性。