我有一个登录屏幕,然后是一个概述屏幕。当用户成功登录后,登录响应将发回一个项目列表,我想在后续的概览屏幕上显示该项目列表。
我可以看到响应已成功映射,但是概述视图没有收到@ObservedObject的任何更新。我可能会遗漏一些明显的东西,但是我浏览了很多文章,但没有设法使任何东西起作用。任何帮助表示赞赏!
登录视图
import SwiftUI
struct LogonView: View {
@State private var username: String = ""
@State private var password: String = ""
@State private var inputError: Bool = false
@State private var errorMessage: String = ""
@State private var loading: Bool? = false
@State private var helpShown: Bool = false
@State private var successful: Bool = false
//MARK:- UIView
var body: some View {
NavigationView {
VStack {
VStack {
TextField("Username", text: $username)
.padding(.horizontal)
.disabled(loading! ? true : false)
Rectangle()
.frame(height: 2.0)
.padding(.horizontal)
.foregroundColor(!inputError ? Color("SharesaveLightGrey") : Color("SharesaveError"))
.animation(.easeInOut)
}.padding(.top, 80)
VStack {
SecureField("Password", text: $password)
.padding(.horizontal)
.disabled(loading! ? true : false)
Rectangle()
.frame(height: 2.0)
.padding(.horizontal)
.foregroundColor(!inputError ? Color("SharesaveLightGrey") : Color("SharesaveError"))
.animation(.easeInOut)
}.padding(.top, 40)
if (inputError) {
HStack {
Text(errorMessage)
.padding(.top)
.padding(.horizontal)
.foregroundColor(Color("SharesaveError"))
.animation(.easeInOut)
.lineLimit(nil)
.font(.footnote)
Spacer()
}
}
SharesaveButton(action: {self.submit(user: self.username, pass: self.password)},
label: "Log on",
loading: $loading,
style: .primary)
.padding(.top, 40)
.animation(.interactiveSpring())
NavigationLink(destination: OverviewView(), isActive: $successful) {
Text("")
}
Spacer()
}
.navigationBarTitle("Hello.")
.navigationBarItems(
trailing: Button(action: { self.helpShown = true }) {
Text("Need help?").foregroundColor(.gray)
})
.sheet(isPresented: $helpShown) {
SafariView( url: URL(string: "http://google.com")! )
}
}
}
//MARK:- Functions
private func submit(user: String, pass: String) {
loading = true
inputError = false
let resultsVM = ResultsViewModel()
resultsVM.getGrants(user: user, pass: pass,
successful: { response in
self.loading = false
if ((response) != nil) { self.successful = true }
},
error: { error in
self.inputError = true
self.loading = false
self.successful = false
switch error {
case 401:
self.errorMessage = "Your credentials were incorrect"
default:
self.errorMessage = "Something went wrong, please try again"
}
},
failure: { fail in
self.inputError = true
self.loading = false
self.successful = false
self.errorMessage = "Check your internet connection"
})
}
}
结果视图模型
import Foundation
import Moya
import Combine
import SwiftUI
class ResultsViewModel: ObservableObject {
@Published var results: Results = Results()
func getGrants(
user: String,
pass: String,
successful successCallback: @escaping (Results?) -> Void,
error errorCallback: @escaping (Int) -> Void,
failure failureCallback: @escaping (MoyaError?) -> Void
)
{
let provider = MoyaProvider<sharesaveAPI>()
provider.request(.getSharesave(username: user, password: pass)) { response in
switch response.result {
case .success(let value):
do {
let data = try JSONDecoder().decode(Results.self, from: value.data)
self.results = data
successCallback(data)
} catch {
let errorCode = value.statusCode
errorCallback(errorCode)
}
case .failure(let error):
failureCallback(error)
}
}
}
}
概述视图
import SwiftUI
import Combine
struct OverviewView: View {
@ObservedObject var viewModel: ResultsViewModel = ResultsViewModel()
var body: some View {
let text = "\(self.viewModel.results.market?.sharePrice ?? 0.00)"
return List {
Text(text)
}
}
}
答案 0 :(得分:1)
您向ResultsViewModel
的一个实例提交了请求
private func submit(user: String, pass: String) {
loading = true
inputError = false
let resultsVM = ResultsViewModel() // << here
通过尝试从ResultsViewModel
的另一个实例读取数据
struct OverviewView: View {
@ObservedObject var viewModel: ResultsViewModel = ResultsViewModel() // << here
,但它必须是一个实例,因此请进行以下修改
1)在OverviewView
struct OverviewView: View {
@ObservedObject var viewModel: ResultsViewModel // expects injection
2)在LogonView
struct LogonView: View {
@ObservedObject var resultsViewModel = ResultsViewModel() // created once
并为OverviewView
注入相同的实例
NavigationLink(destination: OverviewView(viewModel: self.resultsViewModel), isActive: $successful) {
Text("")
}
并提交
private func submit(user: String, pass: String) {
loading = true
inputError = false
let resultsVM = self.resultsViewModel // use created
答案 1 :(得分:0)
请尝试更改NavigationLink
的初始化,如下NavigationLink(destination: OverviewView(viewModel: self.resultsVM),
isActive: $successful) {
Text("")
}
results
OR
通过OverviewView
中的NavigationLink(destination: OverviewView(results: self.resultsVM.results),
isActive: $successful) {
Text("")
}
.....
struct OverviewView: View {
let results: Results
var body: some View {
let text = "\(self.results.market?.sharePrice ?? 0.00)"
return List {
Text(text)
}
}
}
作为如下参数
{{1}}