SwiftUI MVVM简单概念混淆-需要建议

  • 本文关键字:MVVM 简单 SwiftUI mvvm swiftui
  • 更新时间 :
  • 英文 :


我在SwiftUI中遇到了一些基本的MVVM概念。我很感激这可能是一个简单的问题,但我的大脑很疲惫,我想不通。

这是我的模型/视图/视图模型等

import Foundation
struct Challenges {
var all: [Challenge]

init() {
all = []
}
}
struct Challenge: Identifiable, Codable, Hashable {
private(set) var id = UUID()

private(set) var name: String
private(set) var description: String
private(set) var gpxFile: String
private(set) var travelledDistanceMetres: Double = 0

init(name: String, description: String, gpxFile: String) {
self.name = name
self.description = description
self.gpxFile = gpxFile
}
mutating func addDistance(_ distance: Double) {
travelledDistanceMetres += distance
}
}
import SwiftUI
@main
struct ActivityChallengesApp: App {
var body: some Scene {
WindowGroup {
ChallengesView()
.environmentObject(ChallengesViewModel())
}
}
}
import SwiftUI
class ChallengesViewModel: ObservableObject {
@Published var challenges: Challenges

init() {
challenges = Challenges()
challenges.all = DefaultChallenges.ALL
}

func addDistance(_ distance: Double, to challenge: Challenge) {
challenges.all[challenge].addDistance(distance)
}
}
import SwiftUI
struct ChallengesView: View {
@EnvironmentObject var challengesViewModel: ChallengesViewModel

var body: some View {
NavigationView {
List {
ForEach(challengesViewModel.challenges.all) { challenge in
NavigationLink {
ChallengeView(challenge)
.environmentObject(challengesViewModel)
} label: {
VStack(alignment: .leading) {
Text(challenge.name)
Text("(challenge.travelledDistanceMetres)")
}
}
}
}
.navigationTitle("Challenges")
}
}
}
import SwiftUI
struct ChallengeView: View {
var challenge: Challenge

@EnvironmentObject var challengesViewModel: ChallengesViewModel

init(_ challenge: Challenge) {
self.challenge = challenge
}

var body: some View {
VStack(alignment: .leading) {
Text(challenge.name)
Text("(challenge.travelledDistanceMetres)")
}
.onTapGesture {
handleTap()
}
}

func handleTap() {
challengesViewModel.addDistance(40, to: challenge)
}
}

我理解这些概念,但我对ViewModel应该是什么感到困惑。

我觉得这太过分了,即将模型对象发送到视图,并将视图模型作为环境对象。通过此设置,我从视图中调用视图模型中的addDistance()函数来更改模型。

ChallengeView(challenge)
.environmentObject(challengesViewModel)

是为集合设置一个视图模型更好,还是为每个模型对象设置一个查看模型更好?

这是我能想到的最简单的版本
我真的不明白挑战的必要性。好吗?所以我把它拿了出来。

我有

  • 单个challenge的结构
  • 发布challenges数组的可观察类
  • @StateObject实例化一次,然后像您所做的那样向下传递

btw:结构不需要显式初始化程序

这就是:

@main
struct ActivityChallengesApp: App {

// here you create your model once
@StateObject var challenges = ChallengesModel()

var body: some Scene {
WindowGroup {
ChallengesView()
.environmentObject(challenges)
}
}
}
struct Challenge: Identifiable, Codable, Hashable {
var id = UUID()
var name: String
var description: String
var gpxFile: String
var travelledDistanceMetres: Double = 0

mutating func addDistance(_ distance: Double) {
travelledDistanceMetres += distance
}
}

class ChallengesModel: ObservableObject {

@Published var challenges: [Challenge]

init() {
// Test data
challenges = [
Challenge(name: "Challenge One", description: "?", gpxFile: ""),
Challenge(name: "Challenge Two", description: "?", gpxFile: ""),
Challenge(name: "Last Challenge", description: "?", gpxFile: "")
]
}

func addDistance(_ distance: Double, to challenge: Challenge) {
// find the challenge and update it
if let i = challenges.firstIndex(where: {$0.id == challenge.id}) {
challenges[i].addDistance(distance)
}
}
}
struct ChallengesView: View {

@EnvironmentObject var challengesModel: ChallengesModel

var body: some View {
NavigationView {
List {
ForEach(challengesModel.challenges) { challenge in
NavigationLink {
ChallengeView(challenge: challenge)
.environmentObject(challengesModel)
} label: {
VStack(alignment: .leading) {
Text(challenge.name)
Text("(challenge.travelledDistanceMetres)")
}
}
}
}
.navigationTitle("Challenges")
}
}
}

struct ChallengeView: View {

var challenge: Challenge

@EnvironmentObject var challengesModel: ChallengesModel

var body: some View {
VStack(alignment: .leading) {
Text(challenge.name)
Text("(challenge.travelledDistanceMetres)")
}
.onTapGesture {
handleTap()
}
}

func handleTap() {
challengesModel.addDistance(40, to: challenge)
}
}

最新更新