防止NavigationLink自行返回导航视图

问题描述 投票:0回答:1

我有一份一直观察到的餐厅清单:

func getAllRestaurantsInParameters(lat: Double, long: Double){
        
        self.repo.getAllRestaurants().watch(block: {restaurants in
            
            self.restaurantList = (restaurants as! [Restaurant])
        })
}

在我的主视图中,我有一个包含 NavigationLink 列表的 NavigationView:

NavigationView{
            
     List{
         ForEach(restaurantList, id: \.self) { restaurant in
                             
                NavigationLink(destination: IndividualRestaurantView()){

                      ZStack {Text(restaurant.name)}
                }
         }
     } 
}

每当我进入任何 Navigaiton Link 餐厅,并将某些内容更改为另一家餐厅时,导航链接都会自行返回到第一个主视图。为什么会发生这种情况?我认为这是因为观察者方法,每当发生更改时都会更改餐厅列表,但我仍然不想返回主视图..

如何防止这种情况发生?

我做了测试添加 .navigationViewStyle(StackNavigationViewStyle()) .navigationViewStyle(.stack)在NavigationView上,但没有工作。

还有其他选择吗? .watch(块:将观察餐厅的任何变化并调用该方法。

如何防止导航链接自行返回导航视图?

swift swiftui swift3 swiftui-navigationlink swiftui-navigationview
1个回答
0
投票

您的假设是正确的,自动导航回主视图是由于 getAllRestaurants() 中的观察者触发了restaurantList 中的更改,这导致 SwiftUI 重新渲染视图并重置导航堆栈。这是解决您问题的全面解决方案:

出现此问题是因为每次更新 RestaurantList 时,SwiftUI 都会认为需要更新整个视图,从而重置导航堆栈。要解决此问题,您可以通过手动管理导航链接的状态或更改处理数据更新的方式,使视图对数据更改更具弹性。以下是一些策略:

选项 1:为 NavigationLink 使用稳定的标识符

如果Restaurant符合Identifying,请使用其id代替.\self以获得更稳定的标识。如果 Restaurant 不符合 Identificate,您可以向您的 Restaurant 模型添加标识符:

struct Restaurant: Identifiable {
    let id: UUID = UUID()
    var name: String
}

// Then in your view
ForEach(restaurantList, id: \.id) { restaurant in
    NavigationLink(destination: IndividualRestaurantView(restaurant: restaurant)){
        ZStack { Text(restaurant.name) }
    }
}

这样,即使餐厅列表更新,SwiftUI 也可以保持导航链接的状态,因为餐厅的身份没有改变。

选项 2:避免不必要的更新

另一种方法是尽量减少对restaurantList 本身的更新。仅在必要时更新餐厅列表:

func getAllRestaurantsInParameters(lat: Double, long: Double){
    self.repo.getAllRestaurants().watch { restaurants in
        // Convert fetched array to identifiable if not already
        let updatedList = (restaurants as! [Restaurant])
        if updatedList.map(\.id) != self.restaurantList.map(\.id) {
            self.restaurantList = updatedList
        }
    }
}

此代码片段确保仅当获取的餐厅列表实际上与基于餐厅 ID 的当前列表不同时才更新 RestaurantList,从而可能减少不必要的视图刷新。

选项 3:使用不同的状态管理方法

如果上述方法不太适合您的应用程序架构,请考虑对餐厅数据使用不同的状态管理方法,例如 ObservableObject:

class RestaurantViewModel: ObservableObject {
    @Published var restaurantList: [Restaurant] = []

    init() {
        loadRestaurants()
    }

    func loadRestaurants() {
        // Simulation of data fetch and watching
        repo.getAllRestaurants().watch { [weak self] restaurants in
            DispatchQueue.main.async {
                self?.restaurantList = (restaurants as! [Restaurant])
            }
        }
    }
}

// In your SwiftUI view
@StateObject private var viewModel = RestaurantViewModel()

NavigationView {
    List {
        ForEach(viewModel.restaurantList, id: \.id) { restaurant in
            NavigationLink(destination: IndividualRestaurantView(restaurant: restaurant)) {
                ZStack { Text(restaurant.name) }
            }
        }
    }
}

使用 ObservableObject 并异步更新 UI 可以帮助更干净地管理状态更改并避免不必要的导航弹出。

通过使用其中一种策略,您应该能够控制因 SwiftUI 应用程序中的数据更新而导致的不必要的导航重置。由于我对您的应用程序的结构一无所知,因此请确保您选择正确的选项,因为这一切都是为了找到适合您的特定应用程序架构和需求的适当平衡。

希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.