SwiftUI:在关闭Sheet后重新加载视图

5

我在UserDefaults中有一个布尔值来检查用户是否已登录。

在我的第一页中,当用户点击个人资料图片时,会显示一个模态框(使用.sheet),里面有一个用于用户注销的按钮。

当用户按下注销按钮并关闭模态框后,我该如何改变视图呢?

或者说,当用户按下注销按钮并关闭模态框后,我该如何重新加载主页面以检查新的布尔值?

struct Home: View {

    var body: some View {
        ScrollView {
            VStack {   
                // MARK: Header
                Header(title: "Home")    
            }
            Spacer()
        }
        .padding(20)
    }
}

struct Header: View {

    public var title: String = ""
    @State private var showProfile = false

    var body: some View {
        HStack {
            // MARK: - User Profile
            Image("profile")
                .resizable()
                .clipShape(Circle())
                .frame(width: 50, height: 50)
                .onTapGesture {
                    print("⚠️ Profile has been tapped.")
                    self.showProfile.toggle()
            }
            .sheet(isPresented: $showProfile) {
                Account(showProfile: self.$showProfile)
            }

        }
    }
}

struct Account: View {

    @Binding var showProfile: Bool

    var body: some View {
        NavigationView {

            // MARK: - Account Sections
            List {

                // MARK: - Log Out -
                Section {
                    Button(action: {
                        print("❌ User has been logged out.")
                        self.showProfile.toggle()

                    }) {
                        Text("Log Out")
                            .bold()
                            .foregroundColor(.red)
                    }
                }
            }

                // MARK: - NavigationBar Settings
                .navigationBarTitle("Account", displayMode: .inline)
        }
    }
}

这是我的UserDefault类

class UsersSettings: ObservableObject {

    @Published var isLoggedIn: Bool = UserDefaults.standard.bool(forKey: "isLogged") {
        didSet {
            UserDefaults.standard.set(self.isLoggedIn, forKey: "isLogged")
            print(UserDefaults.standard.bool(forKey: "isLogged"))
        }
    }
}

你曾经解决过这个问题吗?我遇到了类似的问题,当查看表格然后关闭其中的列表视图时,列表中的项目现在变成了空白。因此我需要知道如何在关闭表格时强制刷新ListView? - Learn2Code
这个视频中,我注意到这个人做了我想要的事情,经过检查,我发现这个人使用了一个叫做“NotificationCenter”的东西,我也这样做了,现在它对我有用了。你可以在这里了解更多关于NotificationCenter的内容。 - arata
3个回答

0

很难说,你的目标是什么。也许这个方案可以满足你的需求: 1)当用户点击图片时,弹出表单 2)用户可以登录或注销,或者通过向下滑动手势简单地关闭表单 3)用户的图片反映了登录/注销状态

import SwiftUI

class LoginModel: ObservableObject {
    @Published var loggedIn = false
}

let loginModel = LoginModel()

struct ContentView: View {
    @ObservedObject var model = loginModel
    var body: some View {
        ScrollView {
            VStack {
                // MARK: Header
                Header(title: "Home", loggedIn: model.loggedIn)
            }
            Spacer()
        }
        .padding(20)
    }
}

struct Header: View {

    public var title: String = ""
    var loggedIn: Bool
    @State private var showProfile = false
    var body: some View {
        HStack {
            // MARK: - User Profile
            Image(systemName: loggedIn ? "photo.fill.on.rectangle.fill" : "photo.on.rectangle")
                .resizable()
                .clipShape(Circle())
                .frame(width: 50, height: 50)
                .onTapGesture {
                    self.showProfile.toggle()
            }
            .sheet(isPresented: $showProfile) {
                Account(showProfile: self.$showProfile)
            }

        }
    }
}

struct Account: View {

    @Binding var showProfile: Bool
    @ObservedObject var model = loginModel

    var body: some View {
        NavigationView {
            List {
                Section {
                    Button(action: {
                        self.model.loggedIn.toggle()
                        self.showProfile.toggle()

                    }) {
                        Text(model.loggedIn ? "Log Out": "Log In")
                            .bold()
                            .foregroundColor(.red)
                    }
                }
            }
            .navigationBarTitle("Account", displayMode: .inline)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

结果看起来像这样

enter image description here


当用户点击注销按钮时,我正在尝试再次向用户显示登录页面(这将在第一次启动时显示)。在您的代码中,我希望在ContentView()上检查UserDefault值,以查看它是否为真,如果为假,则显示登录视图,并且当用户点击注销时,关闭弹窗并显示登录视图。 - arata
@user3441734,你解决了这个问题吗?我遇到了类似的问题,当表格被查看并关闭后,列表视图中的项目现在变为空白。因此,我需要知道如何在关闭表格时强制刷新ListView? - Learn2Code
@Learn2Code的解决方案是什么?我的答案中的代码按预期运行(如上所述)。老实说,我不理解"arata"的通知... 复制-粘贴-运行此代码,您将看到List中的值已按要求更新。 - user3441734
@user3441734 你能去看一下我的问题吗:https://stackoverflow.com/questions/60662263/issue-with-swiftui-listview-when-sheet-is-presented-and-then-dismissed - Learn2Code

0

UserSettings 是真相之源,必须在您的表格模态视图 (Account) 中使用。

在主页或标题视图中添加一个绑定到此对象,以观察更改并相应地更新您的界面。

您可以像这样声明一个对象绑定:

struct Home: View {
  @ObservedObject var userSettings: UserSettings
  // ...
}

然后您会观察到像这样的更改:

struct Home: View {
  // ...  
  var body: some View {
    if userSettings.isLoggedIn {
      Text("User is logged in")
    } else {
      Text("User is not logged in")
    }
  } 
}

为了使其正常工作,您必须在Active视图中注销用户。


2
它没有改变任何东西,我仍然需要关闭应用程序并重新打开才能看到更改。 - arata

-3

1
这个回答被踩是因为它只有一个链接,可能会过时,而且回答没有帮助到任何人。 - Jimbo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接