Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 28 additions & 24 deletions ExampleStoryboard/ExampleStoryboard/Base.lproj/Main.storyboard

Large diffs are not rendered by default.

64 changes: 17 additions & 47 deletions ExampleStoryboard/ExampleStoryboard/SecondViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@ private extension Selector {
static let popViewController = #selector(SecondViewController.popViewController)
}

class SecondViewController: JSViewController {
class SecondViewController: JSViewController
{
// MARK: - View Lifecycle
override func viewDidLoad() {
override func viewDidLoad()
{
super.viewDidLoad()
view.translatesAutoresizingMaskIntoConstraints = false
view.wantsLayer = true
view.layer?.backgroundColor = NSColor(deviceRed: 240/255, green: 240/255, blue: 240/255, alpha: 1.0).cgColor
self.view.wantsLayer = true
self.view.layer?.backgroundColor = NSColor(deviceRed: 240/255, green: 240/255, blue: 240/255, alpha: 1.0).cgColor
}

override func viewDidAppear() {
override func viewDidAppear()
{
super.viewDidAppear()
view.superview?.addConstraints(viewConstraints())

// NavigationBar
(navigationBarVC as? SecondVCBarViewController)?.backButton?.target = self
Expand All @@ -29,49 +29,19 @@ class SecondViewController: JSViewController {
(navigationBarVC as? SecondVCBarViewController)?.fourthButton?.target = self
(navigationBarVC as? SecondVCBarViewController)?.fourthButton?.action = .pushFourthVC
}

override func viewDidDisappear() {
view.superview?.removeConstraints(viewConstraints())
}

// MARK: - Layout
fileprivate func viewConstraints() -> [NSLayoutConstraint] {
let left = NSLayoutConstraint(
item: view, attribute: .left, relatedBy: .equal,
toItem: view.superview, attribute: .left,
multiplier: 1.0, constant: 0.0
)
let right = NSLayoutConstraint(
item: view, attribute: .right, relatedBy: .equal,
toItem: view.superview, attribute: .right,
multiplier: 1.0, constant: 0.0
)
let top = NSLayoutConstraint(
item: view, attribute: .top, relatedBy: .equal,
toItem: view.superview, attribute: .top,
multiplier: 1.0, constant: 0.0
)
let bottom = NSLayoutConstraint(
item: view, attribute: .bottom, relatedBy: .equal,
toItem: view.superview, attribute: .bottom,
multiplier: 1.0, constant: 0.0
)
return [left, right, top, bottom]
}

@objc func pushThirdViewController() {
if let destinationViewController = destinationViewControllers["ThirdVC"] {
navigationController?.push(viewController: destinationViewController, animated: true)
}
@objc func pushThirdViewController()
{
self.performSegue(withIdentifier: "Third View Controller", sender: nil)
}

@objc func pushFourthViewController() {
if let destinationViewController = destinationViewControllers["FourthVC"] {
navigationController?.push(viewController: destinationViewController, animated: true)
}
@objc func pushFourthViewController()
{
self.performSegue(withIdentifier: "Fourth View Controller", sender: nil)
}

@objc func popViewController() {
navigationController?.popViewController(animated: true)
@objc func popViewController()
{
self.navigationController?.popViewController(animated: true)
}
}
56 changes: 15 additions & 41 deletions ExampleStoryboard/ExampleStoryboard/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,20 @@ private extension Selector {
static let popViewController = #selector(ViewController.popViewController)
}

class ViewController: JSViewController {

class ViewController: JSViewController
{
// MARK: - View Lifecycle
override func viewDidLoad() {

override func viewDidLoad()
{
super.viewDidLoad()
view.translatesAutoresizingMaskIntoConstraints = false
view.wantsLayer = true
view.layer?.backgroundColor = NSColor(deviceRed: 240/255, green: 240/255, blue: 240/255, alpha: 1.0).cgColor
self.view.wantsLayer = true
self.view.layer?.backgroundColor = NSColor(deviceRed: 240/255, green: 240/255, blue: 240/255, alpha: 1.0).cgColor
}

override func viewDidAppear() {
override func viewDidAppear()
{
super.viewDidAppear()
view.superview?.addConstraints(viewConstraints())

// NavigationBar
(navigationBarVC as? BasicNavigationBarViewController)?.backButton?.target = self
Expand All @@ -27,42 +28,15 @@ class ViewController: JSViewController {
(navigationBarVC as? BasicNavigationBarViewController)?.nextButton?.action = .pushToNextViewController
}

override func viewDidDisappear() {
view.superview?.removeConstraints(viewConstraints())
}

// MARK: - Layout
fileprivate func viewConstraints() -> [NSLayoutConstraint] {
let left = NSLayoutConstraint(
item: view, attribute: .left, relatedBy: .equal,
toItem: view.superview, attribute: .left,
multiplier: 1.0, constant: 0.0
)
let right = NSLayoutConstraint(
item: view, attribute: .right, relatedBy: .equal,
toItem: view.superview, attribute: .right,
multiplier: 1.0, constant: 0.0
)
let top = NSLayoutConstraint(
item: view, attribute: .top, relatedBy: .equal,
toItem: view.superview, attribute: .top,
multiplier: 1.0, constant: 0.0
)
let bottom = NSLayoutConstraint(
item: view, attribute: .bottom, relatedBy: .equal,
toItem: view.superview, attribute: .bottom,
multiplier: 1.0, constant: 0.0
)
return [left, right, top, bottom]
}

@objc func pushToNextViewController() {
if let destinationViewController = destinationViewController {
navigationController?.push(viewController: destinationViewController, animated: true)
}
@objc func pushToNextViewController()
{
self.performSegue(withIdentifier: "Second View Controller", sender: nil)
}

@objc func popViewController() {
navigationController?.popViewController(animated: true)
@objc func popViewController()
{
self.navigationController?.popViewController(animated: true)
}
}
8 changes: 4 additions & 4 deletions JSNavigationController.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -44,7 +44,7 @@
F67D71C81CF5E1FA003F8B91 /* JSNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSNavigationController.swift; path = Sources/JSNavigationController.swift; sourceTree = "<group>"; };
F67D71C91CF5E1FA003F8B91 /* JSViewControllersStackManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSViewControllersStackManager.swift; path = Sources/JSViewControllersStackManager.swift; sourceTree = "<group>"; };
F6E5D0AF1CF88C4C000874A3 /* JSNavigationControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSNavigationControllerDelegate.swift; path = Sources/JSNavigationControllerDelegate.swift; sourceTree = "<group>"; };
F6ED5F5E1CFF488300CF7222 /* JSNavigationControllerSegue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSNavigationControllerSegue.swift; path = Sources/JSNavigationControllerSegue.swift; sourceTree = "<group>"; };
F6ED5F5E1CFF488300CF7222 /* JSSegues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JSSegues.swift; path = Sources/JSSegues.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -112,7 +112,7 @@
F67D71C61CF5E1FA003F8B91 /* JSNavigationBarController.swift */,
F67D71C71CF5E1FA003F8B91 /* JSNavigationBarViewControllerProvider.swift */,
F67D71C91CF5E1FA003F8B91 /* JSViewControllersStackManager.swift */,
F6ED5F5E1CFF488300CF7222 /* JSNavigationControllerSegue.swift */,
F6ED5F5E1CFF488300CF7222 /* JSSegues.swift */,
F655C1631D00ABE3005208A1 /* JSViewController.swift */,
);
name = Sources;
Expand Down Expand Up @@ -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;
};
Expand Down
117 changes: 34 additions & 83 deletions JSNavigationController/Sources/JSNavigationBarController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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])
}
}
}
Loading