From 5be096052742f0e592bc8394704fbb098b66d7a3 Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Tue, 18 Aug 2020 20:57:57 +0530 Subject: [PATCH 01/11] Added Layout Constraints to 'view' of 'viewController' to match 'containerView' in 'push(viewController: contentAnimation: navigationBarAnimation:)' in 'JSNavigationController' --- .../Sources/JSNavigationController.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/JSNavigationController/Sources/JSNavigationController.swift b/JSNavigationController/Sources/JSNavigationController.swift index 419286f..016ceed 100644 --- a/JSNavigationController/Sources/JSNavigationController.swift +++ b/JSNavigationController/Sources/JSNavigationController.swift @@ -72,7 +72,14 @@ open class JSNavigationController: NSViewController, JSViewControllersStackManag } // Add the new view - contentView?.addSubview(viewController.view, positioned: .above, relativeTo: previousViewController?.view) + if let contentView = self.contentView + { + contentView.addSubview(viewController.view, positioned: .above, relativeTo: previousViewController?.view) + viewController.view.translatesAutoresizingMaskIntoConstraints = false + let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-[view]-|", options: .alignAllCenterX, metrics: nil, views: ["view" : viewController.view]) + let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-[view]-|", options: .alignAllCenterX, metrics: nil, views: ["view" : viewController.view]) + NSLayoutConstraint.activate(horizontalConstraints + verticalConstraints) + } // NavigationBar if let vc = viewController as? JSNavigationBarViewControllerProvider { From 2b543816539cdd8e04d61a2d7afb0fc070875513 Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Tue, 18 Aug 2020 21:10:04 +0530 Subject: [PATCH 02/11] Corrected Spacings in constraints of 'view' of 'viewController' in 'push(viewController: contentAnimation: navigationBarAnimation:)' in 'JSNavigationController' --- JSNavigationController/Sources/JSNavigationController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/JSNavigationController/Sources/JSNavigationController.swift b/JSNavigationController/Sources/JSNavigationController.swift index 016ceed..9d99acc 100644 --- a/JSNavigationController/Sources/JSNavigationController.swift +++ b/JSNavigationController/Sources/JSNavigationController.swift @@ -76,8 +76,8 @@ open class JSNavigationController: NSViewController, JSViewControllersStackManag { contentView.addSubview(viewController.view, positioned: .above, relativeTo: previousViewController?.view) viewController.view.translatesAutoresizingMaskIntoConstraints = false - let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-[view]-|", options: .alignAllCenterX, metrics: nil, views: ["view" : viewController.view]) - let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-[view]-|", options: .alignAllCenterX, metrics: nil, views: ["view" : viewController.view]) + let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: .alignAllCenterX, metrics: nil, views: ["view" : viewController.view]) + let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: .alignAllCenterX, metrics: nil, views: ["view" : viewController.view]) NSLayoutConstraint.activate(horizontalConstraints + verticalConstraints) } From 0dbd8934f3c978807556521fcc387a84fec6207b Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Wed, 19 Aug 2020 19:59:29 +0530 Subject: [PATCH 03/11] Made the following changes to 'JSViewControllersStackManager': 1. Code formatting 2. Added 'animationDuration' property 3. Added 'animation(for: from: to:)' 3. Added 'clampViewToContentView(_:)' 4. Other code enhancements --- .../JSViewControllersStackManager.swift | 215 +++++++++++------- 1 file changed, 132 insertions(+), 83 deletions(-) diff --git a/JSNavigationController/Sources/JSViewControllersStackManager.swift b/JSNavigationController/Sources/JSViewControllersStackManager.swift index c95b143..465ee38 100644 --- a/JSNavigationController/Sources/JSViewControllersStackManager.swift +++ b/JSNavigationController/Sources/JSViewControllersStackManager.swift @@ -95,153 +95,202 @@ public protocol JSViewControllersStackManager: class { } // MARK: - -public extension JSViewControllersStackManager { - var topViewController: NSViewController? { - return viewControllers.last +public extension JSViewControllersStackManager +{ + // MARK: - Properties + + var topViewController: NSViewController? + { + return self.viewControllers.last + } + var previousViewController: NSViewController? + { + guard self.viewControllers.count > 1 else { return nil } + return self.viewControllers[self.viewControllers.count - 2] } - var previousViewController: NSViewController? { - guard viewControllers.count > 1 else { return nil } - return viewControllers[viewControllers.count - 2] + + var animationDuration: TimeInterval + { + return 0.25 + } + + // MARK: - Methods + + func clampContentView(to view: NSView) + { + guard view.superview == self.contentView else { return } + view.translatesAutoresizingMaskIntoConstraints = false + let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: .alignAllCenterX, metrics: nil, views: ["view" : view]) + let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: .alignAllCenterY, metrics: nil, views: ["view" : view]) + NSLayoutConstraint.activate(horizontalConstraints + verticalConstraints) + } + + func animation(for keypath: String, from: Any, to: Any) -> CAAnimation + { + let animation = CABasicAnimation(keyPath: keypath) + animation.fromValue = from + animation.toValue = to + animation.duration = self.animationDuration + animation.timingFunction = .init(name: .easeOut) + animation.fillMode = .forwards + animation.isRemovedOnCompletion = false + return animation } - func set(viewControllers: [NSViewController], animated: Bool) { + func set(viewControllers: [NSViewController], animated: Bool) + { guard !viewControllers.isEmpty else { return } - if animated { - if let lastViewController = viewControllers.last { - if self.viewControllers.contains(lastViewController) && lastViewController != topViewController { - pop(toViewController: lastViewController, animated: true) - } else { - push(viewController: lastViewController, animated: true) + if animated + { + if let lastViewController = viewControllers.last + { + if self.viewControllers.contains(lastViewController), + lastViewController != self.topViewController + { + self.pop(toViewController: lastViewController, animated: true) + } + else + { + self.push(viewController: lastViewController, animated: true) } } - } else { - if let lastViewController = viewControllers.last { - push(viewController: lastViewController, animated: false) + } + else + { + if let lastViewController = viewControllers.last + { + self.push(viewController: lastViewController, animated: false) } self.viewControllers = viewControllers } } - func push(viewController: NSViewController, animation: AnimationBlock?) { - guard !Set(viewControllers).contains(viewController) else { return } - - viewControllers.append(viewController) + func push(viewController: NSViewController, animation: AnimationBlock?) + { + guard !self.viewControllers.contains(viewController) else { return } + self.viewControllers.append(viewController) // Remove old view - if let previousViewController = previousViewController , animation == nil { + if let previousViewController = self.previousViewController, animation == nil + { previousViewController.view.removeFromSuperview() } // Add the new view - contentView?.addSubview(viewController.view, positioned: .above, relativeTo: previousViewController?.view) + self.contentView?.addSubview(viewController.view, positioned: .above, relativeTo: self.previousViewController?.view) + self.clampContentView(to: viewController.view) - if let animation = animation { + if let animation = animation + { CATransaction.begin() - CATransaction.setCompletionBlock { [weak self] in - self?.previousViewController?.view.removeFromSuperview() - self?.previousViewController?.view.layer?.removeAllAnimations() + CATransaction.setCompletionBlock + { + [unowned self] in + self.previousViewController?.view.removeFromSuperview() + self.previousViewController?.view.layer?.removeAllAnimations() } - animatePush(animation) + self.animatePush(animation) CATransaction.commit() } } - func push(viewController: NSViewController, animated: Bool) { - if animated { - push(viewController: viewController, animation: defaultPushAnimation()) - } else { - push(viewController: viewController, animation: nil) - } + func push(viewController: NSViewController, animated: Bool) + { + self.push(viewController: viewController, animation: animated ? defaultPushAnimation() : nil) } // MARK: - Popping - func popViewController(animation: AnimationBlock?) { - guard let previousViewController = previousViewController else { return } // You can't pop the root view controller - pop(toViewController: previousViewController, animation: animation) + func popViewController(animation: AnimationBlock?) + { + guard let previousViewController = self.previousViewController else { return } // You can't pop the root view controller + self.pop(toViewController: previousViewController, animation: animation) } - func popViewController(animated: Bool) { - if animated { - popViewController(animation: defaultPopAnimation()) - } else { - popViewController(animation: nil) - } + func popViewController(animated: Bool) + { + self.popViewController(animation: animated ? self.defaultPopAnimation() : nil) } - func pop(toViewController viewController: NSViewController, animation: AnimationBlock?) { - guard Set(viewControllers).contains(viewController) else { return } - guard let rootViewController = viewControllers.first else { return } - guard let topViewController = topViewController else { return } + func pop(toViewController viewController: NSViewController, animation: AnimationBlock?) + { + guard self.viewControllers.contains(viewController) else { return } + guard let rootViewController = self.viewControllers.first, + let topViewController = self.topViewController else { return } guard topViewController != rootViewController else { return } - let viewControllerPosition = viewControllers.firstIndex(of: viewController) + let viewControllerPosition = self.viewControllers.firstIndex(of: viewController) // Add the new view - contentView?.addSubview(viewController.view, positioned: .below, relativeTo: topViewController.view) + self.contentView?.addSubview(viewController.view, positioned: .below, relativeTo: topViewController.view) + self.clampContentView(to: viewController.view) - if let animation = animation { + if let animation = animation + { CATransaction.begin() - CATransaction.setCompletionBlock { [unowned self] in + CATransaction.setCompletionBlock + { + [unowned self] in self.topViewController?.view.removeFromSuperview() self.topViewController?.view.layer?.removeAllAnimations() let range = (viewControllerPosition! + 1).. Date: Wed, 19 Aug 2020 20:01:01 +0530 Subject: [PATCH 04/11] Made the following changes to 'JSNavigationBarController': 1. Code enhancements 2. Code formatting --- .../Sources/JSNavigationBarController.swift | 117 +++++------------- 1 file changed, 34 insertions(+), 83 deletions(-) diff --git a/JSNavigationController/Sources/JSNavigationBarController.swift b/JSNavigationController/Sources/JSNavigationBarController.swift index 5697824..8169dc1 100644 --- a/JSNavigationController/Sources/JSNavigationBarController.swift +++ b/JSNavigationController/Sources/JSNavigationBarController.swift @@ -8,97 +8,48 @@ import AppKit -open class JSNavigationBarController: JSViewControllersStackManager { +open class JSNavigationBarController: JSViewControllersStackManager +{ + // MARK: - Properties open var viewControllers: [NSViewController] = [] open weak var contentView: NSView? // MARK: - Initializers - public init(view: NSView) { - contentView = view + public init(view: NSView) + { + self.contentView = view } // MARK: - Default animations - open func defaultPushAnimation() -> AnimationBlock { - return { [weak self] (_, _) in - let containerViewBounds = self?.contentView?.bounds ?? .zero - - let slideToLeftTransform = CATransform3DMakeTranslation(-containerViewBounds.width / 2, 0, 0) - let slideToLeftAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform)) - slideToLeftAnimation.fromValue = NSValue(caTransform3D: CATransform3DIdentity) - slideToLeftAnimation.toValue = NSValue(caTransform3D: slideToLeftTransform) - slideToLeftAnimation.duration = 0.25 - slideToLeftAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - slideToLeftAnimation.fillMode = CAMediaTimingFillMode.forwards - slideToLeftAnimation.isRemovedOnCompletion = false - - let slideFromRightTransform = CATransform3DMakeTranslation(containerViewBounds.width / 2, 0, 0) - let slideFromRightAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform)) - slideFromRightAnimation.fromValue = NSValue(caTransform3D: slideFromRightTransform) - slideFromRightAnimation.toValue = NSValue(caTransform3D: CATransform3DIdentity) - slideFromRightAnimation.duration = 0.25 - slideFromRightAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - slideFromRightAnimation.fillMode = CAMediaTimingFillMode.forwards - slideFromRightAnimation.isRemovedOnCompletion = false - - let fadeInAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity)) - fadeInAnimation.fromValue = 0.0 - fadeInAnimation.toValue = 1.0 - fadeInAnimation.duration = 0.25 - fadeInAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - fadeInAnimation.fillMode = CAMediaTimingFillMode.forwards - fadeInAnimation.isRemovedOnCompletion = false - - let fadeOutAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity)) - fadeOutAnimation.fromValue = 1.0 - fadeOutAnimation.toValue = 0.0 - fadeOutAnimation.duration = 0.25 - fadeOutAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - fadeOutAnimation.fillMode = CAMediaTimingFillMode.forwards - fadeOutAnimation.isRemovedOnCompletion = false - - return ([slideToLeftAnimation, fadeOutAnimation], [slideFromRightAnimation, fadeInAnimation]) - } + + open func defaultPushAnimation() -> AnimationBlock + { + return + { + [unowned self] (_, _) in + + let containerViewBounds = self.contentView?.bounds ?? .zero + let slideToLeftAnimation = self.animation(for: #keyPath(CALayer.transform), from: CATransform3DIdentity, to: CATransform3DMakeTranslation(-containerViewBounds.width / 2, 0, 0)) + let slideFromRightAnimation = self.animation(for: #keyPath(CALayer.transform), from: CATransform3DMakeTranslation(containerViewBounds.width / 2, 0, 0), to: CATransform3DIdentity) + let fadeInAnimation = self.animation(for: #keyPath(CALayer.opacity), from: 0, to: 1) + let fadeOutAnimation = self.animation(for: #keyPath(CALayer.opacity), from: 1, to: 0) + return ([slideToLeftAnimation, fadeOutAnimation], [slideFromRightAnimation, fadeInAnimation]) + } } - open func defaultPopAnimation() -> AnimationBlock { - return { [weak self] (_, _) in - let containerViewBounds = self?.contentView?.bounds ?? .zero - - let slideToRightTransform = CATransform3DMakeTranslation(-containerViewBounds.width / 2, 0, 0) - let slideToRightAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform)) - slideToRightAnimation.fromValue = NSValue(caTransform3D: slideToRightTransform) - slideToRightAnimation.toValue = NSValue(caTransform3D: CATransform3DIdentity) - slideToRightAnimation.duration = 0.25 - slideToRightAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - slideToRightAnimation.fillMode = CAMediaTimingFillMode.forwards - slideToRightAnimation.isRemovedOnCompletion = false - - let slideToRightFromCenterTransform = CATransform3DMakeTranslation(containerViewBounds.width / 2, 0, 0) - let slideToRightFromCenterAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform)) - slideToRightFromCenterAnimation.fromValue = NSValue(caTransform3D: CATransform3DIdentity) - slideToRightFromCenterAnimation.toValue = NSValue(caTransform3D: slideToRightFromCenterTransform) - slideToRightFromCenterAnimation.duration = 0.35 - slideToRightFromCenterAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - slideToRightFromCenterAnimation.fillMode = CAMediaTimingFillMode.forwards - slideToRightFromCenterAnimation.isRemovedOnCompletion = false - - let fadeInAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity)) - fadeInAnimation.fromValue = 0.0 - fadeInAnimation.toValue = 1.0 - fadeInAnimation.duration = 0.25 - fadeInAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - fadeInAnimation.fillMode = CAMediaTimingFillMode.forwards - fadeInAnimation.isRemovedOnCompletion = false - - let fadeOutAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity)) - fadeOutAnimation.fromValue = 1.0 - fadeOutAnimation.toValue = 0.0 - fadeOutAnimation.duration = 0.25 - fadeOutAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - fadeOutAnimation.fillMode = CAMediaTimingFillMode.forwards - fadeOutAnimation.isRemovedOnCompletion = false - - return ([slideToRightFromCenterAnimation, fadeOutAnimation], [slideToRightAnimation, fadeInAnimation]) - } + open func defaultPopAnimation() -> AnimationBlock + { + return + { + [unowned self] (_, _) in + + let containerViewBounds = self.contentView?.bounds ?? .zero + let slideToRightAnimation = self.animation(for: #keyPath(CALayer.transform), from: CATransform3DMakeTranslation(-containerViewBounds.width / 2, 0, 0), to: CATransform3DIdentity) + let slideToRightFromCenterAnimation = self.animation(for: #keyPath(CALayer.transform), from: CATransform3DIdentity, to: CATransform3DMakeTranslation(containerViewBounds.width / 2, 0, 0)) + let fadeInAnimation = self.animation(for: #keyPath(CALayer.opacity), from: 0, to: 1) + let fadeOutAnimation = self.animation(for: #keyPath(CALayer.opacity), from: 1, to: 0) + + return ([slideToRightFromCenterAnimation, fadeOutAnimation], [slideToRightAnimation, fadeInAnimation]) + } } } From 70aa235ba73e032e64cf57c12f08dc6b489baeb6 Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Wed, 19 Aug 2020 20:07:34 +0530 Subject: [PATCH 05/11] Made the following changes to 'JSNavigationController': 1. Code enhancements 2. Code formatting 3. Added 'RootViewControllerSegueIdentifier' 4. Clamping of pushed 'viewController' in 'push(viewController: contentAnimation: navigationBarAnimation:)' 5. Clamping of popped 'viewController' in 'pop(toViewController: contentAnimation: navigationBarAnimation:)' 6. --- .../Sources/JSNavigationController.swift | 349 ++++++++---------- 1 file changed, 162 insertions(+), 187 deletions(-) diff --git a/JSNavigationController/Sources/JSNavigationController.swift b/JSNavigationController/Sources/JSNavigationController.swift index 9d99acc..edfb4aa 100644 --- a/JSNavigationController/Sources/JSNavigationController.swift +++ b/JSNavigationController/Sources/JSNavigationController.swift @@ -8,277 +8,252 @@ import AppKit -open class JSNavigationController: NSViewController, JSViewControllersStackManager { +open class JSNavigationController: NSViewController, JSViewControllersStackManager +{ + // MARK: - IB Outlets @IBOutlet weak open var contentView: NSView? @IBOutlet open var navigationBarView: NSView? + + // MARK: - Properties + static let RootViewControllerSegueIdentifier = NSStoryboardSegue.Identifier("Root View Controller") open var viewControllers: [NSViewController] = [] open var navigationBarController: JSNavigationBarController? open weak var delegate: JSNavigationControllerDelegate? - // MARK: - Creating Navigation Controllers - public init(rootViewController: NSViewController, contentView: NSView, navigationBarView: NSView) { + // MARK: - Initializers + + public init(rootViewController: NSViewController, contentView: NSView, navigationBarView: NSView) + { self.contentView = contentView - navigationBarController = JSNavigationBarController(view: navigationBarView) + self.navigationBarController = JSNavigationBarController(view: navigationBarView) super.init(nibName: nil, bundle: nil) - push(viewController: rootViewController, animated: false) + self.push(viewController: rootViewController, animated: false) } - public init(viewControllers: [NSViewController], contentView: NSView, navigationBarView: NSView) { + public init(viewControllers: [NSViewController], contentView: NSView, navigationBarView: NSView) + { self.contentView = contentView - navigationBarController = JSNavigationBarController(view: navigationBarView) + self.navigationBarController = JSNavigationBarController(view: navigationBarView) super.init(nibName: nil, bundle: nil) - set(viewControllers: viewControllers, animated: false) + self.set(viewControllers: viewControllers, animated: false) } - required public init?(coder: NSCoder) { + required public init?(coder: NSCoder) + { super.init(coder: coder) } - - // MARK: - View Lifecycle - open override func loadView() { - if nibName != nil { + + // MARK: - Methods + + // MARK: Animations + + open func defaultPushAnimation() -> AnimationBlock + { + return + { + [unowned self] (_, _) in + + let containerViewBounds = self.contentView?.bounds ?? .zero + let slideToLeftAnimation = self.animation(for: #keyPath(CALayer.transform), from: CATransform3DIdentity, to: CATransform3DMakeTranslation(-containerViewBounds.width / 2, 0, 0)) + let slideFromRightAnimation = self.animation(for: #keyPath(CALayer.transform), from: CATransform3DMakeTranslation(containerViewBounds.width, 0, 0), to: CATransform3DIdentity) + return ([slideToLeftAnimation], [slideFromRightAnimation]) + } + } + + open func defaultPopAnimation() -> AnimationBlock + { + return + { + [unowned self] (_, _) in + + let containerViewBounds = self.contentView?.bounds ?? .zero + let slideToRightAnimation = self.animation(for: #keyPath(CALayer.transform), from: CATransform3DMakeTranslation(-containerViewBounds.width / 2, 0, 0), to: CATransform3DIdentity) + let slideToRightFromCenterAnimation = self.animation(for: #keyPath(CALayer.transform), from: CATransform3DIdentity, to: CATransform3DMakeTranslation(containerViewBounds.width, 0, 0)) + + return ([slideToRightFromCenterAnimation], [slideToRightAnimation]) + } + } + + + // MARK: View Lifecycle + + open override func loadView() + { + if let _ = self.nibName + { super.loadView() - } else { - view = NSView(frame: .zero) + } + else + { + self.view = NSView(frame: .zero) } } - open override func viewDidAppear() { + open override func viewDidAppear() + { super.viewDidAppear() - guard nibName != nil else { return } - guard let segues = value(forKey: "segueTemplates") as? [NSObject] else { return } // Undocumented + guard let _ = nibName else { return } - if let navigationBarView = navigationBarView { - navigationBarController = JSNavigationBarController(view: navigationBarView) - } - - for segue in segues { - if let id = segue.value(forKey: "identifier") as? String { - performSegue(withIdentifier: id, sender: self) - } + if let navigationBarView = self.navigationBarView + { + self.navigationBarController = JSNavigationBarController(view: navigationBarView) } + self.performSegue(withIdentifier: type(of: self).RootViewControllerSegueIdentifier, sender: nil) } - // MARK: - Pushing - open func push(viewController: NSViewController, contentAnimation: AnimationBlock?, navigationBarAnimation: AnimationBlock?) { - guard !Set(viewControllers).contains(viewController) else { return } - - viewControllers.append(viewController) - delegate?.navigationController(self, willShowViewController: viewController, animated: (contentAnimation != nil)) + // MARK: Pushing + + open func push(viewController: NSViewController, contentAnimation: AnimationBlock?, navigationBarAnimation: AnimationBlock?) + { + guard !self.viewControllers.contains(viewController) else { return } + self.viewControllers.append(viewController) + self.delegate?.navigationController(self, willShowViewController: viewController, animated: (contentAnimation != nil)) // Remove old view - if let previousViewController = previousViewController , contentAnimation == nil { + if let previousViewController = self.previousViewController, contentAnimation == nil + { previousViewController.view.removeFromSuperview() } // Add the new view - if let contentView = self.contentView - { - contentView.addSubview(viewController.view, positioned: .above, relativeTo: previousViewController?.view) - viewController.view.translatesAutoresizingMaskIntoConstraints = false - let horizontalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: .alignAllCenterX, metrics: nil, views: ["view" : viewController.view]) - let verticalConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: .alignAllCenterX, metrics: nil, views: ["view" : viewController.view]) - NSLayoutConstraint.activate(horizontalConstraints + verticalConstraints) - } + self.contentView?.addSubview(viewController.view, positioned: .above, relativeTo: self.previousViewController?.view) + self.clampContentView(to: viewController.view) // NavigationBar - if let vc = viewController as? JSNavigationBarViewControllerProvider { + if let vc = viewController as? JSNavigationBarViewControllerProvider + { vc.navigationController = self - navigationBarController?.push(viewController: vc.navigationBarViewController(), animation: navigationBarAnimation) - } else { - navigationBarController?.push(viewController: EmptyViewController(), animation: navigationBarAnimation) + self.navigationBarController?.push(viewController: vc.navigationBarViewController(), animation: navigationBarAnimation) + } + else + { + self.navigationBarController?.push(viewController: EmptyViewController(), animation: navigationBarAnimation) } - if let contentAnimation = contentAnimation { + if let contentAnimation = contentAnimation + { CATransaction.begin() - CATransaction.setCompletionBlock { [weak self] in - self?.previousViewController?.view.removeFromSuperview() - self?.previousViewController?.view.layer?.removeAllAnimations() - self?.delegate?.navigationController(self!, didShowViewController: viewController, animated: true) + CATransaction.setCompletionBlock + { + [unowned self] in + self.previousViewController?.view.removeFromSuperview() + self.previousViewController?.view.layer?.removeAllAnimations() + self.delegate?.navigationController(self, didShowViewController: viewController, animated: true) } - animatePush(contentAnimation) + self.animatePush(contentAnimation) CATransaction.commit() - } else { - delegate?.navigationController(self, didShowViewController: viewController, animated: false) + } + else + { + self.delegate?.navigationController(self, didShowViewController: viewController, animated: false) } } - open func push(viewController: NSViewController, animation: AnimationBlock?) { - let navBarAnimation: AnimationBlock? = animation != nil ? navigationBarController?.defaultPushAnimation() : nil - push(viewController: viewController, contentAnimation: animation, navigationBarAnimation: navBarAnimation) - } - - open func push(viewController: NSViewController, animated: Bool) { - if animated { - push(viewController: viewController, animation: defaultPushAnimation()) - } else { - push(viewController: viewController, animation: nil) - } + open func push(viewController: NSViewController, animated: Bool = true) + { + let contentAnimation = animated ? self.defaultPushAnimation() : nil + let navigationBarAnimation = animated ? self.navigationBarController?.defaultPushAnimation() : nil + self.push(viewController: viewController, contentAnimation: contentAnimation, navigationBarAnimation: navigationBarAnimation) } - // MARK: - Popping - open func pop(toViewController viewController: NSViewController, contentAnimation: AnimationBlock?, navigationBarAnimation: AnimationBlock?) { - guard Set(viewControllers).contains(viewController) else { return } - guard let rootViewController = viewControllers.first else { return } - guard let topViewController = topViewController else { return } + // MARK: Popping + + open func pop(toViewController viewController: NSViewController, contentAnimation: AnimationBlock?, navigationBarAnimation: AnimationBlock?) + { + guard self.viewControllers.contains(viewController) else { return } + guard let rootViewController = self.viewControllers.first else { return } + guard let topViewController = self.topViewController else { return } guard topViewController != rootViewController else { return } - delegate?.navigationController(self, willShowViewController: viewController, animated: (contentAnimation != nil)) + self.delegate?.navigationController(self, willShowViewController: viewController, animated: (contentAnimation != nil)) - let viewControllerPosition = viewControllers.firstIndex(of: viewController) + let viewControllerPosition = self.viewControllers.firstIndex(of: viewController) // Add the new view - contentView?.addSubview(viewController.view, positioned: .below, relativeTo: topViewController.view) + self.contentView?.addSubview(viewController.view, positioned: .below, relativeTo: topViewController.view) + self.clampContentView(to: viewController.view) // NavigationBar - if let vc = viewController as? JSNavigationBarViewControllerProvider { - navigationBarController?.pop(toViewController: vc.navigationBarViewController(), animation: navigationBarAnimation) + if let vc = viewController as? JSNavigationBarViewControllerProvider + { + self.navigationBarController?.pop(toViewController: vc.navigationBarViewController(), animation: navigationBarAnimation) } - if let contentAnimation = contentAnimation { + if let contentAnimation = contentAnimation + { CATransaction.begin() - CATransaction.setCompletionBlock { [unowned self] in + CATransaction.setCompletionBlock + { + [unowned self] in self.topViewController?.view.removeFromSuperview() self.topViewController?.view.layer?.removeAllAnimations() let range = (viewControllerPosition! + 1).. AnimationBlock { - return { [weak self] (_, _) in - let containerViewBounds = self?.contentView?.bounds ?? .zero - - let slideToLeftTransform = CATransform3DMakeTranslation(-containerViewBounds.width / 2, 0, 0) - let slideToLeftAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform)) - slideToLeftAnimation.fromValue = NSValue(caTransform3D: CATransform3DIdentity) - slideToLeftAnimation.toValue = NSValue(caTransform3D: slideToLeftTransform) - slideToLeftAnimation.duration = 0.25 - slideToLeftAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - slideToLeftAnimation.fillMode = CAMediaTimingFillMode.forwards - slideToLeftAnimation.isRemovedOnCompletion = false - - let slideFromRightTransform = CATransform3DMakeTranslation(containerViewBounds.width, 0, 0) - let slideFromRightAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform)) - slideFromRightAnimation.fromValue = NSValue(caTransform3D: slideFromRightTransform) - slideFromRightAnimation.toValue = NSValue(caTransform3D: CATransform3DIdentity) - slideFromRightAnimation.duration = 0.25 - slideFromRightAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - slideFromRightAnimation.fillMode = CAMediaTimingFillMode.forwards - slideFromRightAnimation.isRemovedOnCompletion = false - - return ([slideToLeftAnimation], [slideFromRightAnimation]) - } - } - - open func defaultPopAnimation() -> AnimationBlock { - return { [weak self] (_, _) in - let containerViewBounds = self?.contentView?.bounds ?? .zero - - let slideToRightTransform = CATransform3DMakeTranslation(-containerViewBounds.width / 2, 0, 0) - let slideToRightAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform)) - slideToRightAnimation.fromValue = NSValue(caTransform3D: slideToRightTransform) - slideToRightAnimation.toValue = NSValue(caTransform3D: CATransform3DIdentity) - slideToRightAnimation.duration = 0.25 - slideToRightAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - slideToRightAnimation.fillMode = CAMediaTimingFillMode.forwards - slideToRightAnimation.isRemovedOnCompletion = false - - let slideToRightFromCenterTransform = CATransform3DMakeTranslation(containerViewBounds.width, 0, 0) - let slideToRightFromCenterAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform)) - slideToRightFromCenterAnimation.fromValue = NSValue(caTransform3D: CATransform3DIdentity) - slideToRightFromCenterAnimation.toValue = NSValue(caTransform3D: slideToRightFromCenterTransform) - slideToRightFromCenterAnimation.duration = 0.25 - slideToRightFromCenterAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - slideToRightFromCenterAnimation.fillMode = CAMediaTimingFillMode.forwards - slideToRightFromCenterAnimation.isRemovedOnCompletion = false - - return ([slideToRightFromCenterAnimation], [slideToRightAnimation]) - } - } - - // MARK: - Storyboard - open override func prepare(for segue: NSStoryboardSegue, sender: Any?) { - guard segue.identifier == "rootViewController" else { return } - guard let destinationController = segue.destinationController as? NSViewController else { return } - - push(viewController: destinationController, animated: false) + open func popToRootViewController(animated: Bool) + { + let contentAnimation = animated ? self.defaultPopAnimation() : nil + let navigationBarAnimation = animated ? self.navigationBarController?.defaultPopAnimation() : nil + self.popToRootViewController(contentAnimation: contentAnimation, navigationBarAnimation: navigationBarAnimation) } } // MARK: - -private class EmptyViewController: NSViewController { - init() { +private class EmptyViewController: NSViewController +{ + init() + { super.init(nibName: nil, bundle: nil) } - required init?(coder: NSCoder) { + required init?(coder: NSCoder) + { fatalError("\(#function) has not been implemented") } - fileprivate override func loadView() { - view = NSView(frame: .zero) + fileprivate override func loadView() + { + self.view = NSView(frame: .zero) } } From 766b40fadf71e6a9f4a110d8816fa1a011c97b11 Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Wed, 19 Aug 2020 20:08:46 +0530 Subject: [PATCH 06/11] Made the following changes to 'JSViewController' 1. Code enhancements 2. Code formatting 3. Added 'NavigationBarSegueIdentifier' 4. Performing of Segue 'NavigationBarSegueIdentifier' in viewDidLoad() --- .../Sources/JSViewController.swift | 58 +++++-------------- 1 file changed, 14 insertions(+), 44 deletions(-) diff --git a/JSNavigationController/Sources/JSViewController.swift b/JSNavigationController/Sources/JSViewController.swift index 85afddd..432f53a 100644 --- a/JSNavigationController/Sources/JSViewController.swift +++ b/JSNavigationController/Sources/JSViewController.swift @@ -8,55 +8,25 @@ import AppKit -open class JSViewController: NSViewController, JSNavigationBarViewControllerProvider { - - private static let navigationControllerPushIdentifier = "navigationControllerPush" - private static let navigationBarViewControllerIdentifier = "navigationBarViewController" - - open private(set) var destinationViewController: NSViewController? - open private(set) var destinationViewControllers: [String: NSViewController] = [:] +open class JSViewController: NSViewController, JSNavigationBarViewControllerProvider +{ + // MARK: - Properties + + static let NavigationBarSegueIdentifier = "Navigation Bar" open var navigationBarVC: NSViewController? open weak var navigationController: JSNavigationController? - - open func navigationBarViewController() -> NSViewController { - guard let navigationBarVC = navigationBarVC else { fatalError("You must set the navigationBar view controller") } + open func navigationBarViewController() -> NSViewController + { + guard let navigationBarVC = self.navigationBarVC else { fatalError("You must set the navigationBar view controller") } return navigationBarVC } // MARK: - View Lifecycle - open override func awakeFromNib() { - if type(of: self).instancesRespond(to: #selector(NSViewController.awakeFromNib)) { - super.awakeFromNib() - } - setupSegues() - } - - // MARK: - Segues - private func setupSegues() { - guard let segues = value(forKey: "segueTemplates") as? [NSObject] else { return } - for segue in segues { - if let id = segue.value(forKey: "identifier") as? String { - performSegue(withIdentifier: id, sender: self) - } - } - } - - open override func prepare(for segue: NSStoryboardSegue, sender: Any?) { - guard let segueIdentifier = segue.identifier else { return } - - switch segueIdentifier { - case JSViewController.navigationBarViewControllerIdentifier: - navigationBarVC = segue.destinationController as? NSViewController - default: - if segueIdentifier.contains(JSViewController.navigationControllerPushIdentifier) { - if segueIdentifier.count > JSViewController.navigationControllerPushIdentifier.count && segueIdentifier.contains("#") { - if let key = segueIdentifier.split(separator: "#").map({ String($0) }).last { - destinationViewControllers[key] = segue.destinationController as? NSViewController - } - } else { - destinationViewController = segue.destinationController as? NSViewController - } - } - } + + open override func viewDidLoad() + { + super.viewDidLoad() + guard let _ = self.nibName else { return } + self.performSegue(withIdentifier: type(of: self).NavigationBarSegueIdentifier, sender: nil) } } From 3b8fddb2aa00a17dccd33bf68c46e26518f988e1 Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Wed, 19 Aug 2020 20:10:07 +0530 Subject: [PATCH 07/11] Renamed 'JSNavigationControllerSegue.swift' to 'JSSegues.swift' 1. Added 'JSRootViewControllerSegue' 2. Added 'JSNavigationBarSegue' 3. Added 'JSPushSegue' --- .../project.pbxproj | 8 +-- .../Sources/JSNavigationControllerSegue.swift | 15 ----- JSNavigationController/Sources/JSSegues.swift | 63 +++++++++++++++++++ 3 files changed, 67 insertions(+), 19 deletions(-) delete mode 100644 JSNavigationController/Sources/JSNavigationControllerSegue.swift create mode 100644 JSNavigationController/Sources/JSSegues.swift diff --git a/JSNavigationController.xcodeproj/project.pbxproj b/JSNavigationController.xcodeproj/project.pbxproj index 2aa462f..f9733fc 100644 --- a/JSNavigationController.xcodeproj/project.pbxproj +++ b/JSNavigationController.xcodeproj/project.pbxproj @@ -17,7 +17,7 @@ F67D71CC1CF5E1FA003F8B91 /* JSNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F67D71C81CF5E1FA003F8B91 /* JSNavigationController.swift */; }; F67D71CD1CF5E1FA003F8B91 /* JSViewControllersStackManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F67D71C91CF5E1FA003F8B91 /* JSViewControllersStackManager.swift */; }; F6E5D0B01CF88C4C000874A3 /* JSNavigationControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6E5D0AF1CF88C4C000874A3 /* JSNavigationControllerDelegate.swift */; }; - F6ED5F5F1CFF488300CF7222 /* JSNavigationControllerSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6ED5F5E1CFF488300CF7222 /* JSNavigationControllerSegue.swift */; }; + F6ED5F5F1CFF488300CF7222 /* JSSegues.swift in Sources */ = {isa = PBXBuildFile; fileRef = F6ED5F5E1CFF488300CF7222 /* JSSegues.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -44,7 +44,7 @@ F67D71C81CF5E1FA003F8B91 /* JSNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSNavigationController.swift; path = Sources/JSNavigationController.swift; sourceTree = ""; }; F67D71C91CF5E1FA003F8B91 /* JSViewControllersStackManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSViewControllersStackManager.swift; path = Sources/JSViewControllersStackManager.swift; sourceTree = ""; }; F6E5D0AF1CF88C4C000874A3 /* JSNavigationControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSNavigationControllerDelegate.swift; path = Sources/JSNavigationControllerDelegate.swift; sourceTree = ""; }; - F6ED5F5E1CFF488300CF7222 /* JSNavigationControllerSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSNavigationControllerSegue.swift; path = Sources/JSNavigationControllerSegue.swift; sourceTree = ""; }; + F6ED5F5E1CFF488300CF7222 /* JSSegues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSSegues.swift; path = Sources/JSSegues.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -112,7 +112,7 @@ F67D71C61CF5E1FA003F8B91 /* JSNavigationBarController.swift */, F67D71C71CF5E1FA003F8B91 /* JSNavigationBarViewControllerProvider.swift */, F67D71C91CF5E1FA003F8B91 /* JSViewControllersStackManager.swift */, - F6ED5F5E1CFF488300CF7222 /* JSNavigationControllerSegue.swift */, + F6ED5F5E1CFF488300CF7222 /* JSSegues.swift */, F655C1631D00ABE3005208A1 /* JSViewController.swift */, ); name = Sources; @@ -235,7 +235,7 @@ F67D71CD1CF5E1FA003F8B91 /* JSViewControllersStackManager.swift in Sources */, F67D71CC1CF5E1FA003F8B91 /* JSNavigationController.swift in Sources */, F6E5D0B01CF88C4C000874A3 /* JSNavigationControllerDelegate.swift in Sources */, - F6ED5F5F1CFF488300CF7222 /* JSNavigationControllerSegue.swift in Sources */, + F6ED5F5F1CFF488300CF7222 /* JSSegues.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/JSNavigationController/Sources/JSNavigationControllerSegue.swift b/JSNavigationController/Sources/JSNavigationControllerSegue.swift deleted file mode 100644 index 4fc849c..0000000 --- a/JSNavigationController/Sources/JSNavigationControllerSegue.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// JSRootViewControllerSegue.swift -// JSNavigationController -// -// Created by Julien Sagot on 01/06/16. -// Copyright © 2016 Julien Sagot. All rights reserved. -// - -import AppKit - -open class JSNavigationControllerSegue: NSStoryboardSegue { - open override func perform() { - return - } -} diff --git a/JSNavigationController/Sources/JSSegues.swift b/JSNavigationController/Sources/JSSegues.swift new file mode 100644 index 0000000..3f39b3b --- /dev/null +++ b/JSNavigationController/Sources/JSSegues.swift @@ -0,0 +1,63 @@ +// +// JSSegues.swift +// JSNavigationController +// +// Created by Julien Sagot on 01/06/16. +// Copyright © 2016 Julien Sagot. All rights reserved. +// + +import AppKit + +open class JSRootViewControllerSegue: NSStoryboardSegue +{ + public override init(identifier: NSStoryboardSegue.Identifier, source sourceController: Any, destination destinationController: Any) + { + assert(identifier == JSNavigationController.RootViewControllerSegueIdentifier, "Segue Identifier is not \"\(JSNavigationController.RootViewControllerSegueIdentifier)\"") + assert(sourceController is JSNavigationController, "Source View Controller is not of type JSNavigationController") + assert(destinationController is JSViewController, "Destination View Controller is not of type JSViewController") + assert((sourceController as! JSNavigationController).viewControllers.isEmpty, "JSNavigationController cannot have multiple Root View Controllers") + super.init(identifier: identifier, source: sourceController, destination: destinationController) + } + + open override func perform() + { + guard let sourceVC = self.sourceController as? JSNavigationController, + let destinationVC = self.destinationController as? JSViewController else { return } + sourceVC.push(viewController: destinationVC, animated: false) + } +} + +open class JSNavigationBarSegue: NSStoryboardSegue +{ + public override init(identifier: NSStoryboardSegue.Identifier, source sourceController: Any, destination destinationController: Any) + { + assert(identifier == JSViewController.NavigationBarSegueIdentifier, "Segue Identifier is not \"\(JSNavigationController.RootViewControllerSegueIdentifier)\"") + assert(sourceController is JSViewController, "Source View Controller is not of type JSViewController") + assert((sourceController as! JSViewController).navigationBarVC == nil, "JSNavigationController cannot have multiple Navigation Bar Controllers") + super.init(identifier: identifier, source: sourceController, destination: destinationController) + } + + open override func perform() + { + guard let sourceVC = self.sourceController as? JSViewController, + let destinationVC = self.destinationController as? NSViewController else { return } + sourceVC.navigationBarVC = destinationVC + } +} + +open class JSPushSegue: NSStoryboardSegue +{ + public override init(identifier: NSStoryboardSegue.Identifier, source sourceController: Any, destination destinationController: Any) + { + assert(sourceController is JSViewController, "Source View Controller is not of type JSViewController") + assert(destinationController is JSViewController, "Destination View Controller is not of type JSViewController") + super.init(identifier: identifier, source: sourceController, destination: destinationController) + } + + open override func perform() + { + guard let sourceVC = self.sourceController as? JSViewController, + let destinationVC = self.destinationController as? JSViewController else { return } + sourceVC.navigationController?.push(viewController: destinationVC, animated: true) + } +} From 620e8c5ee15fdc3d0da39370b58646adeb46085e Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Thu, 20 Aug 2020 01:23:08 +0530 Subject: [PATCH 08/11] Prevention of popping to 'topViewController' in 'JSViewControllersStackManager' & 'JSNavigationController' --- JSNavigationController/Sources/JSNavigationController.swift | 3 ++- .../Sources/JSViewControllersStackManager.swift | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/JSNavigationController/Sources/JSNavigationController.swift b/JSNavigationController/Sources/JSNavigationController.swift index edfb4aa..6885a53 100644 --- a/JSNavigationController/Sources/JSNavigationController.swift +++ b/JSNavigationController/Sources/JSNavigationController.swift @@ -163,7 +163,8 @@ open class JSNavigationController: NSViewController, JSViewControllersStackManag guard self.viewControllers.contains(viewController) else { return } guard let rootViewController = self.viewControllers.first else { return } guard let topViewController = self.topViewController else { return } - guard topViewController != rootViewController else { return } + guard topViewController != rootViewController, + topViewController != viewController else { return } self.delegate?.navigationController(self, willShowViewController: viewController, animated: (contentAnimation != nil)) diff --git a/JSNavigationController/Sources/JSViewControllersStackManager.swift b/JSNavigationController/Sources/JSViewControllersStackManager.swift index 465ee38..d515337 100644 --- a/JSNavigationController/Sources/JSViewControllersStackManager.swift +++ b/JSNavigationController/Sources/JSViewControllersStackManager.swift @@ -217,7 +217,8 @@ public extension JSViewControllersStackManager guard self.viewControllers.contains(viewController) else { return } guard let rootViewController = self.viewControllers.first, let topViewController = self.topViewController else { return } - guard topViewController != rootViewController else { return } + guard topViewController != rootViewController, + topViewController != viewController else { return } let viewControllerPosition = self.viewControllers.firstIndex(of: viewController) From 86865a51bc5c9a6ff701c53ad9521ea904aeac66 Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Thu, 20 Aug 2020 01:57:58 +0530 Subject: [PATCH 09/11] Correction of assertion message in 'JSNavigationBarSegue' in 'JSSegues.swift' --- JSNavigationController/Sources/JSSegues.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/JSNavigationController/Sources/JSSegues.swift b/JSNavigationController/Sources/JSSegues.swift index 3f39b3b..be0bbdb 100644 --- a/JSNavigationController/Sources/JSSegues.swift +++ b/JSNavigationController/Sources/JSSegues.swift @@ -31,7 +31,7 @@ open class JSNavigationBarSegue: NSStoryboardSegue { public override init(identifier: NSStoryboardSegue.Identifier, source sourceController: Any, destination destinationController: Any) { - assert(identifier == JSViewController.NavigationBarSegueIdentifier, "Segue Identifier is not \"\(JSNavigationController.RootViewControllerSegueIdentifier)\"") + assert(identifier == JSViewController.NavigationBarSegueIdentifier, "Segue Identifier is not \"\(JSViewController.NavigationBarSegueIdentifier)\"") assert(sourceController is JSViewController, "Source View Controller is not of type JSViewController") assert((sourceController as! JSViewController).navigationBarVC == nil, "JSNavigationController cannot have multiple Navigation Bar Controllers") super.init(identifier: identifier, source: sourceController, destination: destinationController) From d55a893a791815cc46cf317419060c9b1784c6f8 Mon Sep 17 00:00:00 2001 From: Gurmeher Singh Chawla Date: Thu, 20 Aug 2020 01:59:28 +0530 Subject: [PATCH 10/11] Updated 'ExampleStoryboard' Project with code enhancements, formatting and complying with updated 'JSNavigationController' framework --- .../Base.lproj/Main.storyboard | 52 ++++++++------- .../SecondViewController.swift | 64 +++++-------------- .../ExampleStoryboard/ViewController.swift | 56 +++++----------- 3 files changed, 60 insertions(+), 112 deletions(-) diff --git a/ExampleStoryboard/ExampleStoryboard/Base.lproj/Main.storyboard b/ExampleStoryboard/ExampleStoryboard/Base.lproj/Main.storyboard index a44b062..fa95f8b 100644 --- a/ExampleStoryboard/ExampleStoryboard/Base.lproj/Main.storyboard +++ b/ExampleStoryboard/ExampleStoryboard/Base.lproj/Main.storyboard @@ -1,8 +1,9 @@ - - + + - + + @@ -651,10 +652,13 @@ - + + + + @@ -673,7 +677,7 @@ - + @@ -687,8 +691,8 @@ - - + + @@ -704,7 +708,7 @@ - + @@ -712,7 +716,7 @@