Если вы используете iPad и меняете экран с компактного на обычный, как предотвратить переход текущего представления к виду по умолчанию?

//  BottomNavigationBarView.swift
//  TrexlerLibrary
//
//  Created by Emanuel Luna on 2/3/24.
//

import SwiftUI
import UserNotifications

enum ActiveView: String, Hashable {
    case home
    case search
    case settings
}


struct MainView: View {
    @Environment(\.horizontalSizeClass) var sizeClass
    @State private var activeView: ActiveView? = .home

var body: some View {
    Group {
        if sizeClass == .compact {
            iphoneTabView
        } else {
            ipadExpansiveView
        }
    }
    .onAppear {
        InfoForLibrary().requestNotificationPermission()
    }
}

private var iphoneTabView: some View {
    TabView(selection: $activeView) {
        NavigationView { HomeView() }
            .tabItem {
                Label("Home", systemImage: "house")
            }
            .tag(ActiveView.home)
        
        NavigationView { SearchView() }
            .tabItem {
                Label("Search", systemImage: "magnifyingglass")
            }
            .tag(ActiveView.search)
        
        NavigationView { SettingsView() }
            .tabItem {
                Label("Settings", systemImage: "gear")
            }
            .tag(ActiveView.settings)
    }
}

private var ipadExpansiveView: some View {
    
    NavigationView {
        List {
            NavigationLink(destination: HomeView(), tag: ActiveView.home, selection: $activeView) {
                Label("Home", systemImage: "house")
            }
            
            NavigationLink(destination: SearchView(), tag: ActiveView.search, selection: $activeView) {
                Label("Search", systemImage: "magnifyingglass")
            }
            
            NavigationLink(destination: SettingsView(), tag: ActiveView.settings, selection: $activeView) {
                Label("Settings", systemImage: "gear")
            }
        }
        .listStyle(SidebarListStyle())
        .navigationTitle("Menu")
        
        // Render the currently selected view
        currentView
    }
}

private var currentView: some View {
    switch activeView {
    case .home:
        return AnyView(HomeView())
    case .search:
        return AnyView(SearchView())
    case .settings:
        return AnyView(SettingsView())
    case .none:
        return AnyView(HomeView())
        }
    }
}

// Preview
#Preview {
    MainView().environmentObject(UserSession())
}

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

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

Какие версии iOS вы поддерживаете? Можете ли вы вместо этого использовать NavigationStack?

Sweeper 17.04.2024 03:18

На данный момент я поддерживаю iOS 17.

EMAN-GAMING 17.04.2024 05:45

Я думаю, это потому, что теги вкладок не того типа, что activeView. Попробуйте изменить .tag(ActiveView.home) на .tag(Optional.some(ActiveView.home)) и сделайте то же самое для каждого тега вкладки.

Sweeper 17.04.2024 06:15
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вероятно, такое поведение связано с тем, что тип activeView отличается от типов tag, которые вы назначили каждой вкладке. ActiveTab? против ActiveTab. Тем не менее, то, как вы написали ipadExpansiveView, тоже довольно проблематично.

Для iOS 17 вам следует перейти на NavigationStack и NavigationSplitView.

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

enum ActiveView: String, Hashable, CaseIterable {
    case home
    case search
    case settings
    
    var displayName: String {
        switch self {
        case .home:
            "Home"
        case .search:
            "Search"
        case .settings:
            "Settings"
        }
    }
    
    var systemImageName: String {
        switch self {
        case .home:
            "house"
        case .search:
            "magnifyingglass"
        case .settings:
            "gear"
        }
    }
    
    @ViewBuilder
    var view: some View {
        switch self {
        case .home:
            Text("Home")
        case .search:
            Text("Search")
        case .settings:
            Text("Settings")
        }
    }
}

Я бы также сделал iPhoneTabView и iPadExpansiveViews отдельными View структурами:

struct iPhoneTabView: View {
    @Binding var activeView: ActiveView
    
    var body: some View {
        TabView(selection: $activeView) {
            ForEach(ActiveView.allCases, id: \.self) { tab in
                NavigationStack { tab.view }
                    .tabItem {
                        Label(tab.displayName, systemImage: tab.systemImageName)
                    }
            }
        }
    }
}

struct iPadExpansiveView: View {
    @Binding var activeView: ActiveView
    
    var body: some View {
        NavigationSplitView {
            List(ActiveView.allCases, id: \.self, selection: Binding($activeView)) { tab in
                NavigationLink(value: tab) {
                    Label(tab.displayName, systemImage: tab.systemImageName)
                }
            }
        } detail: {
            activeView.view
        }

    }
}

NavigationSplitView определяется выбором List. Параметр selection: ожидает Binding<ActiveView?>, но отсутствие активного просмотра не имеет смысла, не так ли? Таким образом, iPadExpansiveView принимает необязательную привязку ActiveView и преобразует ее в Binding<ActiveView?> непосредственно перед передачей в selection:.

Тогда MainView будет выглядеть так, с необязательным состоянием activeView.

@Environment(\.horizontalSizeClass) var sizeClass
@State private var activeView: ActiveView = .home

var body: some View {
    Group {
        if sizeClass == .compact {
            iPhoneTabView(activeView: $activeView)
        } else {
            iPadExpansiveView(activeView: $activeView)
        }
    }
}

Это сработало! Интересно, можно ли было бы сделать это с другими видами? Например, в SettingsView есть список с кнопкой «О программе». Когда я нажимаю на него, я перехожу к другому представлению, которое все еще находится в SettingsView.

EMAN-GAMING 18.04.2024 05:06

@EMAN-GAMING Конечно. Я думаю, вам следует поискать «навигацию на основе значений» в качестве отправной точки. Если вы застряли, вы можете опубликовать новый вопрос и включить минимально воспроизводимый пример, как вы это сделали здесь.

Sweeper 18.04.2024 05:10

Другие вопросы по теме