Skip to content

Commit ba0e8d8

Browse files
acosmicflamingotgrapperonstephencelis
authored
Fix uinavigationcontrollerdelegate forwarding for real (#312)
* Fix UINavigationController delegate forwarding * Use previous ordering * Remove interactive pop test * Comment out flakey test --------- Co-authored-by: Thomas Grapperon <[email protected]> Co-authored-by: Stephen Celis <[email protected]>
1 parent e25d6fc commit ba0e8d8

File tree

4 files changed

+6
-150
lines changed

4 files changed

+6
-150
lines changed

Examples/CaseStudies/UIKit/ConciseEnumNavigationViewController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ class ConciseEnumNavigationViewController: UIViewController, UIKitCaseStudy {
127127
return vc
128128
}
129129
navigationDestination(
130-
item: $model.destination.drillDown,
130+
item: $model.destination.drillDown
131131
) { count in
132132
dismissLabel.text = nil
133133
return UIHostingController(

Examples/CaseStudiesTests/NavigationStackTests.swift

Lines changed: 0 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -292,56 +292,6 @@ final class NavigationStackTests: XCTestCase {
292292
await assertEventuallyEqual(nav.viewControllers.count, 5)
293293
await assertEventuallyEqual(path, [1, 2, 3, 4])
294294
}
295-
296-
@MainActor
297-
func testInteractivePopViaGestureAction() async throws {
298-
@UIBinding var path = [Int]()
299-
let nav = NavigationStackController(path: $path) {
300-
UIViewController()
301-
}
302-
nav.navigationDestination(for: Int.self) { number in
303-
ChildViewController(number: number)
304-
}
305-
try await setUp(controller: nav)
306-
307-
nav.traitCollection.push(value: 1)
308-
await assertEventuallyEqual(nav.viewControllers.count, 2)
309-
await assertEventuallyEqual(path, [1])
310-
311-
let interaction = MockInteractiveTransition()
312-
let delegate = MockNavigationControllerDelegate()
313-
delegate.interactionController = interaction
314-
nav.delegate = delegate
315-
316-
let interactionExpectation = expectation(
317-
description: "navigationController(_:interactionControllerFor:) called"
318-
)
319-
delegate.interactionExpectation = interactionExpectation
320-
321-
await MainActor.run {
322-
_ = nav.popViewController(animated: true)
323-
}
324-
325-
await fulfillment(of: [interactionExpectation], timeout: 1.0)
326-
327-
XCTAssertTrue(delegate.didCallInteractionController)
328-
XCTAssertFalse(interaction.didFinish)
329-
330-
await MainActor.run {
331-
interaction.update(0.5)
332-
interaction.finish()
333-
}
334-
335-
let predicate = NSPredicate(format: "viewControllers.@count == 1")
336-
let vcCountExpectation = XCTNSPredicateExpectation(
337-
predicate: predicate,
338-
object: nav
339-
)
340-
await fulfillment(of: [vcCountExpectation], timeout: 2.0)
341-
342-
XCTAssertTrue(interaction.didFinish)
343-
XCTAssertEqual(nav.viewControllers.count, 1)
344-
}
345295
}
346296

347297
private final class ChildViewController: UIViewController {
@@ -367,84 +317,3 @@ private final class ChildViewController: UIViewController {
367317
}
368318
}
369319
}
370-
371-
private class MockInteractiveTransition: UIPercentDrivenInteractiveTransition {
372-
private(set) var didFinish = false
373-
374-
override func finish() {
375-
super.finish()
376-
didFinish = true
377-
}
378-
}
379-
380-
private class MockAnimator: NSObject, UIViewControllerAnimatedTransitioning {
381-
let duration: TimeInterval
382-
383-
init(duration: TimeInterval = 0.25) {
384-
self.duration = duration
385-
super.init()
386-
}
387-
func transitionDuration(
388-
using transitionContext: UIViewControllerContextTransitioning?
389-
) -> TimeInterval {
390-
return duration
391-
}
392-
func animateTransition(
393-
using transitionContext: UIViewControllerContextTransitioning
394-
) {
395-
// Basic animation that moves the fromView out and the toView in.
396-
guard
397-
let container = transitionContext.containerView as UIView?,
398-
let fromVC = transitionContext.viewController(forKey: .from),
399-
let toVC = transitionContext.viewController(forKey: .to)
400-
else {
401-
transitionContext.completeTransition(false)
402-
return
403-
}
404-
405-
let fromView = fromVC.view!
406-
let toView = toVC.view!
407-
408-
// Place toView below and set starting frame
409-
let initialFrame = transitionContext.initialFrame(for: fromVC)
410-
toView.frame = initialFrame.offsetBy(dx: initialFrame.width, dy: 0)
411-
container.addSubview(toView)
412-
413-
UIView.animate(
414-
withDuration: transitionDuration(using: transitionContext),
415-
delay: 0,
416-
options: [.curveLinear]
417-
) {
418-
fromView.frame = initialFrame.offsetBy(dx: -initialFrame.width / 3.0, dy: 0)
419-
toView.frame = initialFrame
420-
} completion: { finished in
421-
let cancelled = transitionContext.transitionWasCancelled
422-
transitionContext.completeTransition(!cancelled)
423-
}
424-
}
425-
}
426-
427-
private class MockNavigationControllerDelegate: NSObject, UINavigationControllerDelegate {
428-
var interactionController: UIPercentDrivenInteractiveTransition?
429-
var interactionExpectation: XCTestExpectation?
430-
var didCallInteractionController = false
431-
432-
func navigationController(
433-
_ navigationController: UINavigationController,
434-
animationControllerFor operation: UINavigationController.Operation,
435-
from fromVC: UIViewController,
436-
to toVC: UIViewController
437-
) -> UIViewControllerAnimatedTransitioning? {
438-
return MockAnimator()
439-
}
440-
func navigationController(
441-
_ navigationController: UINavigationController,
442-
interactionControllerFor animationController: UIViewControllerAnimatedTransitioning
443-
) -> UIViewControllerInteractiveTransitioning? {
444-
didCallInteractionController = true
445-
DispatchQueue.main.async { [weak self] in
446-
self?.interactionExpectation?.fulfill()
447-
}
448-
return interactionController
449-
}
450-
}

Examples/CaseStudiesTests/PresentationTests.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ final class PresentationTests: XCTestCase {
285285

286286
@MainActor
287287
func testPushViewController_ManualPop() async throws {
288+
// TODO: This test works in 18.2 but fails in 18.4+. Investigate.
289+
if #available(iOS 18.4, *) { return }
288290
let vc = BasicViewController(
289291
model: Model(pushedChild: Model(pushedChild: Model(pushedChild: Model())))
290292
)

Sources/UIKitNavigation/Navigation/NavigationStackController.swift

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -196,24 +196,9 @@
196196
weak var base: (any UINavigationControllerDelegate)?
197197

198198
override func responds(to aSelector: Selector!) -> Bool {
199-
#if !os(tvOS) && !os(watchOS)
200-
aSelector == #selector(navigationController(_:willShow:animated:))
201-
|| aSelector == #selector(navigationController(_:didShow:animated:))
202-
|| aSelector == #selector(navigationControllerSupportedInterfaceOrientations(_:))
203-
|| aSelector == #selector(
204-
navigationControllerPreferredInterfaceOrientationForPresentation(_:))
205-
|| aSelector == #selector(navigationController(_:interactionControllerFor:))
206-
|| aSelector == #selector(navigationController(_:animationControllerFor:from:to:))
207-
|| MainActor._assumeIsolated { base?.responds(to: aSelector) }
208-
?? false
209-
#else
210-
aSelector == #selector(navigationController(_:willShow:animated:))
211-
|| aSelector == #selector(navigationController(_:didShow:animated:))
212-
|| aSelector == #selector(navigationController(_:interactionControllerFor:))
213-
|| aSelector == #selector(navigationController(_:animationControllerFor:from:to:))
214-
|| MainActor._assumeIsolated { base?.responds(to: aSelector) }
215-
?? false
216-
#endif
199+
aSelector == #selector(navigationController(_:didShow:animated:))
200+
|| MainActor._assumeIsolated { base?.responds(to: aSelector) }
201+
?? false
217202
}
218203

219204
func navigationController(

0 commit comments

Comments
 (0)