Swiftui 在另一个视图中使用一个视图的计算值

Swiftui Using a calculated value from 1 view in another view

我对 Swiftui 比较陌生,目前正在开发我的第二个应用程序,它比第一个应用程序复杂得多。 我在几天来一直试图解决的一个特定要求上遇到了瓶颈,现在我在使用大量关于 State/Binding/ObservableObject 等

的视频和文章后绕圈子

我正在开发一个高尔夫计分应用程序,用户将依次通过每个洞并输入他们的分数,将进行各种计算并显示在视图中。其中之一是总得分。当他们移动到第二个洞时,将遵循相同的过程,但有一个额外的计算需要将洞 1 和洞 2 的总分加在一起。我尝试过的各种方法都以 0 或我想记住更多的错误消息,当然太多了,无法包含在此处!!

如果有任何帮助,我将不胜感激,我已将我的代码包含在下面(为此目的 post 进行了删减),其中包括一些注释来解释我需要做什么,我希望这些注释是清楚的。如果任何人都可以将我的代码改编成可以正常工作的东西,那么我可以看看它们是如何组合在一起的。

提前致谢

开始查看

// 这个画面只是用来开始一个回合的。它将带您到 1 号洞,从那里,1 号洞的导航链接将带您到 2 号洞,依此类推。

import SwiftUI

struct ContentView: View {
    
var body: some View {
        NavigationView {
                NavigationLink(destination: Hole1View()) {
                    Text("Start Round")
                        .frame(width: 300, height: 30)
                        .font(.system(size: 18, weight: .bold, design: .rounded))
                        .lineLimit(1)
                        .multilineTextAlignment(.center)
                        .padding(18)
                        .background(Color.yellow)
                        .foregroundColor(Color.blue)
                        .cornerRadius(10)
                        .border(Color.blue, width: 10)
                        .cornerRadius(1)
                    }
                }
            }
        }
struct ContentView_Previews : PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

洞 1 视图

// 在此视图中,您将输入各种信息,并且视图中将包含各种计算。其中一个计算是计算一个值(Hole1totalpoints),这将在下一个视图的计算中需要。

import SwiftUI

struct Hole1View: View {
    @State private var hole1gross = 0
    
    
    var hole1totalpoints: Int {
        let hole1points = hole1gross * 3
        return hole1points
    }
    
    
    var body: some View {
        
        // On this view you will enter various information and there will be various calculations to include in the View. One of the calculations is to calculate a value (Hole1totalpoints) which will be required in calculations in the next view.
        
        
        
        
        
        Stepper("\(hole1gross)", value: $hole1gross, in: 0...15)
            .frame(width: 300, height: 35, alignment: .leading)
            .font(.system(size: 16, weight: .bold, design: .rounded))
            .minimumScaleFactor(0.6)
            .multilineTextAlignment(.leading)
            .lineLimit(2)
        
        Text("Calculated Value \(hole1totalpoints)")
        
        
        
        NavigationLink(destination: Hole2View()) {
            Text("Go to hole 2")
        }
            
         
        }
    }

struct Hole1View_Previews: PreviewProvider {
    static var previews: some View {
        Hole1View()
    }
}

洞 2 视图

// 在此视图中,您将输入各种信息,并且视图中将包含各种计算。其中一项计算是计算一个值(Hole2totalpoints)。其中一个计算需要包含前一个视图 (Hole1View) 的值 hole1totalpoints,以计算可在 View 中使用的 2 个视图 (hole1totalpoints+hole2totalpoints) 的总点数。

import SwiftUI

struct Hole2View: View {
    @State private var hole2gross = 0
    @State private var hole2totpoints = 0
    
    var hole2totalpoints: Int {
        let hole1points = hole2gross * 2
        return hole1points
    }
    
    
    
    var body: some View {
        
       
        
        
        Stepper("\(hole2gross)", value: $hole2gross, in: 0...15)
            .frame(width: 300, height: 35, alignment: .leading)
            .font(.system(size: 16, weight: .bold, design: .rounded))
            .minimumScaleFactor(0.6)
            .multilineTextAlignment(.leading)
            .lineLimit(2)
        
        Text("Calculated Value \(hole2totalpoints)")
        
        
    }
}

struct Hole2View_Previews: PreviewProvider {
    static var previews: some View {
        Hole2View()
    }
}

您可以使用@ObservableObject 或@EnvironmentObject 来完成此操作。我选择通过 props 传递 @ObservableObject 来显示它,但你可以轻松地将其更改为仅在顶部注入我的 ScoreManager 对象,同时使用 environmentObject


struct ContentView: View {
    @ObservedObject var scoreManager = ScoreManager()
    
    var body: some View {
        NavigationView {
            NavigationLink(destination: Hole1View(scoreManager: scoreManager)) {
                Text("Start Round")
                    .frame(width: 300, height: 30)
                    .font(.system(size: 18, weight: .bold, design: .rounded))
                    .lineLimit(1)
                    .multilineTextAlignment(.center)
                    .padding(18)
                    .background(Color.yellow)
                    .foregroundColor(Color.blue)
                    .cornerRadius(10)
                    .border(Color.blue, width: 10)
                    .cornerRadius(1)
            }
        }
    }
}

class ScoreManager : ObservableObject {
    @Published var hole1gross = 0
    
    var hole1totalpoints: Int {
        let hole1points = hole1gross * 3
        return hole1points
    }
    
    @Published var hole2gross = 0
    @Published var hole2totpoints = 0
    
    var hole2totalpoints: Int {
        //do any calculations here relating to hole 1 points, since you have access to both
        let hole1points = hole2gross * 2
        return hole1points
    }
    
    var hole1AndHole2Points : Int {
        hole1totalpoints + hole2totalpoints
    }
}

struct Hole1View: View {
    @ObservedObject var scoreManager : ScoreManager
    
    var body: some View {
        Stepper("\(scoreManager.hole1gross)", value: $scoreManager.hole1gross, in: 0...15)
            .frame(width: 300, height: 35, alignment: .leading)
            .font(.system(size: 16, weight: .bold, design: .rounded))
            .minimumScaleFactor(0.6)
            .multilineTextAlignment(.leading)
            .lineLimit(2)
        
        Text("Calculated Value \(scoreManager.hole1totalpoints)")
        
        NavigationLink(destination: Hole2View(scoreManager: scoreManager)) {
            Text("Go to hole 2")
        }
    }
}

struct Hole2View: View {
    @ObservedObject var scoreManager : ScoreManager
    
    var body: some View {
        
        Stepper("\(scoreManager.hole2gross)", value: $scoreManager.hole2gross, in: 0...15)
            .frame(width: 300, height: 35, alignment: .leading)
            .font(.system(size: 16, weight: .bold, design: .rounded))
            .minimumScaleFactor(0.6)
            .multilineTextAlignment(.leading)
            .lineLimit(2)
        
        Text("Calculated Value \(scoreManager.hole2totalpoints)")
        
        Text("Both holes: \(scoreManager.hole1AndHole2Points)")
    }
}

ContentView 现在创建一个 ScoreManager。它通过 NavigationLinks 中的其他视图向下传递。其他视图以该对象的相同版本结束(它不会在新视图中重新创建——它们都具有对原始对象的相同引用)。然后,在原始版本中,您可以访问所有想要的乐谱。我创建了 hole1AndHole2Points,我认为它可以满足您的描述。您可以在第 2 洞的最后 Text 项中看到反映的值。

如果你想走环境对象路线,代码会非常相似。有关该系统的更多阅读:https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-environmentobject-to-share-data-between-views