Last active
May 29, 2020 11:29
-
-
Save agelessman/335914b2db480c5a343111a4a5bd4e36 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// ContentView.swift | |
// DissmissGesture | |
// | |
// Created by MC on 2020/5/29. | |
// Copyright © 2020 MC. All rights reserved. | |
// | |
import SwiftUI | |
import UIKit | |
struct ContentView: View { | |
@State private var show = false | |
@ObservedObject var dataModel = MyDataModel() | |
var body: some View { | |
DissmissGuardian(preventDismiss: $dataModel.preventDissmissal, attempted: $dataModel.attempted) { | |
VStack { | |
Spacer() | |
Text("演示如何监听Dissmiss手势").font(.title) | |
Spacer() | |
Button("跳转到新的View") { | |
self.show = true | |
} | |
.sheet(isPresented: self.$show) { | |
MyCustomerView().environmentObject(self.dataModel) | |
} | |
Spacer() | |
} | |
} | |
} | |
} | |
class MyDataModel: ObservableObject { | |
@Published var attempted = false | |
@Published var preventDissmissal = false | |
@Published var firstName: String = "" { | |
didSet { | |
updatePrecentDissmissal() | |
} | |
} | |
@Published var lastName: String = "" { | |
didSet { | |
updatePrecentDissmissal() | |
} | |
} | |
func updatePrecentDissmissal() { | |
self.preventDissmissal = (self.firstName != "" || self.lastName != "") | |
} | |
func save() { | |
self.reset() | |
} | |
func reset() { | |
self.firstName = "" | |
self.lastName = "" | |
} | |
} | |
protocol DismissGuardianDelegate { | |
func attemptedUpdate(flag: Bool) | |
} | |
class DismissGuardianUIHostingController<Content>: UIHostingController<Content>, UIAdaptivePresentationControllerDelegate where Content: View { | |
var preventDismissal: Bool | |
var dismissGuardianDelegate: DismissGuardianDelegate? | |
init(rootView: Content, preventDismissal: Bool) { | |
self.preventDismissal = preventDismissal | |
super.init(rootView: rootView) | |
} | |
@objc required dynamic init?(coder aDecoder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) { | |
viewControllerToPresent.presentationController?.delegate = self | |
dismissGuardianDelegate?.attemptedUpdate(flag: false) | |
super.present(viewControllerToPresent, animated: flag, completion: completion) | |
} | |
func presentationControllerDidAttemptToDismiss(_ presentationController: UIPresentationController) { | |
dismissGuardianDelegate?.attemptedUpdate(flag: true) | |
} | |
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { | |
return !self.preventDismissal | |
} | |
} | |
struct DissmissGuardian<Content: View>: UIViewControllerRepresentable { | |
@Binding var preventDismiss: Bool | |
@Binding var attempted: Bool | |
var content: Content | |
init(preventDismiss: Binding<Bool>, attempted: Binding<Bool>, @ViewBuilder content: @escaping () -> Content) { | |
self._preventDismiss = preventDismiss | |
self._attempted = attempted | |
self.content = content() | |
} | |
func makeUIViewController(context: Context) -> UIViewController { | |
return DismissGuardianUIHostingController(rootView: self.content, preventDismissal: self.preventDismiss) | |
} | |
func updateUIViewController(_ uiViewController: UIViewController, context: Context) { | |
let dismissHosting = uiViewController as! DismissGuardianUIHostingController<Content> | |
dismissHosting.preventDismissal = self.preventDismiss | |
dismissHosting.rootView = self.content | |
dismissHosting.dismissGuardianDelegate = context.coordinator | |
} | |
func makeCoordinator() -> Coordinator { | |
return Coordinator(attempted: $attempted) | |
} | |
class Coordinator: NSObject, DismissGuardianDelegate { | |
@Binding var attempted: Bool | |
init(attempted: Binding<Bool>) { | |
self._attempted = attempted | |
} | |
func attemptedUpdate(flag: Bool) { | |
self.attempted = flag | |
} | |
} | |
} | |
struct MyCustomerView: View { | |
@EnvironmentObject var dataModel: MyDataModel | |
@Environment(\.presentationMode) private var presentationMode | |
var body: some View { | |
NavigationView { | |
Form { | |
TextField("姓", text: $dataModel.firstName) | |
TextField("名", text: $dataModel.lastName) | |
} | |
.navigationBarTitle("编辑姓名") | |
.navigationBarItems(trailing: | |
Button("保存") { | |
self.dataModel.save() | |
self.presentationMode.wrappedValue.dismiss() | |
} | |
) | |
.alert(isPresented: $dataModel.attempted) { | |
Alert(title: Text("警告"), message: Text("请填写姓名"), primaryButton: .default(Text("仍然退出")), secondaryButton: .cancel()) | |
} | |
} | |
} | |
} | |
struct ContentView_Previews: PreviewProvider { | |
static var previews: some View { | |
ContentView() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment