Tôi đã kết thúc việc ghi đè mặc định NavigationView
và NavigationLink
để có được hành vi mong muốn. Điều này có vẻ đơn giản đến mức tôi phải xem một cái gì đó mà các chế độ xem SwiftUI mặc định làm gì?
Điều hướng
Tôi gói gọn UINavigationController
trong một siêu đơn giản UIViewControllerRepresentable
cung cấp cho UINavigationController
chế độ xem nội dung SwiftUI dưới dạng môi trường. Điều này có nghĩa là NavigationLink
sau này có thể lấy được miễn là trong cùng một bộ điều khiển điều hướng (trình điều khiển chế độ xem được trình bày không nhận được môi trường môi trường), đó chính xác là những gì chúng ta muốn.
Lưu ý: NavigationView cần .edgesIgnoringSafeArea(.top)
và tôi chưa biết cách đặt nó trong cấu trúc. Xem ví dụ nếu nvc của bạn bị cắt ở đầu.
struct NavigationView<Content: View>: UIViewControllerRepresentable {
var content: () -> Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
}
func makeUIViewController(context: Context) -> UINavigationController {
let nvc = UINavigationController()
let host = UIHostingController(rootView: content().environmentObject(nvc))
nvc.viewControllers = [host]
return nvc
}
func updateUIViewController(_ uiViewController: UINavigationController, context: Context) {}
}
extension UINavigationController: ObservableObject {}
Điều hướng
Tôi tạo một NavigationLink tùy chỉnh truy cập vào các môi trường UINavestionControll để đẩy UIhostingControll lưu trữ khung nhìn tiếp theo.
Lưu ý: Tôi đã không triển khai selection
và isActive
SwiftUI.NavulationLink có vì tôi chưa hiểu hết những gì họ làm. Nếu bạn muốn giúp với điều đó xin vui lòng bình luận / chỉnh sửa.
struct NavigationLink<Destination: View, Label:View>: View {
var destination: Destination
var label: () -> Label
public init(destination: Destination, @ViewBuilder label: @escaping () -> Label) {
self.destination = destination
self.label = label
}
/// If this crashes, make sure you wrapped the NavigationLink in a NavigationView
@EnvironmentObject var nvc: UINavigationController
var body: some View {
Button(action: {
let rootView = self.destination.environmentObject(self.nvc)
let hosted = UIHostingController(rootView: rootView)
self.nvc.pushViewController(hosted, animated: true)
}, label: label)
}
}
Điều này giải quyết thao tác vuốt ngược không hoạt động chính xác trên SwiftUI và vì tôi sử dụng tên NavigationView và NavigationLink, toàn bộ dự án của tôi đã chuyển sang những cái này ngay lập tức.
Thí dụ
Trong ví dụ tôi cũng trình bày phương thức.
struct ContentView: View {
@State var isPresented = false
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 30) {
NavigationLink(destination: Text("Detail"), label: {
Text("Show detail")
})
Button(action: {
self.isPresented.toggle()
}, label: {
Text("Show modal")
})
}
.navigationBarTitle("SwiftUI")
}
.edgesIgnoringSafeArea(.top)
.sheet(isPresented: $isPresented) {
Modal()
}
}
}
struct Modal: View {
@Environment(\.presentationMode) var presentationMode
var body: some View {
NavigationView {
VStack(alignment: .center, spacing: 30) {
NavigationLink(destination: Text("Detail"), label: {
Text("Show detail")
})
Button(action: {
self.presentationMode.wrappedValue.dismiss()
}, label: {
Text("Dismiss modal")
})
}
.navigationBarTitle("Modal")
}
}
}
Chỉnh sửa: Tôi bắt đầu với "Điều này có vẻ đơn giản đến mức tôi phải nhìn ra thứ gì đó" và tôi nghĩ rằng tôi đã tìm thấy nó. Điều này dường như không chuyển môi trường môi trường sang chế độ xem tiếp theo. Tôi không biết NavigationLink mặc định làm điều đó như thế nào nên bây giờ tôi tự gửi các đối tượng đến chế độ xem tiếp theo nơi tôi cần chúng.
NavigationLink(destination: Text("Detail").environmentObject(objectToSendOnToTheNextView)) {
Text("Show detail")
}
Chỉnh sửa 2:
Điều này cho thấy bộ điều khiển điều hướng cho tất cả các khung nhìn bên trong NavigationView
bằng cách thực hiện @EnvironmentObject var nvc: UINavigationController
. Cách để khắc phục điều này là tạo môi trườngObject mà chúng ta sử dụng để quản lý điều hướng một lớp fileprivate. Tôi đã sửa lỗi này trong ý chính: https://gist.github.com/Amzd/67bfd4b8e41ec3f179486e13e9892eeb