List的导航或许页面按钮的导航是iOS中最常见的状况,从OC的UIKit开端 UINavigationController便是最常用的,每次公司新事务 开一个新的页面或许主页加功用都是从UINavigationController开端

前史 — 视图导航

  • 1 开端的时分从xib ,tab + nav

  • 2 OC 的正常运用UINavigationController

  • 3 router path 的办法,通过runtime 和 hashmap来操控

其他的办法 大部分环绕去耦合的办法,少import 的思想来规划视图导航控件。这一次苹果自己规划了一次

NavigationStack 根本用法


NavigationStack {
  List(parks) { park in
    NavigationLink(park.name, value: park)
  }
  .navigationDestination(for: Park.self) { park in
    ParkDetails(park: park)
  }
}

NavigationStack 等同于开端的主页navContrller ,导航开端的时分。

@State private var path: [File] = []

NavigationStack(path: $path) {}

这个还有一种办法 通过path 来记载自己途径一个@State 状况改变时刻调查

这儿参阅 Simon Ng 的demo 懒得new 一个新的

SwiftUI 关于NavigationStack 视图导航

SwiftUI 关于NavigationStack 视图导航

全代码


var body: some View {
    NavigationStack {
      List(bgColors, id: \.**self**) { bgColor **in**
        NavigationLink {
          bgColor
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        } label: {
          Text(bgColor.description)
        }
      }
      .listStyle(.plain)
      .navigationTitle("Color")
    }
  }
 

NavigationLink

其实是个view ,用NavigationLink包一个自己的Cell在Label变量里边,这个很重要,这个很重要,

这个很重要。因为不是一切列表都要跳转,可是这个列表还有部分需求跳转。

NavigationLink 携带数值


NavigationStack {
  List(bgColors, id: \.self) { bgColor in
    NavigationLink(value: bgColor) {
      Text(bgColor.description)
    }
  }
  .listStyle(.plain)
  .navigationDestination(for: Color.self) { color in
    color
      .frame(maxWidth: .infinity, maxHeight: .infinity)
  }
  .navigationTitle("Color")
}

Link 的value 和 navigationDestination 的for 类型是对应的,不必定 navigationDestination 必须有才干跳转,仅仅是个一个选项

navigationDestination

详细页面在这儿完成。也能够多个Link 来一一对应 多个 navigationDestination


    var body: some View {
    NavigationStack {
      List {
        Section("Categories") {
          ForEach(categories) { category in
            NavigationLink(value: category) {
              Text(category.query)
                .font(.headline)
            }
          }
        }
       
        Section("Recent") {
          ForEach(recentProducts) { product in
            NavigationLink(product.title, value: product)
          }
        }
      }
      .navigationTitle("Home")
      .navigationDestination(for: Category.self) { category in
        CategoryView(category: category)
      }
      .navigationDestination(for: Product.self) { product in
        ProductDetailView(product: product)
      }
    }

这儿参阅 Swift with Majid 的文章的代码。也是懒得敲一遍了。

不同的数据,不同的跳转新页面,别yy 非页面跳转的状况,比如一个变量一个 改写什么的。

因为 navigationDestination 的文档说明


func navigationDestination<D, C>(for data: D.Type, destination: @escaping (D) -> C) -> some View where D : Hashable, C : View

内部要的是一个view,不是view 哪怕是写一个print 都是过错

接连跳转

这个我的了解和Simo Ng 的文章不同的看法

NavigationStack 要的去耦合 ,新页面假如再想跳不断的重复写Link 就行,不必写 navigationDestination 和 NavigationStack(这个和UINavigationController 的思想一样),一个操控器 操控一切压入的page,不必每个page 都有一个nav。

可是因为引入的 navigationDestination 统一管理,是优点也是难处。很少事务不断的push 不需求改一些数据问题。

所以反而不必navigationDestination 能适应的场景更多,这样的写法也更简略


NavigationStack {
      List(bgColors, id: \.**self**) { bgColor **in**
        NavigationLink { // 跳转后的page
          bgColor
            .frame(maxWidth: .infinity, maxHeight: .infinity)
        } label: { // cell的姿态
          Text(bgColor.description)
        }
      }
      .listStyle(.plain)
      .navigationTitle("Color")
    }

别直接 的就 NavigationLink(value: category) { },这样少了许多的麻烦

SwiftUI 关于NavigationStack 视图导航

这个的版别操控 必定要注意,mac 和ios 的都是比较新的版别才适配,老的navigationView 已经抛弃

吐槽

juejin 的md 太难用了,代码格局 不能直接复制粘贴。iOS 的NavigationStack 尽管多渠道都能够用,可是macos 用的更多的是 NavigationSplitView 来进行 ui 的散布操控。

遇到的坑

这个最大的坑便是 push 的时分 假如不是一个View 就全要重新考虑替换掉Link 的写法,这也是SwiftUI和UIKit 的思想不一样的原因,View的编写用SwiftUI 功率是很高,UIKit的navigation 放开了点击的事件,可是SwiftUI 想的是尽量不要在view 里边写办法关于逻辑的,这个事写SwiftUI的一个个人感觉

进口和出口关于SwiftUI 都是一个简略的变量,能够 @State 也可能是一个@Binding 变量。可是肯定不是一个Bool var + 一个改写办法放在nav 里边