努力与SwiftUI实现全局通知视图
我正在尝试实现一个可以显示在导航栏顶部的视图。让我们将此视图称为努力与SwiftUI实现全局通知视图,swiftui,Swiftui,我正在尝试实现一个可以显示在导航栏顶部的视图。让我们将此视图称为通知视图。从任何其他SwiftUI视图都可以轻松触发此视图。例如,在登录视图中,如果用户名和密码错误 在下面,您可以找到我到目前为止的代码。只有在Username和Password字段中输入值时,此代码的问题才可见。通知视图显示正确,但同时用户名和密码字段的值正在丢失 发生这种情况是因为整个视图树正在重新渲染,通过NavigationLink创建一个全新的LoginView实例,其中包含一个空的LoginModel 如何在Swift
通知视图
。从任何其他SwiftUI视图都可以轻松触发此视图。例如,在登录视图中,如果用户名和密码错误
在下面,您可以找到我到目前为止的代码。只有在Username
和Password
字段中输入值时,此代码的问题才可见。通知视图显示正确,但同时用户名
和密码
字段的值正在丢失
发生这种情况是因为整个视图树正在重新渲染,通过NavigationLink
创建一个全新的LoginView
实例,其中包含一个空的LoginModel
如何在SwiftUI中正确执行此操作,以使值不会丢失
导入快捷界面
最终类通知模型:ObserveObject{
func show(文本:字符串){
self.text=文本
isHidden=false
}
@出版
var isHidden=true
var text=“”
}
结构通知视图:视图{
@环境对象
var模型:NotificationModel
var body:一些观点{
GeometryReader{中的几何体
如果!self.model.ishiden{
团体{
HStack{
图像(系统名:“感叹号标记.三角形”)
.font(font.largeTitle.weight(.light))
文本(self.model.Text)
.font(font.body.weight(.medium))
.padding()
垫片()
}
.frame(最大宽度:。无穷大,最小高度:geometry.safeareainsetts.top+44)
.填充(边设置(顶部:几何体。安全区域插入。顶部,前导:20,底部:0,尾随:20))
}
.背景(颜色.红色)
.transition(AnyTransition.move(边:。顶部)。与:。不透明度组合)
.ontapsigne{
动画片{
self.model.ishiden=true
}
}
}
}.edgesIgnoringSafeArea(.all)
}
}
最终类LoginModel:ObserveObject{
@出版
var email=“”
@出版
var password=“”
let notificationModel:notificationModel
init(notificationModel:notificationModel){
self.notificationModel=notificationModel
}
func submit(){
notificationModel.show(文本:“用户名/密码错误”)
}
}
结构逻辑视图:视图{
@观察对象
var模型:LoginModel
var body:一些观点{
VStack{
文本字段(“用户名”,文本:$model.email)
分隔器()
文本字段(“密码”,文本:$model.Password)
分隔器()
按钮(操作:{
self.model.submit()
}) {
文本(“提交”)
}
}
}
}
结构ContentView:View{
@环境对象
var notificationModel:notificationModel
var body:一些观点{
ZStack{
导航视图{
VStack{
导航链接(目标:LoginView(模型:LoginModel(notificationModel:notificationModel))){
文本(“登录”)
}
垫片()
}
.navigationBarTitle(“开始”)
}
通知视图()
}
}
}
您可能需要在contentView中翻转LoginModel和notificationModel
final class NotificationModel: ObservableObject {
func show(text: String) {
self.text = text
self.isHidden = false
}
@Published
var isHidden = true
var text = ""
}
struct NotificationView: View {
@EnvironmentObject
var model: NotificationModel
var body: some View {
GeometryReader { geometry in
if !self.model.isHidden {
Group {
HStack {
Image(systemName: "exclamationmark.triangle")
.font(Font.largeTitle.weight(.light))
Text(self.model.text)
.font(Font.body.weight(.medium))
.padding()
Spacer()
}
.frame(maxWidth: .infinity, minHeight: geometry.safeAreaInsets.top + 44)
.padding(EdgeInsets(top: geometry.safeAreaInsets.top, leading: 20, bottom: 0, trailing: 20))
}
.background(Color.red)
.transition(AnyTransition.move(edge: .top).combined(with: .opacity))
.onTapGesture {
withAnimation {
self.model.isHidden = true
}
}
}
}.edgesIgnoringSafeArea(.all)
}
}
final class LoginModel: ObservableObject {
@Published
var email = ""
@Published
var password = ""
let notificationModel: NotificationModel
init(notificationModel: NotificationModel) {
self.notificationModel = notificationModel
}
func submit() {
notificationModel.show(text: "Username/password wrong")
}
}
struct LoginView: View {
@ObservedObject
var model: LoginModel
var body: some View {
VStack {
TextField("Username", text: $model.email)
Divider()
TextField("Password", text: $model.password)
Divider()
Button(action: {
self.model.submit()
}) {
Text("Submit")
}
}
}
}
struct ContentView: View {
@EnvironmentObject var loginModel : LoginModel
var body: some View {
return ZStack {
NavigationView {
VStack {
NavigationLink(destination: LoginView(model: loginModel)) {
Text("Login")
}
Spacer()
}
.navigationBarTitle("Start")
}
NotificationView().environmentObject(loginModel.notificationModel)
}
}
}
谢谢,但这不是一个真正的选择。假设有另一组嵌套视图(选项卡栏等),表示应用程序的登录部分。问题是一样的,我不想让最外层的视图保存最内层的模型。每个登录模型或中间视图模型都应该有自己的通知模式。没有全局通知模型