Как деаллоцировать или сбросить представления, когда пользователь выходит из системы?

Вопрос или проблема

Я экспериментирую с функцией входа в свою апликацию и заметил, что когда пользователь выходит и затем снова входит, представления отображают данные из предыдущей сессии. Неважно, является ли второй пользователь другим, это все равно происходит.

Как я могу освободить или иначе сбросить свои представления, когда пользователь выходит?

Упрощенный пример моего приложения.

@main
struct MyApp: App {
    @StateObject private var authModel = AuthModel()

    var body: some Scene {
        WindowGroup {
            if authModel.isAuthenticated && authModel.hasFreshData {
                ContentView().environmentObject(authModel)
            } else {
                LoginView().environmentObject(authModel)
            }
        }
    }
}

struct ContentView: View {
    var body: some View {
        TabView {
            HomeView().tabItem { Label("Главная", systemImage: "house") }

            SearchView().tabItem { Label("Поиск", systemImage: "magnifyingglass") }

            WebView().tabItem { Label("Старый", systemImage: "globe") }
        }
    }
}

struct SearchView: View {
    @State private var searchText = ""
    @State private var data = [data]()

    var body: some View {
        NavigationStack {
            List {
                ForEach(data) { dat in
                    Text("\(dat.value)")
                }
            }
            .searchable(text: $searchText)
            .onSubmit(of: .search, runSearch)
        }
    }

    func runSearch() {
        Task {
            data = await HTTPClient.runSearch(searchText)
        }
    }
}

struct WebView: UIViewRepresentable {
    var url: URL
    var webView: WKWebView

    func makeUIView(context: Context) -> WKWebView {
        webView = WKWebView()
        return webView
    }

    func updateUIView(_ webView: WKWebView, context: Context) {
        let request = URLRequest(url: url)
        webView.load(request)
    }
}

Представление SearchView использует модификатор searchable(text:placement:prompt:). Если в строке поиска введен текст, он виден, когда пользователь выходит и (другой пользователь) входит.

Ответ или решение

Чтобы корректно сбрасывать состояние представлений (views) при выходе пользователя из приложения, необходимо учесть несколько моментов. В вашем примере приложение сохраняет данные и состояния между сессиями пользователей, поэтому важно их инициализировать заново при логировании.

Шаг 1: Сброс состояния аутентификации и данных

Вы можете дополнить модель аутентификации (AuthModel), добавив метод для сброса состояния при выходе пользователя. Также можно воспользоваться наблюдаемыми свойствами для автоматического обновления представлений.

Шаг 2: Пример реализации

В вашем AuthModel добавьте методы для выхода и сброса данных. Например:

class AuthModel: ObservableObject {
    @Published var isAuthenticated = false
    @Published var hasFreshData = false
    @Published var currentUser: User? = nil // Например, модель пользователя

    func logIn(user: User) {
        self.currentUser = user
        self.isAuthenticated = true
        self.hasFreshData = true // Загрузите свежие данные для пользователя
    }

    func logOut() {
        // Сбросьте состояние
        self.currentUser = nil
        self.isAuthenticated = false
        self.hasFreshData = false
        // Выполняйте дополнительные действия по очистке данных, если необходимо
    }
}

Шаг 3: Обновление представлений при выходе

В вашем ContentView, добавьте кнопку выхода, которая будет вызывать метод logOut().

struct ContentView: View {
    @EnvironmentObject var authModel: AuthModel

    var body: some View {
        TabView {
            HomeView().tabItem { Label("Home", systemImage: "house") }
            SearchView().tabItem { Label("Search", systemImage: "magnifyingglass") }
            WebView().tabItem { Label("Old", systemImage: "globe") }
        }
        .toolbar {
            Button(action: {
                authModel.logOut()
            }) {
                Text("Выход")
            }
        }
    }
}

Шаг 4: Сброс данных в SearchView

В вашем SearchView, чтобы избежать показа старых данных, вы можете добавить инициализацию для переменной data в методе onAppear():

struct SearchView: View {
    @State private var searchText = ""
    @State private var data: [DataType] = []

    var body: some View {
        NavigationStack {
            List {
                ForEach(data) { dat in
                    Text("\(dat.value)")
                }
            }
            .searchable(text: $searchText)
            .onSubmit(of: .search, runSearch)
        }
        .onAppear {
            // Сброс состояния при появлении представления
            searchText = ""
            data = []
        }
    }

    func runSearch() {
        Task {
            data = await HTTPClient.runSearch(searchText)
        }
    }
}

Заключение

В результате этих изменений, вы сбросите состояние представлений, таким образом обеспечив корректное отображение данных для нового пользователя после выхода предыдущего. Каждый раз, когда пользователь выходит, будет очищаться состояние соответствующих представлений, что поможет избежать недоразумений с отображаемой информацией.

Оцените материал
Добавить комментарий

Капча загружается...