SwiftUI MVVM如何在函数后显示警报
我正在使用MVVM架构创建一个用户登录页面,如果文本字段为空或用户名/密码错误,我希望显示一个警报页面。因此,在登录单击和API调用之后,如果登录失败,我想显示一个警报,但是我尝试更改状态,但仍然没有显示警报 登录视图SwiftUI MVVM如何在函数后显示警报,swift,xcode,mvvm,swiftui,Swift,Xcode,Mvvm,Swiftui,我正在使用MVVM架构创建一个用户登录页面,如果文本字段为空或用户名/密码错误,我希望显示一个警报页面。因此,在登录单击和API调用之后,如果登录失败,我想显示一个警报,但是我尝试更改状态,但仍然没有显示警报 登录视图 struct LoginView: View { @ObservedObject var user: User @ObservedObject var viewModel = LoginViewModel() @State var inputUser: S
struct LoginView: View {
@ObservedObject var user: User
@ObservedObject var viewModel = LoginViewModel()
@State var inputUser: String = ""
@State var inputPass: String = ""
@State private var showingAlert = true
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Group {
Text("Login")
CustomTextField(placeHolder: "Username", value: $viewModel.user)
CustomTextField(placeHolder: "Password", value: $viewModel.pass)
Button(action: {
self.viewModel.login { (isSuccess) in
if isSuccess {
self.user.tokenIsActive = true
} else {
// if login failed, show alert, but alert not showing
self.showingAlert = true
}
}
}) {
Text("Sign In")
}.buttonStyle(PrimaryButtonStyle())
.alert(isPresented: $showingAlert) {
Alert(title: Text("Error"), message: Text("Invalid username / password"), dismissButton: .default(Text("Got it!")))
}
}
}
}
}
}
LoginView模型
class LoginViewModel: ObservableObject, LoginService {
var apiSession: APIService
@Published var user = ""
@Published var pass = ""
@Published var accessToken: String?
@Published var refreshToken: String?
@Published var showingAlert = true
var cancellables = Set<AnyCancellable>()
init(apiSession: APIService = APISession()) {
self.apiSession = apiSession
}
func login(_ completion: @escaping ((Bool)->Void)) {
let cancellable = self.loginUser(user: user, pass: pass)
.sink(receiveCompletion: { result in
switch result {
case .failure(let error):
print("Handle error: \(error)")
case .finished:
break
}
}) { (result) in
completion(true)
self.accessToken = result.accessToken
self.refreshToken = result.refreshToken
UserDefaults.standard.set(self.accessToken, forKey: "AccessToken")
UserDefaults.standard.set(self.refreshToken, forKey: "RefreshToken")
}
cancellables.insert(cancellable)
}
}
classloginviewmodel:observeObject,LoginService{
apiSession:APIService
@已发布的var user=“”
@已发布的var pass=“”
@已发布的var accessToken:字符串?
@已发布的var刷新令牌:字符串?
@已发布变量showingAlert=true
var cancelables=Set()
初始化(apiSession:APIService=apiSession()){
self.apiSession=apiSession
}
func登录(uu完成:@escaping((Bool)->Void)){
让Cancelable=self.loginUser(用户:用户,通过:通过)
.sink(receiveCompletion:{结果为
切换结果{
案例。失败(let错误):
打印(“句柄错误:\(错误)”)
案例。完成:
打破
}
})(结果)
完成(真)
self.accessToken=result.accessToken
self.refreshtToken=result.refreshtToken
UserDefaults.standard.set(self.accessToken,forKey:“accessToken”)
UserDefaults.standard.set(self.refreshtToken,forKey:“refreshtToken”)
}
可取消。插入(可取消)
}
}
如何显示警报?提前感谢大家。如果我正确理解了您的流程,问题在于登录逻辑
let cancellable = self.loginUser(user: user, pass: pass)
.receive(on: DispatchQueue.main) // << add also this one !!
.sink(receiveCompletion: { result in
switch result {
case .failure(let error):
print("Handle error: \(error)")
completion(false) // << here !!
case .finished:
break
}
}) { (result) in
self.accessToken = result.accessToken
self.refreshToken = result.refreshToken
UserDefaults.standard.set(self.accessToken, forKey: "AccessToken")
UserDefaults.standard.set(self.refreshToken, forKey: "RefreshToken")
completion(true) // obviously should be called here !!
// and if result is provided always, ie. for
// failed login as well, then conditional
// completion should be called.
}
let cancelable=self.logiuser(用户:用户,通过:通过)
.receive(on:DispatchQueue.main)//非常感谢您的回答。我对Swift很陌生,你能举例说明“有条件完成”是如何实施的吗?