Несоответствие анимации NavigationStack (пользовательский пакет)

Я создал оболочку вокруг API стека навигации с заменой root и функциями push и remove.

Есть одна ошибка, которую я не мог преодолеть некоторое время. Есть одна проблема, которая не соответствует всплывающим окнам и выталкивает анимацию после определенных операций навигации.

Чтобы было легче понять, позвольте мне объяснить некоторые необходимые сведения.

Это основная точка входа пакета, который экспортирует navigationStack со всеми настройками.

      public struct AppBuilder: View {

   @ObservedObject var navigationHandler : NavigationHandler

   public init(initial: PageRouteInfo) {
     navigationHandler = NavigationHandler(initial: initial)
   }

 public var body: some View {
    NavigationStack(path:$navigationHandler.stack) {
      EmptyView()
       .navigationDestination(for: PageRouteInfo.self) { routeInfo in
          AnyView(routeInfo.view.transition(.asymmetric(insertion: .move(edge: .leading), removal: .identity)))
             .navigationBarBackButtonHidden(routeInfo.isInitial )

       }
    }
    .environmentObject(navigationHandler)
   }
}


Это модель навигации, которая соответствует хешируемому протоколу для заполнения им стека.

      
public struct PageRouteInfo: Hashable {

   let view: any View
   let isInitial: Bool
   let id : String = UUID().uuidString
   

   public init( view: any View) {
      self.view = view
      self.isInitial = false
   }

   public init(view: any View, isInitial : Bool) {
      self.view = view
      self.isInitial = isInitial
   }


   public static func == (lhs: PageRouteInfo, rhs: PageRouteInfo) -> Bool {
      lhs.hashValue == rhs.hashValue
   }

   public func hash(into hasher: inout Hasher) {
      hasher.combine(id)
   }

   public mutating func makeFirst() -> PageRouteInfo {
      return PageRouteInfo(view: view, isInitial: true)
   }

}

И это класс, который управляет всеми элементами навигации и содержит стек @Published.

      
import Foundation
import SwiftUI

@available(iOS 16.0, *)
@available(macOS 13.0, *)
public class NavigationHandler: Navigator {
   @Published public var stack: [PageRouteInfo] = [] {
      didSet {
         print(stack.map { "Name : \($0.view)" })
      }
   }

   public init(initial: PageRouteInfo) {
      stack.append(initial)
   }

   public func push(destionation: any DeepRoutes) {
      stack.append(destionation.toItem())
   }

   public func pop() {
      if isNotLast {
         stack.removeLast()
      }
   }

   public func popToRoot() {
      stack.removeLast((1 ... stack.count - 1).count)
   }

   public func pushAndRemoveUntil(destionation: any DeepRoutes) {
      var route = destionation.toItem()
      stack.append(route.makeFirst())
      if stack.last != route {
         withDelay {
            self.stack.removeFirst((0 ..< (self.stack.count - 1)).count)
         }
      }
   }

   public func replaceRoot(with: any DeepRoutes) {
      var route = with.toItem()
      if isNotLast {
         stack.insert(route.makeFirst(), at: 0)
         stack.remove(at: 1)
      } else {
         stack.insert(route.makeFirst(), at: 1)
         withDelay { self.stack.remove(at: 0) }
      }
   }
}

private extension NavigationHandler {
   var isNotLast: Bool {
      return stack.count > 1
   }
}

private extension NavigationHandler {
   func withDelay(_ callback: @escaping () -> ()) {
      DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) {
         callback()
      }
   }
}

С учетом всего сказанного, push, pop и popToRoot работают как шарм. Но когда дело доходит до pushAndRemoveUntil и replaceRoot, все идет наперекосяк.

Например, если я использую pushAndRemoveUntil, он работает, как и предполагалось, помимо анимации. Он помещает новый вид в стек без кнопки «Назад» и удаляет остальные. Но если вы используете что-либо после запуска ошибки, в случае нажатия она исчезает мгновенно, или если вы снова используете pushAndRemoveUntil, она идет с всплывающей анимацией. То же самое с функцией replaceRoot.

Ниже приведены некоторые изображения описанной проблемы.

0 ответов

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