Skip to content

Instantly share code, notes, and snippets.

@filimo
Last active November 25, 2022 14:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save filimo/a3b5a92c6a0c7b670b97604cd70c521b to your computer and use it in GitHub Desktop.
Save filimo/a3b5a92c6a0c7b670b97604cd70c521b to your computer and use it in GitHub Desktop.
import SwiftUI
enum NavTestRoute: Hashable {
case child(Int)
}
struct NavTestChildView: View {
let num: Int
init(num: Int) {
print("[init][NavTestChildView]")
self.num = num
}
var body: some View {
Text("NavTestChildView \(num)")
}
}
struct NavTestMainView2: View {
init() {
print("[init][NavTestMainView2]")
}
var body: some View {
VStack {
NavigationLink {
NavTestMainView2()
} label: {
Text("Reenter NavTestMainView")
}
ForEach(1 ..< 10, id: \.self) { num in
NavigationLink(value: NavTestRoute.child(num)) {
Text("Open child \(num)")
}
}
}
.navigationDestination(for: NavTestRoute.self) { route in
switch route {
case let .child(num):
NavTestChildView(num: num)
}
}
}
}
struct NavTestMainView: View {
init() {
print("[init][NavTestMainView]")
}
var body: some View {
NavigationStack {
NavTestMainView2()
}
}
}
enum NavTestRoute: Hashable {
case child(Int)
}
struct NavTestChildView: View {
let num: Int
init(num: Int) {
print("[init][NavTestChildView]")
self.num = num
}
var body: some View {
Text("NavTestChildView \(num)")
}
}
struct NavTestMainView2: View {
@Binding var items: [Int]
init(items: Binding<[Int]>) {
print("[init][NavTestMainView2]")
self._items = items
}
var body: some View {
VStack {
NavigationLink {
NavTestMainView2(items: $items)
} label: {
Text("Reenter NavTestMainView")
}
ForEach(1 ..< 10, id: \.self) { num in
NavigationLink(value: NavTestRoute.child(num)) {
Text("Open child \(num)")
}
}
}
.navigationDestination(for: NavTestRoute.self) { route in
switch route {
case let .child(num):
NavTestChildView(num: num)
}
}
}
}
struct NavTestMainView: View {
@State var items: [Int] = [1, 2, 3, 4]
init() {
print("[init][NavTestMainView]")
}
var body: some View {
NavigationStack {
NavTestMainView2(items: $items)
}
}
}
import SwiftUI
enum NavTestRoute: Hashable {
case child(Int)
}
struct NavTestChildView: View {
let num: Int
var body: some View {
Text("NavTestChildView \(num)")
}
}
struct NavTestMainView_Control: View {
let num: Int
let isDetailMode: Bool
@Binding var items: [Int]
var body: some View {
VStack {
if isDetailMode {
Text("Long mode \(num)")
ForEach(items, id: \.self) { item in
NavigationLink(value: NavTestRoute.child(item)) {
Text("Go to \(item)")
}
}
} else {
Text("Short mode \(num)")
}
}
}
}
struct NavTestMainView2: View {
@State var items: [Int] = []
var body: some View {
ForEach(1 ..< 5) { num in
NavigationLink {
NavTestMainView_Control(num: num, isDetailMode: true, items: $items)
} label: {
NavTestMainView_Control(num: num, isDetailMode: false, items: $items)
}
.task {
items = [1, 2, 4]
}
.navigationDestination(for: NavTestRoute.self) { route in
switch route {
case let .child(num):
NavTestChildView(num: num)
}
}
}
}
}
struct NavTestMainView: View {
init() {
print("[init][NavTestMainView]")
}
var body: some View {
NavigationStack {
NavTestMainView2()
}
}
}
@drucelweisse
Copy link

drucelweisse commented Nov 24, 2022

Я не уверен насчет этого, но вроде бы прекрасно работает, правда ломается биндинг внутри чайлда, но это уже совершенно другая задача(не подтягивает изменения на лету)

extension Binding: Equatable where Value: Equatable {
    public static func == (lhs: Binding<Value>, rhs: Binding<Value>) -> Bool {
        lhs.wrappedValue == rhs.wrappedValue
    }
    
   
}

extension Binding: Hashable where Value: Hashable {
    public func hash(into hasher: inout Hasher) {
        hasher.combine(wrappedValue)
    }
}

enum NavTestRoute: Hashable {
    case child(Binding<Int>)
    case main
}
struct NavTestChildView: View {
    @Binding var num: Int

    var body: some View {
        VStack {
            Text("NavTestChildView \(num)")
            Stepper("Chane", value: $num, in: 0...10)
        }
       
            .navigationTitle("child \(num)")
    }
}
struct NavTestMainView2: View {
    @Binding var items: [Int]
    var body: some View {
        VStack {
            NavigationLink(value: NavTestRoute.main){
                Text("Reenter NavTestMainView")
            }
            
            ForEach($items, id: \.self) { $item in
                NavigationLink(value: NavTestRoute.child($item)) {
                    VStack {
                        Text("Open child \(item)")

                    }
                    
                }
            }
        }
        

    }
}
struct NavTestMainView: View {
    @State var items: [Int] = [1, 2, 3, 4]
    var body: some View {
        NavigationStack {
            NavTestMainView2(items: $items)
                .navigationTitle("Root")
                .navigationDestination(for: NavTestRoute.self) { route in
                    switch route {
                    case let .child(num):
                        NavTestChildView(num: num)
                    case .main:
                        NavTestMainView2(items: $items)
                    }
                }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        NavTestMainView()
    }
}

@filimo
Copy link
Author

filimo commented Nov 24, 2022

With case detail(num: Int, items: Binding<[DebugItem]>)

import SwiftUI

extension Binding: Equatable where Value: Hashable {
    public static func == (lhs: Binding<Value>, rhs: Binding<Value>) -> Bool {
        lhs.wrappedValue == rhs.wrappedValue
    }
}

extension Binding: Hashable where Value: Hashable {
    public func hash(into hasher: inout Hasher) {
        hasher.combine(wrappedValue)
    }
}

struct DebugItem: Hashable {
    let id: Int
    let name: String
    var selected: Bool = true
}

enum NavTestRoute: Hashable {
    case child(DebugItem)
    case detail(num: Int, items: Binding<[DebugItem]>)
}

struct NavTestChildView: View {
    let item: DebugItem

    var body: some View {
        Text("NavTestChildView \(String(describing: item))")
    }
}

struct NavTestMainView_Control: View {
    let num: Int
    let isDetailMode: Bool
    @Binding var items: [DebugItem]

    var body: some View {
        VStack {
            if isDetailMode {
                Text("Long mode \(num)")

                ForEach($items, id: \.self) { $item in
                    NavigationLink(value: NavTestRoute.child(item)) {
                        HStack {
                            Text("Go to \(item.name)")
                            Toggle("", isOn: $item.selected)
                        }
                    }
                }
            } else {
                Text("Short mode \(num)")
            }
        }
    }
}

struct NavTestMainView2: View {
    let num: Int
    
    @State var items: [DebugItem] = []

    var body: some View {
        NavigationLink(value: NavTestRoute.detail(num: num, items: $items)) {
            NavTestMainView_Control(num: num, isDetailMode: false, items: $items)
        }
        .task {
            guard items.isEmpty else { return }

            items = [
                .init(id: 1, name: "item1"),
                .init(id: 2, name: "item2"),
                .init(id: 3, name: "item3")
            ]
        }
    }
}

struct NavTestMainView: View {
    var body: some View {
        NavigationStack {
            ForEach(1 ..< 5) { num in
                NavTestMainView2(num: num)
            }
            .navigationDestination(for: NavTestRoute.self) { route in
                switch route {
                case let .detail(num, items):
                    NavTestMainView_Control(num: num, isDetailMode: true, items: items)
                case let .child(item):
                    NavTestChildView(item: item)
                }
            }
        }
    }
}

@filimo
Copy link
Author

filimo commented Nov 25, 2022

поменял на extension Binding: Equatable where Value: Hashable { иначе ломается .searchable

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment