通常只有一个ViewModel来管理所有Coredata实体-Core Data+ mvvm+斯威夫特

发布于 2025-01-25 10:43:04 字数 3228 浏览 1 评论 0原文

只有一个viewModel来管理所有coredata实体是否常见?

例如,在下面的示例中,我有三个核心数据实体,carcarServiceserviceRecord其中car有许多汽车服务,每个carservice有许多servicerecords。一切正常,但是我觉得我的carviewModel文件正在增长和增长,我不确定这是否真的是一个很好的MVVM练习。

如下面的示例,您正在使用carviewModelcore> core data获取数据,并围绕SwiftUI视图传递。同样,一切都很好,但我觉得我缺少一些东西。

使用MVVM + Coredata + Swiftui时,有人可以分享您通常如何构建代码的方式。您是否处理一个viewModel如下所示的所有内容,还是通常为每个实体具有viewModel?如果每个实体都是最佳选择,那么您使用哪种方法传递了SwiftUi视图周围的ViewModels?

coredatamanager

class CoreDataManager{

    static let instance = CoreDataManager()

    lazy var context: NSManagedObjectContext = {
        return container.viewContext
    }()
    
    lazy var container: NSPersistentContainer = {
        return setupContainer()
    }()
    
    func setupContainer()->NSPersistentContainer{
        // code to setup container...
        return container
    }
    
    func save(){
        do{
            try context.save()
        }catch let error{
            print("Error saving Core Data. \(error.localizedDescription)")
        }
    }
}

carviewModel

class CarViewModel: ObservableObject{

    let manager: CoreDataManager
    
    @Published var cars: [Car] = []
    @Published var carServices: [CarService] = []
    @Published var serviceRecords: [ServiceRecord] = []
    
    init(coreDataManager: CoreDataManager = .instance){
        self.manager = coreDataManager
        // getCars() etc.
    }

    // CREATIONS
    func addCar(name:String){}
    func addService(name:String, cost: Double){}
    func createRecord(name:String, cost: Double){}
    
    // DELETES
    func deleteCar(){}
    func deleteCarService(){}
    func deleteServiceRecord(){}
    
    // UPDATES
    func updateCar(){}
    func updateService(){}

    // GETS
    func getCars(){}
    func getServices(){}
    func getRecords(){}
    
    func save(){
        self.manager.save()
    }
}

swiftui视图

CARSVIEW

struct CarsView: View {
    @StateObject var carViewModel = CarViewModel()
    var body: some View {
        NavigationView{
            VStack{
                List {
                    ForEach(carViewModel.cars) { car in
                    }
                }
            }  
        }
    }
}

SERVICEVIEW

struct ServicesView: View {
    @ObservedObject var carViewModel:CarViewModel
    var body: some View {
        NavigationView{
            VStack{
                List {
                    ForEach(carViewModel.carServices) { service in
                    }
                }
            }  
        }
    }
}

RECORDVIEW

struct RecordsView: View {
    @ObservedObject var carViewModel: CarViewModel
    var body: some View {
        NavigationView{
            VStack{
                List {
                    ForEach(carViewModel.serviceRecords) { record in
                    }
                }
            }  
        }
    }
}

Is it common to have only one ViewModel to manage all CoreData entities?

For instance, in the following example, I have three Core Data entities, Car, CarService and ServiceRecord where Car has many carServices and each CarService has many serviceRecords. Everything is working fine but I feel like my CarViewModel file is growing and growing and I'm not sure if this is really a good MVVM practice.

As you can see in the following example I'm using CarViewModel to fetch data from Core Data and passing it around SwiftUI views. Again, everything is working fine but I feel like I'm missing something.

Can someone please share how you usually structure your code when using MVVM + CoreData + SwiftUI. Do you handle everything from one ViewModel as shown below or do you usually have a ViewModel for each entity? If a viewModel per each entity is the best option, what method do you use to pass viewModels around SwiftUI views?

CoreDataManager

class CoreDataManager{

    static let instance = CoreDataManager()

    lazy var context: NSManagedObjectContext = {
        return container.viewContext
    }()
    
    lazy var container: NSPersistentContainer = {
        return setupContainer()
    }()
    
    func setupContainer()->NSPersistentContainer{
        // code to setup container...
        return container
    }
    
    func save(){
        do{
            try context.save()
        }catch let error{
            print("Error saving Core Data. \(error.localizedDescription)")
        }
    }
}

CarViewModel

class CarViewModel: ObservableObject{

    let manager: CoreDataManager
    
    @Published var cars: [Car] = []
    @Published var carServices: [CarService] = []
    @Published var serviceRecords: [ServiceRecord] = []
    
    init(coreDataManager: CoreDataManager = .instance){
        self.manager = coreDataManager
        // getCars() etc.
    }

    // CREATIONS
    func addCar(name:String){}
    func addService(name:String, cost: Double){}
    func createRecord(name:String, cost: Double){}
    
    // DELETES
    func deleteCar(){}
    func deleteCarService(){}
    func deleteServiceRecord(){}
    
    // UPDATES
    func updateCar(){}
    func updateService(){}

    // GETS
    func getCars(){}
    func getServices(){}
    func getRecords(){}
    
    func save(){
        self.manager.save()
    }
}

SwiftUI Views

CarsView

struct CarsView: View {
    @StateObject var carViewModel = CarViewModel()
    var body: some View {
        NavigationView{
            VStack{
                List {
                    ForEach(carViewModel.cars) { car in
                    }
                }
            }  
        }
    }
}

ServicesView

struct ServicesView: View {
    @ObservedObject var carViewModel:CarViewModel
    var body: some View {
        NavigationView{
            VStack{
                List {
                    ForEach(carViewModel.carServices) { service in
                    }
                }
            }  
        }
    }
}

RecordsView

struct RecordsView: View {
    @ObservedObject var carViewModel: CarViewModel
    var body: some View {
        NavigationView{
            VStack{
                List {
                    ForEach(carViewModel.serviceRecords) { record in
                    }
                }
            }  
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

九八野马 2025-02-01 10:43:04

我个人将创建一个服务文件,该文件将所有功能都保存在给定模型中。然后,我只会在我的ViewController所需的ViewModel中揭示功能。

例如:

carservice.swift

class CarService {
    func addCar(name:String) {}
    func addService(name:String, cost: Double) {}
    func createRecord(name:String, cost: Double) {}

    // DELETES
    func deleteCar() {}
    func deleteCarService() {}
    func deleteServiceRecord() {}

    // UPDATES
    func updateCar() {}
    func updateService() {}

    // GETS
    func getCars() {}
    func getServices() {}
    func getRecords() {}
}

carviewmodel.swift

protocol CarViewModelType {

    func addCar(name: String)
    func deleteCar()

}

class CarViewModel: CarViewModelType {

    var carService: CarService

    init(service: CarService) {
        self.carService = service
    }

    func addCar(name: String) {
        self.carService.addCar(name: name)
    }

    func deleteCar() {
        self.carService.deleteCar()
    }
}

carviewcontroller.swift

class CarViewController: UIViewController {

    var viewModel: CarViewModelType!

}

这当然只是一种方法,我相信没有“正确”结构代码的方法。

希望它有帮助

Personally I would create a service file which holds all the functions to a given model. I would then only expose the functions in my viewModel that my viewController needs.

For example:

CarService.swift

class CarService {
    func addCar(name:String) {}
    func addService(name:String, cost: Double) {}
    func createRecord(name:String, cost: Double) {}

    // DELETES
    func deleteCar() {}
    func deleteCarService() {}
    func deleteServiceRecord() {}

    // UPDATES
    func updateCar() {}
    func updateService() {}

    // GETS
    func getCars() {}
    func getServices() {}
    func getRecords() {}
}

CarViewModel.swift

protocol CarViewModelType {

    func addCar(name: String)
    func deleteCar()

}

class CarViewModel: CarViewModelType {

    var carService: CarService

    init(service: CarService) {
        self.carService = service
    }

    func addCar(name: String) {
        self.carService.addCar(name: name)
    }

    func deleteCar() {
        self.carService.deleteCar()
    }
}

CarViewController.swift

class CarViewController: UIViewController {

    var viewModel: CarViewModelType!

}

This is of course just one way to go about it, I believe there is no 'right' way to structure your code.

Hope it helps

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文