From 3261089bd234c076b3f051d8540db08ecbe9616a Mon Sep 17 00:00:00 2001 From: SungdooYoo Date: Thu, 17 Mar 2022 11:44:06 +0900 Subject: [PATCH 1/2] support accessibilityPerformEscape --- PanModal/View/PanContainerView.swift | 17 ++++++++ Tests/UIAccessiblityPerformEscapeTests.swift | 43 ++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 Tests/UIAccessiblityPerformEscapeTests.swift diff --git a/PanModal/View/PanContainerView.swift b/PanModal/View/PanContainerView.swift index f5c2892b..665a613f 100644 --- a/PanModal/View/PanContainerView.swift +++ b/PanModal/View/PanContainerView.swift @@ -15,10 +15,13 @@ import UIKit having to do those changes directly on the view */ class PanContainerView: UIView { + + private weak var presentedViewController: UIViewController? init(presentedView: UIView, frame: CGRect) { super.init(frame: frame) addSubview(presentedView) + presentedViewController = presentedView.parentViewController } @available(*, unavailable) @@ -26,6 +29,20 @@ class PanContainerView: UIView { fatalError("init(coder:) has not been implemented") } + override func accessibilityPerformEscape() -> Bool { + var shouldPerforEscape: Bool = true + if let panModalPresentable = presentedViewController as? PanModalPresentable { + shouldPerforEscape = panModalPresentable.allowsDragToDismiss || panModalPresentable.allowsTapToDismiss + presentedViewController?.dismiss(animated: true, completion: nil) + } + return shouldPerforEscape + } +} + +private extension UIResponder { + var parentViewController: UIViewController? { + return next as? UIViewController ?? next?.parentViewController + } } extension UIView { diff --git a/Tests/UIAccessiblityPerformEscapeTests.swift b/Tests/UIAccessiblityPerformEscapeTests.swift new file mode 100644 index 00000000..9502fc79 --- /dev/null +++ b/Tests/UIAccessiblityPerformEscapeTests.swift @@ -0,0 +1,43 @@ +// +// UIAccessiblityPerformEscapeTests.swift +// PanModalTests +// +// Created by Sungdoo on 2022/03/17. +// Copyright © 2022 Detail. All rights reserved. +// + +import XCTest +import PanModal + +class UIAccessiblityPerformEscapeTests: XCTestCase { + + class MockViewController: UIViewController, PanModalPresentable { + var panScrollable: UIScrollView? { return nil } + } + + func testAccessibilityPerformEscape() throws { + + let presenterViewController = UIApplication.shared.keyWindow?.rootViewController + let panModal: UIViewController & PanModalPresentable = MockViewController() + + presenterViewController?.presentPanModal(panModal) + XCTAssertNotNil(presenterViewController?.presentedViewController, "panModal should have been presented") + + let presentDidFisnish = XCTestExpectation() + let dismissDidFinish = XCTestExpectation() + + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + + let panContainerView = panModal.view.superview + presentDidFisnish.fulfill() + + panContainerView?.accessibilityPerformEscape() + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + XCTAssertNil(presenterViewController?.presentedViewController, "panModal should have been dismissed") + dismissDidFinish.fulfill() + } + } + + wait(for: [presentDidFisnish, dismissDidFinish], timeout: 10) + } +} From 77cdf1b6c36f3756dc478deab25c4c946b958a46 Mon Sep 17 00:00:00 2001 From: Sungdoo Yoo Date: Fri, 18 Mar 2022 09:23:30 +0900 Subject: [PATCH 2/2] fix/uiaccessibilityPerformEscape --- PanModal/View/PanContainerView.swift | 4 ++- PanModalDemo.xcodeproj/project.pbxproj | 4 +++ Tests/UIAccessiblityPerformEscapeTests.swift | 38 ++++++++++++++++++-- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/PanModal/View/PanContainerView.swift b/PanModal/View/PanContainerView.swift index 665a613f..06e0175f 100644 --- a/PanModal/View/PanContainerView.swift +++ b/PanModal/View/PanContainerView.swift @@ -33,7 +33,9 @@ class PanContainerView: UIView { var shouldPerforEscape: Bool = true if let panModalPresentable = presentedViewController as? PanModalPresentable { shouldPerforEscape = panModalPresentable.allowsDragToDismiss || panModalPresentable.allowsTapToDismiss - presentedViewController?.dismiss(animated: true, completion: nil) + if shouldPerforEscape { + presentedViewController?.dismiss(animated: true, completion: nil) + } } return shouldPerforEscape } diff --git a/PanModalDemo.xcodeproj/project.pbxproj b/PanModalDemo.xcodeproj/project.pbxproj index 0fe4e141..821e6f80 100644 --- a/PanModalDemo.xcodeproj/project.pbxproj +++ b/PanModalDemo.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 0800056627E406A200EF6459 /* UIAccessiblityPerformEscapeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0800056527E406A200EF6459 /* UIAccessiblityPerformEscapeTests.swift */; }; 0F2A2C552239C119003BDB2F /* PanModal.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2A2C532239C119003BDB2F /* PanModal.h */; settings = {ATTRIBUTES = (Public, ); }; }; 0F2A2C582239C119003BDB2F /* PanModal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0F2A2C512239C119003BDB2F /* PanModal.framework */; }; 0F2A2C592239C119003BDB2F /* PanModal.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 0F2A2C512239C119003BDB2F /* PanModal.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; @@ -90,6 +91,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0800056527E406A200EF6459 /* UIAccessiblityPerformEscapeTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIAccessiblityPerformEscapeTests.swift; sourceTree = ""; }; 0F2A2C512239C119003BDB2F /* PanModal.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PanModal.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 0F2A2C532239C119003BDB2F /* PanModal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PanModal.h; sourceTree = ""; }; 0F2A2C542239C119003BDB2F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -207,6 +209,7 @@ 743CABC52226171500634A5A /* Tests */ = { isa = PBXGroup; children = ( + 0800056527E406A200EF6459 /* UIAccessiblityPerformEscapeTests.swift */, 743CABC62226171500634A5A /* PanModalTests.swift */, 743CABC82226171500634A5A /* Info.plist */, ); @@ -552,6 +555,7 @@ buildActionMask = 2147483647; files = ( 743CABC72226171500634A5A /* PanModalTests.swift in Sources */, + 0800056627E406A200EF6459 /* UIAccessiblityPerformEscapeTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Tests/UIAccessiblityPerformEscapeTests.swift b/Tests/UIAccessiblityPerformEscapeTests.swift index 9502fc79..49a3143b 100644 --- a/Tests/UIAccessiblityPerformEscapeTests.swift +++ b/Tests/UIAccessiblityPerformEscapeTests.swift @@ -10,11 +10,17 @@ import XCTest import PanModal class UIAccessiblityPerformEscapeTests: XCTestCase { - + class MockViewController: UIViewController, PanModalPresentable { - var panScrollable: UIScrollView? { return nil } + var panScrollable: UIScrollView? { nil } } - + + class UnDismissablePanModalViewController: UIViewController, PanModalPresentable { + var panScrollable: UIScrollView? { nil } + var allowsTapToDismiss: Bool { false } + var allowsDragToDismiss: Bool { false } + } + func testAccessibilityPerformEscape() throws { let presenterViewController = UIApplication.shared.keyWindow?.rootViewController @@ -40,4 +46,30 @@ class UIAccessiblityPerformEscapeTests: XCTestCase { wait(for: [presentDidFisnish, dismissDidFinish], timeout: 10) } + + func testAccessibilityPerformEscapeOnDismissDisabledModal() throws { + + let presenterViewController = UIApplication.shared.keyWindow?.rootViewController + let panModal: UIViewController & PanModalPresentable = UnDismissablePanModalViewController() + + presenterViewController?.presentPanModal(panModal) + XCTAssertNotNil(presenterViewController?.presentedViewController, "panModal should have been presented") + + let presentDidFisnish = XCTestExpectation() + let dismissDidFinish = XCTestExpectation() + + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + + let panContainerView = panModal.view.superview + presentDidFisnish.fulfill() + + panContainerView?.accessibilityPerformEscape() + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + XCTAssertNotNil(presenterViewController?.presentedViewController, "panModal shouldn't have been dismissed") + dismissDidFinish.fulfill() + } + } + + wait(for: [presentDidFisnish, dismissDidFinish], timeout: 10) + } }