Skip to content

Instantly share code, notes, and snippets.

@agelessman
Last active May 29, 2020 11:29
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 agelessman/335914b2db480c5a343111a4a5bd4e36 to your computer and use it in GitHub Desktop.
Save agelessman/335914b2db480c5a343111a4a5bd4e36 to your computer and use it in GitHub Desktop.
//
// 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