From 0382017e805901ec7f0edee53df207cae1e4db53 Mon Sep 17 00:00:00 2001 From: Arnaud Lays Date: Thu, 16 Nov 2017 16:06:18 -0500 Subject: [PATCH 01/73] External current top offset --- PullUpController/PullUpController.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index c23e78a..d37d7fc 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -77,6 +77,13 @@ open class PullUpController: UIViewController { private var portraitPreviousStickyPointIndex: Int? + /** + Current top offset + */ + public var currentTopOffset: CGFloat? { + return (parent?.view.frame.height ?? 0) - (topConstraint?.constant ?? 0) + } + /** This method will move the pull up controller's view in order to show the provided visible point. From b5532e8bad85bd1383bfd1682a1bc76756b05a73 Mon Sep 17 00:00:00 2001 From: Arnaud Lays Date: Thu, 16 Nov 2017 16:06:58 -0500 Subject: [PATCH 02/73] Add Delegate to observe current top offset changes --- PullUpController/PullUpController.swift | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index d37d7fc..50edc90 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -8,6 +8,21 @@ import UIKit +public protocol pullUpControllerDelegate { + + /** + Call when any offset changes + */ + func pullUpControllerDidScroll(_ pullUpController: PullUpController) +} + +extension pullUpControllerDelegate { + + func pullUpControllerDidScroll(_ pullUpController: PullUpController) { + //optional + } +} + open class PullUpController: UIViewController { private var leftConstraint: NSLayoutConstraint? @@ -16,6 +31,8 @@ open class PullUpController: UIViewController { private var heightConstraint: NSLayoutConstraint? private var panGestureRecognizer: UIPanGestureRecognizer? + public var pullUpControllerDelegate: pullUpControllerDelegate? = nil + /** The desired height in screen units expressed in the pull up controller coordinate system that will be initially showed. The default value is 50. @@ -94,6 +111,7 @@ open class PullUpController: UIViewController { open func pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, completion: (() -> Void)?) { guard isPortrait else { return } topConstraint?.constant = (parent?.view.frame.height ?? 0) - visiblePoint + pullUpControllerOffsetIsChanging() UIView.animate( withDuration: 0.3, @@ -194,6 +212,7 @@ open class PullUpController: UIViewController { } ) } + pullUpControllerOffsetIsChanging() } @objc fileprivate func handleInternalScrollViewPanGestureRecognizer(_ gestureRecognizer: UIPanGestureRecognizer) { @@ -222,6 +241,7 @@ open class PullUpController: UIViewController { } ) } + pullUpControllerOffsetIsChanging() } private func setPortraitConstraints(parentViewSize: CGSize) { @@ -244,6 +264,11 @@ open class PullUpController: UIViewController { } else { setPortraitConstraints(parentViewSize: size) } + pullUpControllerOffsetIsChanging() + } + + open func pullUpControllerOffsetIsChanging() { + pullUpControllerDelegate?.pullUpControllerDidScroll(self) } } From 3c06b70d017ae59b53cf9022071483715ec89ab9 Mon Sep 17 00:00:00 2001 From: Arnaud Lays Date: Thu, 16 Nov 2017 16:17:52 -0500 Subject: [PATCH 03/73] Fix protocol lowercase and optional method --- PullUpController/PullUpController.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 50edc90..38e2372 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -8,7 +8,7 @@ import UIKit -public protocol pullUpControllerDelegate { +public protocol PullUpControllerDelegate { /** Call when any offset changes @@ -16,7 +16,7 @@ public protocol pullUpControllerDelegate { func pullUpControllerDidScroll(_ pullUpController: PullUpController) } -extension pullUpControllerDelegate { +public extension PullUpControllerDelegate { func pullUpControllerDidScroll(_ pullUpController: PullUpController) { //optional @@ -31,7 +31,7 @@ open class PullUpController: UIViewController { private var heightConstraint: NSLayoutConstraint? private var panGestureRecognizer: UIPanGestureRecognizer? - public var pullUpControllerDelegate: pullUpControllerDelegate? = nil + public var pullUpControllerDelegate: PullUpControllerDelegate? = nil /** The desired height in screen units expressed in the pull up controller coordinate system that will be initially showed. @@ -120,7 +120,7 @@ open class PullUpController: UIViewController { }, completion: { _ in completion?() - } + } ) } From 9921859418edb6fd11d07a424d594dd4737aa975 Mon Sep 17 00:00:00 2001 From: Ilya Seliverstov Date: Tue, 21 Nov 2017 15:30:37 +0100 Subject: [PATCH 04/73] notifications for movements between sticky points --- PullUpController/PullUpController.swift | 39 ++++++++++++------- .../SearchViewController.swift | 10 ++++- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index c23e78a..0de3a33 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -8,6 +8,8 @@ import UIKit +public typealias PullUpControllerMoveToPoint = ((_ point: CGFloat) -> Void) + open class PullUpController: UIViewController { private var leftConstraint: NSLayoutConstraint? @@ -15,7 +17,13 @@ open class PullUpController: UIViewController { private var widthConstraint: NSLayoutConstraint? private var heightConstraint: NSLayoutConstraint? private var panGestureRecognizer: UIPanGestureRecognizer? - + + /** + Notifications to be called when controller will/did move to one of sticky points + */ + open var willMoveToStickyPoint: PullUpControllerMoveToPoint? + open var didMoveToStickyPoint: PullUpControllerMoveToPoint? + /** The desired height in screen units expressed in the pull up controller coordinate system that will be initially showed. The default value is 50. @@ -98,7 +106,7 @@ open class PullUpController: UIViewController { } ) } - + open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { let isPortrait = size.height > size.width var targetStickyPoint: CGFloat? @@ -158,6 +166,7 @@ open class PullUpController: UIViewController { } } + willMoveToStickyPoint?(pullUpControllerAllStickyPoints[currentStickyPointIndex]) return (parent?.view.frame.height ?? 0) - pullUpControllerAllStickyPoints[currentStickyPointIndex] } @@ -180,12 +189,7 @@ open class PullUpController: UIViewController { if gestureRecognizer.state == .ended { topConstraint.constant = nearestStickyPointY(yVelocity: gestureRecognizer.velocity(in: view).y) - UIView.animate( - withDuration: 0.3, - animations: { [weak self] in - self?.parent?.view.layoutIfNeeded() - } - ) + animateLayout() } } @@ -208,15 +212,22 @@ open class PullUpController: UIViewController { if gestureRecognizer.state.rawValue == 3 { // for some reason gestureRecognizer.state == .ended doesn't work topConstraint?.constant = nearestStickyPointY(yVelocity: 0) - UIView.animate( - withDuration: 0.3, - animations: { [weak self] in - self?.parent?.view.layoutIfNeeded() - } - ) + animateLayout() } } + private func animateLayout() { + UIView.animate( + withDuration: 0.3, + animations: { [weak self] in + self?.parent?.view.layoutIfNeeded() + + let point = (self?.parent?.view.frame.height ?? 0.0) - (self?.topConstraint?.constant ?? 0.0) + self?.didMoveToStickyPoint?(point) + } + ) + } + private func setPortraitConstraints(parentViewSize: CGSize) { topConstraint?.constant = parentViewSize.height - pullUpControllerPreviewOffset leftConstraint?.constant = (parentViewSize.width - min(pullUpControllerPreferredSize.width, parentViewSize.width))/2 diff --git a/PullUpControllerDemo/SearchViewController.swift b/PullUpControllerDemo/SearchViewController.swift index 76eb64b..8dd6f2e 100644 --- a/PullUpControllerDemo/SearchViewController.swift +++ b/PullUpControllerDemo/SearchViewController.swift @@ -33,8 +33,16 @@ class SearchViewController: PullUpController { tableView.attach(to: self) setupDataSource() + + self.willMoveToStickyPoint = { point in + print("willMoveToStickyPoint \(point)") + } + + self.didMoveToStickyPoint = { point in + print("didMoveToStickyPoint \(point)") + } } - + override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() From e8fae082b46389d2d0ac96a15b3e7d527dcba8b0 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 21 Nov 2017 19:12:57 +0100 Subject: [PATCH 05/73] Revert "External topOffset and observe changes" --- PullUpController/PullUpController.swift | 34 +------------------------ 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 38e2372..c23e78a 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -8,21 +8,6 @@ import UIKit -public protocol PullUpControllerDelegate { - - /** - Call when any offset changes - */ - func pullUpControllerDidScroll(_ pullUpController: PullUpController) -} - -public extension PullUpControllerDelegate { - - func pullUpControllerDidScroll(_ pullUpController: PullUpController) { - //optional - } -} - open class PullUpController: UIViewController { private var leftConstraint: NSLayoutConstraint? @@ -31,8 +16,6 @@ open class PullUpController: UIViewController { private var heightConstraint: NSLayoutConstraint? private var panGestureRecognizer: UIPanGestureRecognizer? - public var pullUpControllerDelegate: PullUpControllerDelegate? = nil - /** The desired height in screen units expressed in the pull up controller coordinate system that will be initially showed. The default value is 50. @@ -94,13 +77,6 @@ open class PullUpController: UIViewController { private var portraitPreviousStickyPointIndex: Int? - /** - Current top offset - */ - public var currentTopOffset: CGFloat? { - return (parent?.view.frame.height ?? 0) - (topConstraint?.constant ?? 0) - } - /** This method will move the pull up controller's view in order to show the provided visible point. @@ -111,7 +87,6 @@ open class PullUpController: UIViewController { open func pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, completion: (() -> Void)?) { guard isPortrait else { return } topConstraint?.constant = (parent?.view.frame.height ?? 0) - visiblePoint - pullUpControllerOffsetIsChanging() UIView.animate( withDuration: 0.3, @@ -120,7 +95,7 @@ open class PullUpController: UIViewController { }, completion: { _ in completion?() - } + } ) } @@ -212,7 +187,6 @@ open class PullUpController: UIViewController { } ) } - pullUpControllerOffsetIsChanging() } @objc fileprivate func handleInternalScrollViewPanGestureRecognizer(_ gestureRecognizer: UIPanGestureRecognizer) { @@ -241,7 +215,6 @@ open class PullUpController: UIViewController { } ) } - pullUpControllerOffsetIsChanging() } private func setPortraitConstraints(parentViewSize: CGSize) { @@ -264,11 +237,6 @@ open class PullUpController: UIViewController { } else { setPortraitConstraints(parentViewSize: size) } - pullUpControllerOffsetIsChanging() - } - - open func pullUpControllerOffsetIsChanging() { - pullUpControllerDelegate?.pullUpControllerDidScroll(self) } } From 9c79b6b93c0f2ba05844c830e018f8c539327082 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 21 Nov 2017 19:24:21 +0100 Subject: [PATCH 06/73] Improve code documentation --- PullUpController/PullUpController.swift | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 0de3a33..8c3aa4f 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -8,8 +8,6 @@ import UIKit -public typealias PullUpControllerMoveToPoint = ((_ point: CGFloat) -> Void) - open class PullUpController: UIViewController { private var leftConstraint: NSLayoutConstraint? @@ -17,13 +15,19 @@ open class PullUpController: UIViewController { private var widthConstraint: NSLayoutConstraint? private var heightConstraint: NSLayoutConstraint? private var panGestureRecognizer: UIPanGestureRecognizer? - + /** - Notifications to be called when controller will/did move to one of sticky points + The closure to execute before the view controller's view move to a sticky point. + The target sticky point, expressed in the pull up controller coordinate system, is provided in the closure parameter. */ - open var willMoveToStickyPoint: PullUpControllerMoveToPoint? - open var didMoveToStickyPoint: PullUpControllerMoveToPoint? - + open var willMoveToStickyPoint: ((_ point: CGFloat) -> Void)? + + /** + The closure to execute after the view controller's view move to a sticky point. + The sticky point, expressed in the pull up controller coordinate system, is provided in the closure parameter. + */ + open var didMoveToStickyPoint: ((_ point: CGFloat) -> Void)? + /** The desired height in screen units expressed in the pull up controller coordinate system that will be initially showed. The default value is 50. @@ -103,10 +107,10 @@ open class PullUpController: UIViewController { }, completion: { _ in completion?() - } + } ) } - + open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { let isPortrait = size.height > size.width var targetStickyPoint: CGFloat? @@ -227,7 +231,7 @@ open class PullUpController: UIViewController { } ) } - + private func setPortraitConstraints(parentViewSize: CGSize) { topConstraint?.constant = parentViewSize.height - pullUpControllerPreviewOffset leftConstraint?.constant = (parentViewSize.width - min(pullUpControllerPreferredSize.width, parentViewSize.width))/2 From 639b4225f17ac9175875101752e21cb576b2edf7 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 21 Jun 2018 12:56:14 +0200 Subject: [PATCH 07/73] Remove fixed value from animation duration MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The animation duration now is calculated based on gesture recognizer pan vertical velocity. Also I’ve fixed a couple of typos and cleaned up the code. --- PullUpController/PullUpController.swift | 65 ++++++++++++------- .../project.pbxproj | 6 +- 2 files changed, 46 insertions(+), 25 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 8c3aa4f..1253fac 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -10,11 +10,7 @@ import UIKit open class PullUpController: UIViewController { - private var leftConstraint: NSLayoutConstraint? - private var topConstraint: NSLayoutConstraint? - private var widthConstraint: NSLayoutConstraint? - private var heightConstraint: NSLayoutConstraint? - private var panGestureRecognizer: UIPanGestureRecognizer? + // MARK: - Open properties /** The closure to execute before the view controller's view move to a sticky point. @@ -57,16 +53,6 @@ open class PullUpController: UIViewController { return [] } - /** - A list of y values, in screen units expressed in the pull up controller coordinate system. - At the end of the gesture the pull up controller will scroll at the nearest point in the list. - */ - public final var pullUpControllerAllStickyPoints: [CGFloat] { - var sc_allStickyPoints = [pullUpControllerPreviewOffset, pullUpControllerPreferredSize.height] - sc_allStickyPoints.append(contentsOf: pullUpControllerMiddleStickyPoints) - return sc_allStickyPoints.sorted() - } - /** A Boolean value that determines whether bouncing occurs when scrolling reaches the end of the pull up controller's view size. The default value is false. @@ -83,12 +69,32 @@ open class PullUpController: UIViewController { return CGRect(x: 10, y: 10, width: 300, height: UIScreen.main.bounds.height - 20) } + // MARK: - Public properties + + /** + A list of y values, in screen units expressed in the pull up controller coordinate system. + At the end of the gesture the pull up controller will scroll at the nearest point in the list. + */ + public final var pullUpControllerAllStickyPoints: [CGFloat] { + var sc_allStickyPoints = [pullUpControllerPreviewOffset, pullUpControllerPreferredSize.height] + sc_allStickyPoints.append(contentsOf: pullUpControllerMiddleStickyPoints) + return sc_allStickyPoints.sorted() + } + + private var leftConstraint: NSLayoutConstraint? + private var topConstraint: NSLayoutConstraint? + private var widthConstraint: NSLayoutConstraint? + private var heightConstraint: NSLayoutConstraint? + private var panGestureRecognizer: UIPanGestureRecognizer? + private var isPortrait: Bool { return UIScreen.main.bounds.height > UIScreen.main.bounds.width } private var portraitPreviousStickyPointIndex: Int? + // MARK: - Open methods + /** This method will move the pull up controller's view in order to show the provided visible point. @@ -107,7 +113,7 @@ open class PullUpController: UIViewController { }, completion: { _ in completion?() - } + } ) } @@ -133,6 +139,8 @@ open class PullUpController: UIViewController { }) } + // MARK: - Setup + fileprivate func setupPanGestureRecognizer() { panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestureRecognizer(_:))) panGestureRecognizer?.minimumNumberOfTouches = 1 @@ -142,7 +150,7 @@ open class PullUpController: UIViewController { } } - fileprivate func setupConstrains() { + fileprivate func setupConstraints() { guard let parentView = parent?.view else { return } topConstraint = view.topAnchor.constraint(equalTo: parentView.topAnchor, constant: 0) @@ -150,7 +158,7 @@ open class PullUpController: UIViewController { widthConstraint = view.widthAnchor.constraint(equalToConstant: pullUpControllerPreferredSize.width) heightConstraint = view.heightAnchor.constraint(equalToConstant: pullUpControllerPreferredSize.height) - NSLayoutConstraint.activate([topConstraint, leftConstraint, widthConstraint, heightConstraint].flatMap { $0 }) + NSLayoutConstraint.activate([topConstraint, leftConstraint, widthConstraint, heightConstraint].compactMap { $0 }) } private var currentStickyPointIndex: Int { @@ -192,8 +200,12 @@ open class PullUpController: UIViewController { } if gestureRecognizer.state == .ended { - topConstraint.constant = nearestStickyPointY(yVelocity: gestureRecognizer.velocity(in: view).y) - animateLayout() + let yVelocity = gestureRecognizer.velocity(in: view).y // v = px/s + let oldTopConstraintConstant = topConstraint.constant + topConstraint.constant = nearestStickyPointY(yVelocity: yVelocity) + let distanceToConver = oldTopConstraintConstant - topConstraint.constant // px + let animationDuration = TimeInterval(abs(distanceToConver/yVelocity)) // s = px/v + animateLayout(animationDuration: animationDuration) } } @@ -220,12 +232,14 @@ open class PullUpController: UIViewController { } } - private func animateLayout() { + private func animateLayout(animationDuration: TimeInterval? = nil) { + let defaultAnimationDuration = 0.3 + let animationDuration = max(0.08, min(defaultAnimationDuration, animationDuration ?? defaultAnimationDuration)) + UIView.animate( - withDuration: 0.3, + withDuration: animationDuration, animations: { [weak self] in self?.parent?.view.layoutIfNeeded() - let point = (self?.parent?.view.frame.height ?? 0.0) - (self?.topConstraint?.constant ?? 0.0) self?.didMoveToStickyPoint?(point) } @@ -253,6 +267,7 @@ open class PullUpController: UIViewController { setPortraitConstraints(parentViewSize: size) } } + } extension UIViewController { @@ -268,9 +283,10 @@ extension UIViewController { view.addSubview(pullUpController.view) pullUpController.setupPanGestureRecognizer() - pullUpController.setupConstrains() + pullUpController.setupConstraints() pullUpController.refreshConstraints(size: view.frame.size) } + } extension UIScrollView { @@ -282,4 +298,5 @@ extension UIScrollView { open func attach(to pullUpController: PullUpController) { panGestureRecognizer.addTarget(pullUpController, action: #selector(pullUpController.handleInternalScrollViewPanGestureRecognizer(_:))) } + } diff --git a/PullUpControllerDemo.xcodeproj/project.pbxproj b/PullUpControllerDemo.xcodeproj/project.pbxproj index 6e21ed5..26b70f3 100644 --- a/PullUpControllerDemo.xcodeproj/project.pbxproj +++ b/PullUpControllerDemo.xcodeproj/project.pbxproj @@ -108,7 +108,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0910; - LastUpgradeCheck = 0910; + LastUpgradeCheck = 0940; ORGANIZATIONNAME = Mario; TargetAttributes = { AC1A74C31FACEEAD00392CB8 = { @@ -197,6 +197,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -204,6 +205,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; @@ -254,6 +256,7 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; @@ -261,6 +264,7 @@ CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; From bd2fe9947edb85a1f6ff0232e68938548505cb6f Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 21 Jun 2018 17:56:34 +0200 Subject: [PATCH 08/73] Refactor project to pod template --- Example/Podfile | 5 + Example/Podfile.lock | 16 + .../PullUpController.podspec.json | 24 + Example/Pods/Manifest.lock | 16 + Example/Pods/Pods.xcodeproj/project.pbxproj | 584 ++++++++++++++++++ .../Pods-PullUpController_Example/Info.plist | 26 + ...ntroller_Example-acknowledgements.markdown | 26 + ...pController_Example-acknowledgements.plist | 58 ++ .../Pods-PullUpController_Example-dummy.m | 5 + ...ods-PullUpController_Example-frameworks.sh | 153 +++++ ...Pods-PullUpController_Example-resources.sh | 118 ++++ .../Pods-PullUpController_Example-umbrella.h | 16 + ...ds-PullUpController_Example.debug.xcconfig | 11 + .../Pods-PullUpController_Example.modulemap | 6 + ...-PullUpController_Example.release.xcconfig | 11 + .../PullUpController/Info.plist | 26 + .../PullUpController/PullUpController-dummy.m | 5 + .../PullUpController-prefix.pch | 12 + .../PullUpController-umbrella.h | 16 + .../PullUpController.modulemap | 6 + .../PullUpController.xcconfig | 10 + .../project.pbxproj | 414 +++++++++++++ .../contents.xcworkspacedata | 2 +- .../PullUpController-Example.xcscheme | 115 ++++ .../contents.xcworkspacedata | 10 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../PullUpController}/AppDelegate.swift | 0 .../AppIcon.appiconset/Contents.json | 0 .../Assets.xcassets/Contents.json | 0 .../Supporting files}/Info.plist | 0 .../Supporting files}/LaunchScreen.storyboard | 0 .../PullUpController/UI}/Main.storyboard | 0 .../UI}/MapViewController.swift | 0 .../UI}/SearchResultCell.swift | 0 .../UI}/SearchViewController.swift | 1 + PullUpController.podspec | 6 +- .../project.pbxproj | 349 ----------- _Pods.xcodeproj | 1 + 38 files changed, 1703 insertions(+), 353 deletions(-) create mode 100644 Example/Podfile create mode 100644 Example/Podfile.lock create mode 100644 Example/Pods/Local Podspecs/PullUpController.podspec.json create mode 100644 Example/Pods/Manifest.lock create mode 100644 Example/Pods/Pods.xcodeproj/project.pbxproj create mode 100644 Example/Pods/Target Support Files/Pods-PullUpController_Example/Info.plist create mode 100644 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-acknowledgements.markdown create mode 100644 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-acknowledgements.plist create mode 100644 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-dummy.m create mode 100755 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-frameworks.sh create mode 100755 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-resources.sh create mode 100644 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-umbrella.h create mode 100644 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.debug.xcconfig create mode 100644 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.modulemap create mode 100644 Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.release.xcconfig create mode 100644 Example/Pods/Target Support Files/PullUpController/Info.plist create mode 100644 Example/Pods/Target Support Files/PullUpController/PullUpController-dummy.m create mode 100644 Example/Pods/Target Support Files/PullUpController/PullUpController-prefix.pch create mode 100644 Example/Pods/Target Support Files/PullUpController/PullUpController-umbrella.h create mode 100644 Example/Pods/Target Support Files/PullUpController/PullUpController.modulemap create mode 100644 Example/Pods/Target Support Files/PullUpController/PullUpController.xcconfig create mode 100644 Example/PullUpController.xcodeproj/project.pbxproj rename {PullUpControllerDemo.xcodeproj => Example/PullUpController.xcodeproj}/project.xcworkspace/contents.xcworkspacedata (53%) create mode 100644 Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme create mode 100644 Example/PullUpController.xcworkspace/contents.xcworkspacedata create mode 100644 Example/PullUpController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename {PullUpControllerDemo => Example/PullUpController}/AppDelegate.swift (100%) rename {PullUpControllerDemo => Example/PullUpController}/Assets.xcassets/AppIcon.appiconset/Contents.json (100%) rename {PullUpControllerDemo => Example/PullUpController}/Assets.xcassets/Contents.json (100%) rename {PullUpControllerDemo => Example/PullUpController/Supporting files}/Info.plist (100%) rename {PullUpControllerDemo/Base.lproj => Example/PullUpController/Supporting files}/LaunchScreen.storyboard (100%) rename {PullUpControllerDemo/Base.lproj => Example/PullUpController/UI}/Main.storyboard (100%) rename {PullUpControllerDemo => Example/PullUpController/UI}/MapViewController.swift (100%) rename {PullUpControllerDemo => Example/PullUpController/UI}/SearchResultCell.swift (100%) rename {PullUpControllerDemo => Example/PullUpController/UI}/SearchViewController.swift (99%) delete mode 100644 PullUpControllerDemo.xcodeproj/project.pbxproj create mode 120000 _Pods.xcodeproj diff --git a/Example/Podfile b/Example/Podfile new file mode 100644 index 0000000..fec5842 --- /dev/null +++ b/Example/Podfile @@ -0,0 +1,5 @@ +use_frameworks! + +target 'PullUpController_Example' do + pod 'PullUpController', :path => '../' +end diff --git a/Example/Podfile.lock b/Example/Podfile.lock new file mode 100644 index 0000000..b52f761 --- /dev/null +++ b/Example/Podfile.lock @@ -0,0 +1,16 @@ +PODS: + - PullUpController (0.2.0) + +DEPENDENCIES: + - PullUpController (from `../`) + +EXTERNAL SOURCES: + PullUpController: + :path: "../" + +SPEC CHECKSUMS: + PullUpController: 7df1d1e15cf588cecda202879275aeafae1f8a81 + +PODFILE CHECKSUM: 33dfca2e6c424e0eb19d05b0b6293a44ee627326 + +COCOAPODS: 1.5.0 diff --git a/Example/Pods/Local Podspecs/PullUpController.podspec.json b/Example/Pods/Local Podspecs/PullUpController.podspec.json new file mode 100644 index 0000000..14d7a48 --- /dev/null +++ b/Example/Pods/Local Podspecs/PullUpController.podspec.json @@ -0,0 +1,24 @@ +{ + "name": "PullUpController", + "version": "0.2.0", + "summary": "Pull up controller with multiple sticky points like in iOS Maps.", + "homepage": "https://github.com/MarioIannotta/PullUpController", + "license": { + "type": "MIT", + "file": "LICENSE" + }, + "authors": { + "Mario Iannotta": "info@marioiannotta.com" + }, + "source": { + "git": "https://github.com/MarioIannotta/PullUpController.git", + "tag": "0.2.0" + }, + "platforms": { + "ios": "9.0" + }, + "source_files": "PullUpController/**/*.swift", + "pod_target_xcconfig": { + "SWIFT_VERSION": "4.2" + } +} diff --git a/Example/Pods/Manifest.lock b/Example/Pods/Manifest.lock new file mode 100644 index 0000000..b52f761 --- /dev/null +++ b/Example/Pods/Manifest.lock @@ -0,0 +1,16 @@ +PODS: + - PullUpController (0.2.0) + +DEPENDENCIES: + - PullUpController (from `../`) + +EXTERNAL SOURCES: + PullUpController: + :path: "../" + +SPEC CHECKSUMS: + PullUpController: 7df1d1e15cf588cecda202879275aeafae1f8a81 + +PODFILE CHECKSUM: 33dfca2e6c424e0eb19d05b0b6293a44ee627326 + +COCOAPODS: 1.5.0 diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj new file mode 100644 index 0000000..1702cb5 --- /dev/null +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -0,0 +1,584 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 2955C19063DF47E923334A533D99F273 /* Pods-PullUpController_Example-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 13054176DE8FD7682EA5876D0559D994 /* Pods-PullUpController_Example-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 8031195AB9B2F6F1140776E5BDA4A34C /* PullUpController-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 23CC8DB9AF358116FE5F077A38A91D66 /* PullUpController-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + E010BBE3A0DCA0581AEA0F8AE4F58BFC /* Pods-PullUpController_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = BB536EBEECAC21C47D62C1DF0D798356 /* Pods-PullUpController_Example-dummy.m */; }; + E371467500760254B3FDE804F871C01F /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */; }; + F12BA5B5DD5E409088A60EE72BAD20DD /* PullUpController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8AAE02B10DCAF71B4C8DA0F59BB3F4D4 /* PullUpController.swift */; }; + F698D35311AF7A82832B9961D8567285 /* PullUpController-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = C5B8751D4FDEC7CA05976A501C20CE94 /* PullUpController-dummy.m */; }; + FB3DAB06F8E1C5D93F78EDD7AB44A67E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + F8C04CCB6BD040FDB99775BF786172D0 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; + proxyType = 1; + remoteGlobalIDString = 88A21A82856B75E85E451F68BE9B66F7; + remoteInfo = PullUpController; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 1018868A7D2730AD2239974DEC2BB3EC /* Pods-PullUpController_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PullUpController_Example-frameworks.sh"; sourceTree = ""; }; + 13054176DE8FD7682EA5876D0559D994 /* Pods-PullUpController_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PullUpController_Example-umbrella.h"; sourceTree = ""; }; + 21F144D6F2B3882BC5FD9933E31927EA /* Pods-PullUpController_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PullUpController_Example.release.xcconfig"; sourceTree = ""; }; + 23CC8DB9AF358116FE5F077A38A91D66 /* PullUpController-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PullUpController-umbrella.h"; sourceTree = ""; }; + 2C5AA6A33D63B64686BB7A5B6B78E35B /* PullUpController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PullUpController.framework; path = PullUpController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C31DAEE49BC012D13D12539B321D0A3 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + 40664F6BBDF3B9CD293C19FB51C67E34 /* Pods-PullUpController_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PullUpController_Example-acknowledgements.markdown"; sourceTree = ""; }; + 483D1843AE28A17CB5FD474CEE4AF6BB /* PullUpController-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PullUpController-prefix.pch"; sourceTree = ""; }; + 50E3AF474793B9EE7DE53500151B8954 /* PullUpController.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = PullUpController.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 79F4FAA2380B9E03FF9DE31DABF0669C /* Pods-PullUpController_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PullUpController_Example-resources.sh"; sourceTree = ""; }; + 8AAE02B10DCAF71B4C8DA0F59BB3F4D4 /* PullUpController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PullUpController.swift; path = PullUpController/PullUpController.swift; sourceTree = ""; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9F56E5FB334BA9037FAA64158F05C7D6 /* PullUpController.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PullUpController.modulemap; sourceTree = ""; }; + BB536EBEECAC21C47D62C1DF0D798356 /* Pods-PullUpController_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PullUpController_Example-dummy.m"; sourceTree = ""; }; + BB9F8EA9DDF18EABDC0BB608ACF09769 /* Pods-PullUpController_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PullUpController_Example-acknowledgements.plist"; sourceTree = ""; }; + BF0DB4470D13394EFA28A938F1A38755 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + C5B8751D4FDEC7CA05976A501C20CE94 /* PullUpController-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PullUpController-dummy.m"; sourceTree = ""; }; + C8FA5C2BF2D4AFB310AB73255CE621BC /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D755ED3538F9C07483D9251773906FF9 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + DA07B630F7B2CEB638C65108EE8C97AF /* Pods_PullUpController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PullUpController_Example.framework; path = "Pods-PullUpController_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + DCF8A9AF865D53B852B08F7253C08494 /* Pods-PullUpController_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PullUpController_Example.debug.xcconfig"; sourceTree = ""; }; + DD9FE163A3EEF9FA109361613CC05E88 /* Pods-PullUpController_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PullUpController_Example.modulemap"; sourceTree = ""; }; + DE129AA35E6DD8D1AC44CED9A162F31F /* PullUpController.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PullUpController.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 68399AA00D7ED1FAE5D85A2356B715F7 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + FB3DAB06F8E1C5D93F78EDD7AB44A67E /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7956F4F535B023771CF75A099890F970 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E371467500760254B3FDE804F871C01F /* Foundation.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 029F610A648A9E8A3E4E658B2A17BCA7 /* Pods-PullUpController_Example */ = { + isa = PBXGroup; + children = ( + D755ED3538F9C07483D9251773906FF9 /* Info.plist */, + DD9FE163A3EEF9FA109361613CC05E88 /* Pods-PullUpController_Example.modulemap */, + 40664F6BBDF3B9CD293C19FB51C67E34 /* Pods-PullUpController_Example-acknowledgements.markdown */, + BB9F8EA9DDF18EABDC0BB608ACF09769 /* Pods-PullUpController_Example-acknowledgements.plist */, + BB536EBEECAC21C47D62C1DF0D798356 /* Pods-PullUpController_Example-dummy.m */, + 1018868A7D2730AD2239974DEC2BB3EC /* Pods-PullUpController_Example-frameworks.sh */, + 79F4FAA2380B9E03FF9DE31DABF0669C /* Pods-PullUpController_Example-resources.sh */, + 13054176DE8FD7682EA5876D0559D994 /* Pods-PullUpController_Example-umbrella.h */, + DCF8A9AF865D53B852B08F7253C08494 /* Pods-PullUpController_Example.debug.xcconfig */, + 21F144D6F2B3882BC5FD9933E31927EA /* Pods-PullUpController_Example.release.xcconfig */, + ); + name = "Pods-PullUpController_Example"; + path = "Target Support Files/Pods-PullUpController_Example"; + sourceTree = ""; + }; + 7BAD67385D0C43E7DA5CAF14D803C9B3 /* PullUpController */ = { + isa = PBXGroup; + children = ( + 8AAE02B10DCAF71B4C8DA0F59BB3F4D4 /* PullUpController.swift */, + 9338AE7FCA03262521D339B678C6DDA9 /* Pod */, + F3A348D06466386159932F373F839F8A /* Support Files */, + ); + name = PullUpController; + path = ../..; + sourceTree = ""; + }; + 7DB346D0F39D3F0E887471402A8071AB = { + isa = PBXGroup; + children = ( + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, + BB16A59184FD9A5B1E8359F87D3D0E62 /* Development Pods */, + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, + B9052FE89FBCC9091AC04DA17B7D5702 /* Products */, + 9CCF54054156BC7F2DAD2E85902CE025 /* Targets Support Files */, + ); + sourceTree = ""; + }; + 9338AE7FCA03262521D339B678C6DDA9 /* Pod */ = { + isa = PBXGroup; + children = ( + 3C31DAEE49BC012D13D12539B321D0A3 /* LICENSE */, + 50E3AF474793B9EE7DE53500151B8954 /* PullUpController.podspec */, + BF0DB4470D13394EFA28A938F1A38755 /* README.md */, + ); + name = Pod; + sourceTree = ""; + }; + 9CCF54054156BC7F2DAD2E85902CE025 /* Targets Support Files */ = { + isa = PBXGroup; + children = ( + 029F610A648A9E8A3E4E658B2A17BCA7 /* Pods-PullUpController_Example */, + ); + name = "Targets Support Files"; + sourceTree = ""; + }; + B9052FE89FBCC9091AC04DA17B7D5702 /* Products */ = { + isa = PBXGroup; + children = ( + DA07B630F7B2CEB638C65108EE8C97AF /* Pods_PullUpController_Example.framework */, + 2C5AA6A33D63B64686BB7A5B6B78E35B /* PullUpController.framework */, + ); + name = Products; + sourceTree = ""; + }; + BB16A59184FD9A5B1E8359F87D3D0E62 /* Development Pods */ = { + isa = PBXGroup; + children = ( + 7BAD67385D0C43E7DA5CAF14D803C9B3 /* PullUpController */, + ); + name = "Development Pods"; + sourceTree = ""; + }; + BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { + isa = PBXGroup; + children = ( + D35AF013A5F0BAD4F32504907A52519E /* iOS */, + ); + name = Frameworks; + sourceTree = ""; + }; + D35AF013A5F0BAD4F32504907A52519E /* iOS */ = { + isa = PBXGroup; + children = ( + 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */, + ); + name = iOS; + sourceTree = ""; + }; + F3A348D06466386159932F373F839F8A /* Support Files */ = { + isa = PBXGroup; + children = ( + C8FA5C2BF2D4AFB310AB73255CE621BC /* Info.plist */, + 9F56E5FB334BA9037FAA64158F05C7D6 /* PullUpController.modulemap */, + DE129AA35E6DD8D1AC44CED9A162F31F /* PullUpController.xcconfig */, + C5B8751D4FDEC7CA05976A501C20CE94 /* PullUpController-dummy.m */, + 483D1843AE28A17CB5FD474CEE4AF6BB /* PullUpController-prefix.pch */, + 23CC8DB9AF358116FE5F077A38A91D66 /* PullUpController-umbrella.h */, + ); + name = "Support Files"; + path = "Example/Pods/Target Support Files/PullUpController"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 0D41126CBF9C129313DEC023CC93CF47 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 2955C19063DF47E923334A533D99F273 /* Pods-PullUpController_Example-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 5FBADA4F2CE146E6B2CDCEEB2F073F9C /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 8031195AB9B2F6F1140776E5BDA4A34C /* PullUpController-umbrella.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 88A21A82856B75E85E451F68BE9B66F7 /* PullUpController */ = { + isa = PBXNativeTarget; + buildConfigurationList = 16FFB3C2338453E99B74D534984F78AF /* Build configuration list for PBXNativeTarget "PullUpController" */; + buildPhases = ( + 7E66410792C029213D6F33CF4D65B8F6 /* Sources */, + 68399AA00D7ED1FAE5D85A2356B715F7 /* Frameworks */, + 5FBADA4F2CE146E6B2CDCEEB2F073F9C /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PullUpController; + productName = PullUpController; + productReference = 2C5AA6A33D63B64686BB7A5B6B78E35B /* PullUpController.framework */; + productType = "com.apple.product-type.framework"; + }; + 9B7B5B1BA4CD6DBC28237C8242FDAC97 /* Pods-PullUpController_Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 3271BBD358556CAFA956B27A0236CA70 /* Build configuration list for PBXNativeTarget "Pods-PullUpController_Example" */; + buildPhases = ( + 05A7696B59DEBED8A9BA94BD58F3B8E9 /* Sources */, + 7956F4F535B023771CF75A099890F970 /* Frameworks */, + 0D41126CBF9C129313DEC023CC93CF47 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + F5F72EFF015DAE50ACE2F392FFEE1F81 /* PBXTargetDependency */, + ); + name = "Pods-PullUpController_Example"; + productName = "Pods-PullUpController_Example"; + productReference = DA07B630F7B2CEB638C65108EE8C97AF /* Pods_PullUpController_Example.framework */; + productType = "com.apple.product-type.framework"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0930; + LastUpgradeCheck = 0930; + }; + buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7DB346D0F39D3F0E887471402A8071AB; + productRefGroup = B9052FE89FBCC9091AC04DA17B7D5702 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 9B7B5B1BA4CD6DBC28237C8242FDAC97 /* Pods-PullUpController_Example */, + 88A21A82856B75E85E451F68BE9B66F7 /* PullUpController */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 05A7696B59DEBED8A9BA94BD58F3B8E9 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E010BBE3A0DCA0581AEA0F8AE4F58BFC /* Pods-PullUpController_Example-dummy.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7E66410792C029213D6F33CF4D65B8F6 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F698D35311AF7A82832B9961D8567285 /* PullUpController-dummy.m in Sources */, + F12BA5B5DD5E409088A60EE72BAD20DD /* PullUpController.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + F5F72EFF015DAE50ACE2F392FFEE1F81 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = PullUpController; + target = 88A21A82856B75E85E451F68BE9B66F7 /* PullUpController */; + targetProxy = F8C04CCB6BD040FDB99775BF786172D0 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 41698083C7A3797BC8B6A26752DD851A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DCF8A9AF865D53B852B08F7253C08494 /* Pods-PullUpController_Example.debug.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PullUpController_Example/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 5B72497DEE340A664F983CB2EF6ED00D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE129AA35E6DD8D1AC44CED9A162F31F /* PullUpController.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PullUpController/PullUpController-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PullUpController/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PullUpController/PullUpController.modulemap"; + PRODUCT_MODULE_NAME = PullUpController; + PRODUCT_NAME = PullUpController; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + 74128B20A2ECF810A017E7EDD9B348C4 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = DE129AA35E6DD8D1AC44CED9A162F31F /* PullUpController.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/PullUpController/PullUpController-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/PullUpController/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/PullUpController/PullUpController.modulemap"; + PRODUCT_MODULE_NAME = PullUpController; + PRODUCT_NAME = PullUpController; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 8B33C5230DE4A9DFA6D8F46505DD7AF7 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_DEBUG=1", + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + B42B54097A876E8A982CBF5DAA91B1AB /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGNING_ALLOWED = NO; + CODE_SIGNING_REQUIRED = NO; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "POD_CONFIGURATION_RELEASE=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_INSTALLED_PRODUCT = NO; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Release; + }; + DE5E330B58FACE48D79870B93F2ACFF4 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 21F144D6F2B3882BC5FD9933E31927EA /* Pods-PullUpController_Example.release.xcconfig */; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-PullUpController_Example/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 16FFB3C2338453E99B74D534984F78AF /* Build configuration list for PBXNativeTarget "PullUpController" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 74128B20A2ECF810A017E7EDD9B348C4 /* Debug */, + 5B72497DEE340A664F983CB2EF6ED00D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8B33C5230DE4A9DFA6D8F46505DD7AF7 /* Debug */, + B42B54097A876E8A982CBF5DAA91B1AB /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 3271BBD358556CAFA956B27A0236CA70 /* Build configuration list for PBXNativeTarget "Pods-PullUpController_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 41698083C7A3797BC8B6A26752DD851A /* Debug */, + DE5E330B58FACE48D79870B93F2ACFF4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; +} diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Info.plist b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Info.plist new file mode 100644 index 0000000..2243fe6 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-acknowledgements.markdown b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-acknowledgements.markdown new file mode 100644 index 0000000..834e86a --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-acknowledgements.markdown @@ -0,0 +1,26 @@ +# Acknowledgements +This application makes use of the following third party libraries: + +## PullUpController + +Copyright (c) 2018 MarioIannotta + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +Generated by CocoaPods - https://cocoapods.org diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-acknowledgements.plist b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-acknowledgements.plist new file mode 100644 index 0000000..33c908f --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-acknowledgements.plist @@ -0,0 +1,58 @@ + + + + + PreferenceSpecifiers + + + FooterText + This application makes use of the following third party libraries: + Title + Acknowledgements + Type + PSGroupSpecifier + + + FooterText + Copyright (c) 2018 MarioIannotta <info@marioiannotta.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + License + MIT + Title + PullUpController + Type + PSGroupSpecifier + + + FooterText + Generated by CocoaPods - https://cocoapods.org + Title + + Type + PSGroupSpecifier + + + StringsTable + Acknowledgements + Title + Acknowledgements + + diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-dummy.m b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-dummy.m new file mode 100644 index 0000000..5f861a8 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_Pods_PullUpController_Example : NSObject +@end +@implementation PodsDummy_Pods_PullUpController_Example +@end diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-frameworks.sh b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-frameworks.sh new file mode 100755 index 0000000..26f1d46 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-frameworks.sh @@ -0,0 +1,153 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then + # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy + # frameworks to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" +mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + +COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" +SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" + +# Used as a return value for each invocation of `strip_invalid_archs` function. +STRIP_BINARY_RETVAL=0 + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +# Copies and strips a vendored framework +install_framework() +{ + if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then + local source="${BUILT_PRODUCTS_DIR}/$1" + elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then + local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" + elif [ -r "$1" ]; then + local source="$1" + fi + + local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + + if [ -L "${source}" ]; then + echo "Symlinked..." + source="$(readlink "${source}")" + fi + + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + + local basename + basename="$(basename -s .framework "$1")" + binary="${destination}/${basename}.framework/${basename}" + if ! [ -r "$binary" ]; then + binary="${destination}/${basename}" + fi + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then + strip_invalid_archs "$binary" + fi + + # Resign the code if required by the build settings to avoid unstable apps + code_sign_if_enabled "${destination}/$(basename "$1")" + + # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. + if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then + local swift_runtime_libs + swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) + for lib in $swift_runtime_libs; do + echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" + rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" + code_sign_if_enabled "${destination}/${lib}" + done + fi +} + +# Copies and strips a vendored dSYM +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + # Copy the dSYM into a the targets temp dir. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" + + local basename + basename="$(basename -s .framework.dSYM "$source")" + binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" + + # Strip invalid architectures so "fat" simulator / device frameworks work on device + if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then + strip_invalid_archs "$binary" + fi + + if [[ $STRIP_BINARY_RETVAL == 1 ]]; then + # Move the stripped file into its final destination. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" + else + # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. + touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" + fi + fi +} + +# Signs a framework with the provided identity +code_sign_if_enabled() { + if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then + # Use the current code_sign_identitiy + echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" + local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" + + if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + code_sign_cmd="$code_sign_cmd &" + fi + echo "$code_sign_cmd" + eval "$code_sign_cmd" + fi +} + +# Strip invalid architectures +strip_invalid_archs() { + binary="$1" + # Get architectures for current target binary + binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" + # Intersect them with the architectures we are building for + intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" + # If there are no archs supported by this binary then warn the user + if [[ -z "$intersected_archs" ]]; then + echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." + STRIP_BINARY_RETVAL=0 + return + fi + stripped="" + for arch in $binary_archs; do + if ! [[ "${ARCHS}" == *"$arch"* ]]; then + # Strip non-valid architectures in-place + lipo -remove "$arch" -output "$binary" "$binary" || exit 1 + stripped="$stripped $arch" + fi + done + if [[ "$stripped" ]]; then + echo "Stripped $binary of architectures:$stripped" + fi + STRIP_BINARY_RETVAL=1 +} + + +if [[ "$CONFIGURATION" == "Debug" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/PullUpController/PullUpController.framework" +fi +if [[ "$CONFIGURATION" == "Release" ]]; then + install_framework "${BUILT_PRODUCTS_DIR}/PullUpController/PullUpController.framework" +fi +if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then + wait +fi diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-resources.sh b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-resources.sh new file mode 100755 index 0000000..fe3f9c7 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-resources.sh @@ -0,0 +1,118 @@ +#!/bin/sh +set -e +set -u +set -o pipefail + +if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then + # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy + # resources to, so exit 0 (signalling the script phase was successful). + exit 0 +fi + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + +RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt +> "$RESOURCES_TO_COPY" + +XCASSET_FILES=() + +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + +case "${TARGETED_DEVICE_FAMILY:-}" in + 1,2) + TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" + ;; + 1) + TARGET_DEVICE_ARGS="--target-device iphone" + ;; + 2) + TARGET_DEVICE_ARGS="--target-device ipad" + ;; + 3) + TARGET_DEVICE_ARGS="--target-device tv" + ;; + 4) + TARGET_DEVICE_ARGS="--target-device watch" + ;; + *) + TARGET_DEVICE_ARGS="--target-device mac" + ;; +esac + +install_resource() +{ + if [[ "$1" = /* ]] ; then + RESOURCE_PATH="$1" + else + RESOURCE_PATH="${PODS_ROOT}/$1" + fi + if [[ ! -e "$RESOURCE_PATH" ]] ; then + cat << EOM +error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. +EOM + exit 1 + fi + case $RESOURCE_PATH in + *.storyboard) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.xib) + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true + ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} + ;; + *.framework) + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + ;; + *.xcdatamodel) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" + ;; + *.xcdatamodeld) + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true + xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" + ;; + *.xcmappingmodel) + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true + xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" + ;; + *.xcassets) + ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" + XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") + ;; + *) + echo "$RESOURCE_PATH" || true + echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" + ;; + esac +} + +mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then + mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" +fi +rm -f "$RESOURCES_TO_COPY" + +if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] +then + # Find all other xcassets (this unfortunately includes those of path pods and other targets). + OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) + while read line; do + if [[ $line != "${PODS_ROOT}*" ]]; then + XCASSET_FILES+=("$line") + fi + done <<<"$OTHER_XCASSETS" + + if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" + else + printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_BUILD_DIR}/assetcatalog_generated_info.plist" + fi +fi diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-umbrella.h b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-umbrella.h new file mode 100644 index 0000000..b347ce4 --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double Pods_PullUpController_ExampleVersionNumber; +FOUNDATION_EXPORT const unsigned char Pods_PullUpController_ExampleVersionString[]; + diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.debug.xcconfig b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.debug.xcconfig new file mode 100644 index 0000000..e2f38ed --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.debug.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PullUpController" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PullUpController/PullUpController.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "PullUpController" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.modulemap b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.modulemap new file mode 100644 index 0000000..91df9ac --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.modulemap @@ -0,0 +1,6 @@ +framework module Pods_PullUpController_Example { + umbrella header "Pods-PullUpController_Example-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.release.xcconfig b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.release.xcconfig new file mode 100644 index 0000000..e2f38ed --- /dev/null +++ b/Example/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.release.xcconfig @@ -0,0 +1,11 @@ +ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES +FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/PullUpController" +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' +OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/PullUpController/PullUpController.framework/Headers" +OTHER_LDFLAGS = $(inherited) -framework "PullUpController" +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_PODFILE_DIR_PATH = ${SRCROOT}/. +PODS_ROOT = ${SRCROOT}/Pods diff --git a/Example/Pods/Target Support Files/PullUpController/Info.plist b/Example/Pods/Target Support Files/PullUpController/Info.plist new file mode 100644 index 0000000..0d7bfa2 --- /dev/null +++ b/Example/Pods/Target Support Files/PullUpController/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + ${PRODUCT_BUNDLE_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.2.0 + CFBundleSignature + ???? + CFBundleVersion + ${CURRENT_PROJECT_VERSION} + NSPrincipalClass + + + diff --git a/Example/Pods/Target Support Files/PullUpController/PullUpController-dummy.m b/Example/Pods/Target Support Files/PullUpController/PullUpController-dummy.m new file mode 100644 index 0000000..0fecc86 --- /dev/null +++ b/Example/Pods/Target Support Files/PullUpController/PullUpController-dummy.m @@ -0,0 +1,5 @@ +#import +@interface PodsDummy_PullUpController : NSObject +@end +@implementation PodsDummy_PullUpController +@end diff --git a/Example/Pods/Target Support Files/PullUpController/PullUpController-prefix.pch b/Example/Pods/Target Support Files/PullUpController/PullUpController-prefix.pch new file mode 100644 index 0000000..beb2a24 --- /dev/null +++ b/Example/Pods/Target Support Files/PullUpController/PullUpController-prefix.pch @@ -0,0 +1,12 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + diff --git a/Example/Pods/Target Support Files/PullUpController/PullUpController-umbrella.h b/Example/Pods/Target Support Files/PullUpController/PullUpController-umbrella.h new file mode 100644 index 0000000..0ebd2b3 --- /dev/null +++ b/Example/Pods/Target Support Files/PullUpController/PullUpController-umbrella.h @@ -0,0 +1,16 @@ +#ifdef __OBJC__ +#import +#else +#ifndef FOUNDATION_EXPORT +#if defined(__cplusplus) +#define FOUNDATION_EXPORT extern "C" +#else +#define FOUNDATION_EXPORT extern +#endif +#endif +#endif + + +FOUNDATION_EXPORT double PullUpControllerVersionNumber; +FOUNDATION_EXPORT const unsigned char PullUpControllerVersionString[]; + diff --git a/Example/Pods/Target Support Files/PullUpController/PullUpController.modulemap b/Example/Pods/Target Support Files/PullUpController/PullUpController.modulemap new file mode 100644 index 0000000..d72c8bd --- /dev/null +++ b/Example/Pods/Target Support Files/PullUpController/PullUpController.modulemap @@ -0,0 +1,6 @@ +framework module PullUpController { + umbrella header "PullUpController-umbrella.h" + + export * + module * { export * } +} diff --git a/Example/Pods/Target Support Files/PullUpController/PullUpController.xcconfig b/Example/Pods/Target Support Files/PullUpController/PullUpController.xcconfig new file mode 100644 index 0000000..89cd387 --- /dev/null +++ b/Example/Pods/Target Support Files/PullUpController/PullUpController.xcconfig @@ -0,0 +1,10 @@ +CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PullUpController +GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 +OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" +PODS_BUILD_DIR = ${BUILD_DIR} +PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) +PODS_ROOT = ${SRCROOT} +PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. +PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} +SKIP_INSTALL = YES +SWIFT_VERSION = 4.2 diff --git a/Example/PullUpController.xcodeproj/project.pbxproj b/Example/PullUpController.xcodeproj/project.pbxproj new file mode 100644 index 0000000..fafdee2 --- /dev/null +++ b/Example/PullUpController.xcodeproj/project.pbxproj @@ -0,0 +1,414 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 607FACD51AFB9204008FA782 /* AppDelegate.swift */; }; + AC44912120DBFFBE00F98838 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC44911920DBFFBE00F98838 /* LaunchScreen.storyboard */; }; + AC44912320DBFFBE00F98838 /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC44911C20DBFFBE00F98838 /* SearchViewController.swift */; }; + AC44912420DBFFBE00F98838 /* MapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC44911D20DBFFBE00F98838 /* MapViewController.swift */; }; + AC44912520DBFFBE00F98838 /* SearchResultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC44911E20DBFFBE00F98838 /* SearchResultCell.swift */; }; + AC44912620DBFFBE00F98838 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC44911F20DBFFBE00F98838 /* Main.storyboard */; }; + AC44912720DBFFBE00F98838 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AC44912020DBFFBE00F98838 /* Assets.xcassets */; }; + E969182522AF18CFABF54185 /* Pods_PullUpController_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFA23D4840D57C4607249C0D /* Pods_PullUpController_Example.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 293D0A2418F9B613A61561F3 /* PullUpController.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = PullUpController.podspec; path = ../PullUpController.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 56A8923EF4695AE64CB0A36A /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = ""; }; + 5F0B85693EE28EE7439643E7 /* Pods_PullUpController_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PullUpController_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 607FACD01AFB9204008FA782 /* PullUpController_Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PullUpController_Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 607FACD51AFB9204008FA782 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 6D13751B90ADB8E6A7085A3F /* Pods-PullUpController_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PullUpController_Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.release.xcconfig"; sourceTree = ""; }; + 94B8AB427B262E433795430A /* Pods-PullUpController_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PullUpController_Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PullUpController_Tests/Pods-PullUpController_Tests.debug.xcconfig"; sourceTree = ""; }; + 9AB34C6007A366EB15327B6E /* Pods-PullUpController_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PullUpController_Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example.debug.xcconfig"; sourceTree = ""; }; + AC44911920DBFFBE00F98838 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; + AC44911A20DBFFBE00F98838 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + AC44911C20DBFFBE00F98838 /* SearchViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = ""; }; + AC44911D20DBFFBE00F98838 /* MapViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MapViewController.swift; sourceTree = ""; }; + AC44911E20DBFFBE00F98838 /* SearchResultCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchResultCell.swift; sourceTree = ""; }; + AC44911F20DBFFBE00F98838 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; + AC44912020DBFFBE00F98838 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + BFA23D4840D57C4607249C0D /* Pods_PullUpController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PullUpController_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + F59F16287664980C2DF5643A /* Pods-PullUpController_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PullUpController_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PullUpController_Tests/Pods-PullUpController_Tests.release.xcconfig"; sourceTree = ""; }; + F97967A110801D095B7F4727 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 607FACCD1AFB9204008FA782 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + E969182522AF18CFABF54185 /* Pods_PullUpController_Example.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 607FACC71AFB9204008FA782 = { + isa = PBXGroup; + children = ( + 607FACF51AFB993E008FA782 /* Podspec Metadata */, + 607FACD21AFB9204008FA782 /* Example for PullUpController */, + 607FACD11AFB9204008FA782 /* Products */, + A34E4D9765C4E394C167B4D4 /* Pods */, + 6E774B959D15037B1657CE44 /* Frameworks */, + ); + sourceTree = ""; + }; + 607FACD11AFB9204008FA782 /* Products */ = { + isa = PBXGroup; + children = ( + 607FACD01AFB9204008FA782 /* PullUpController_Example.app */, + ); + name = Products; + sourceTree = ""; + }; + 607FACD21AFB9204008FA782 /* Example for PullUpController */ = { + isa = PBXGroup; + children = ( + 607FACD51AFB9204008FA782 /* AppDelegate.swift */, + AC44912020DBFFBE00F98838 /* Assets.xcassets */, + AC44911820DBFFBE00F98838 /* Supporting files */, + AC44911B20DBFFBE00F98838 /* UI */, + ); + name = "Example for PullUpController"; + path = PullUpController; + sourceTree = ""; + }; + 607FACF51AFB993E008FA782 /* Podspec Metadata */ = { + isa = PBXGroup; + children = ( + 293D0A2418F9B613A61561F3 /* PullUpController.podspec */, + F97967A110801D095B7F4727 /* README.md */, + 56A8923EF4695AE64CB0A36A /* LICENSE */, + ); + name = "Podspec Metadata"; + sourceTree = ""; + }; + 6E774B959D15037B1657CE44 /* Frameworks */ = { + isa = PBXGroup; + children = ( + BFA23D4840D57C4607249C0D /* Pods_PullUpController_Example.framework */, + 5F0B85693EE28EE7439643E7 /* Pods_PullUpController_Tests.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + A34E4D9765C4E394C167B4D4 /* Pods */ = { + isa = PBXGroup; + children = ( + 9AB34C6007A366EB15327B6E /* Pods-PullUpController_Example.debug.xcconfig */, + 6D13751B90ADB8E6A7085A3F /* Pods-PullUpController_Example.release.xcconfig */, + 94B8AB427B262E433795430A /* Pods-PullUpController_Tests.debug.xcconfig */, + F59F16287664980C2DF5643A /* Pods-PullUpController_Tests.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + AC44911820DBFFBE00F98838 /* Supporting files */ = { + isa = PBXGroup; + children = ( + AC44911920DBFFBE00F98838 /* LaunchScreen.storyboard */, + AC44911A20DBFFBE00F98838 /* Info.plist */, + ); + path = "Supporting files"; + sourceTree = ""; + }; + AC44911B20DBFFBE00F98838 /* UI */ = { + isa = PBXGroup; + children = ( + AC44911F20DBFFBE00F98838 /* Main.storyboard */, + AC44911D20DBFFBE00F98838 /* MapViewController.swift */, + AC44911E20DBFFBE00F98838 /* SearchResultCell.swift */, + AC44911C20DBFFBE00F98838 /* SearchViewController.swift */, + ); + path = UI; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 607FACCF1AFB9204008FA782 /* PullUpController_Example */ = { + isa = PBXNativeTarget; + buildConfigurationList = 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "PullUpController_Example" */; + buildPhases = ( + 8909FE713AFF2BA76756295B /* [CP] Check Pods Manifest.lock */, + 607FACCC1AFB9204008FA782 /* Sources */, + 607FACCD1AFB9204008FA782 /* Frameworks */, + 607FACCE1AFB9204008FA782 /* Resources */, + 6426681623BA90E723285041 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PullUpController_Example; + productName = PullUpController; + productReference = 607FACD01AFB9204008FA782 /* PullUpController_Example.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 607FACC81AFB9204008FA782 /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0830; + LastUpgradeCheck = 0940; + ORGANIZATIONNAME = CocoaPods; + TargetAttributes = { + 607FACCF1AFB9204008FA782 = { + CreatedOnToolsVersion = 6.3.1; + LastSwiftMigration = 0900; + }; + }; + }; + buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "PullUpController" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 607FACC71AFB9204008FA782; + productRefGroup = 607FACD11AFB9204008FA782 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 607FACCF1AFB9204008FA782 /* PullUpController_Example */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 607FACCE1AFB9204008FA782 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AC44912620DBFFBE00F98838 /* Main.storyboard in Resources */, + AC44912720DBFFBE00F98838 /* Assets.xcassets in Resources */, + AC44912120DBFFBE00F98838 /* LaunchScreen.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 6426681623BA90E723285041 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/PullUpController/PullUpController.framework", + ); + name = "[CP] Embed Pods Frameworks"; + outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PullUpController.framework", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-PullUpController_Example/Pods-PullUpController_Example-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + 8909FE713AFF2BA76756295B /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-PullUpController_Example-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 607FACCC1AFB9204008FA782 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + AC44912320DBFFBE00F98838 /* SearchViewController.swift in Sources */, + AC44912420DBFFBE00F98838 /* MapViewController.swift in Sources */, + AC44912520DBFFBE00F98838 /* SearchResultCell.swift in Sources */, + 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 607FACED1AFB9204008FA782 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 607FACEE1AFB9204008FA782 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 607FACF01AFB9204008FA782 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9AB34C6007A366EB15327B6E /* Pods-PullUpController_Example.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "$(SRCROOT)/PullUpController/Supporting files/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MODULE_NAME = ExampleApp; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Debug; + }; + 607FACF11AFB9204008FA782 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 6D13751B90ADB8E6A7085A3F /* Pods-PullUpController_Example.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + INFOPLIST_FILE = "$(SRCROOT)/PullUpController/Supporting files/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MODULE_NAME = ExampleApp; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "PullUpController" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 607FACED1AFB9204008FA782 /* Debug */, + 607FACEE1AFB9204008FA782 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 607FACEF1AFB9204008FA782 /* Build configuration list for PBXNativeTarget "PullUpController_Example" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 607FACF01AFB9204008FA782 /* Debug */, + 607FACF11AFB9204008FA782 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 607FACC81AFB9204008FA782 /* Project object */; +} diff --git a/PullUpControllerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Example/PullUpController.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 53% rename from PullUpControllerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Example/PullUpController.xcodeproj/project.xcworkspace/contents.xcworkspacedata index 8dfc177..0ac21b6 100644 --- a/PullUpControllerDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ b/Example/PullUpController.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -2,6 +2,6 @@ + location = "self:PullUpController.xcodeproj"> diff --git a/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme b/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme new file mode 100644 index 0000000..463c029 --- /dev/null +++ b/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Example/PullUpController.xcworkspace/contents.xcworkspacedata b/Example/PullUpController.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..655019a --- /dev/null +++ b/Example/PullUpController.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/Example/PullUpController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Example/PullUpController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Example/PullUpController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/PullUpControllerDemo/AppDelegate.swift b/Example/PullUpController/AppDelegate.swift similarity index 100% rename from PullUpControllerDemo/AppDelegate.swift rename to Example/PullUpController/AppDelegate.swift diff --git a/PullUpControllerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Example/PullUpController/Assets.xcassets/AppIcon.appiconset/Contents.json similarity index 100% rename from PullUpControllerDemo/Assets.xcassets/AppIcon.appiconset/Contents.json rename to Example/PullUpController/Assets.xcassets/AppIcon.appiconset/Contents.json diff --git a/PullUpControllerDemo/Assets.xcassets/Contents.json b/Example/PullUpController/Assets.xcassets/Contents.json similarity index 100% rename from PullUpControllerDemo/Assets.xcassets/Contents.json rename to Example/PullUpController/Assets.xcassets/Contents.json diff --git a/PullUpControllerDemo/Info.plist b/Example/PullUpController/Supporting files/Info.plist similarity index 100% rename from PullUpControllerDemo/Info.plist rename to Example/PullUpController/Supporting files/Info.plist diff --git a/PullUpControllerDemo/Base.lproj/LaunchScreen.storyboard b/Example/PullUpController/Supporting files/LaunchScreen.storyboard similarity index 100% rename from PullUpControllerDemo/Base.lproj/LaunchScreen.storyboard rename to Example/PullUpController/Supporting files/LaunchScreen.storyboard diff --git a/PullUpControllerDemo/Base.lproj/Main.storyboard b/Example/PullUpController/UI/Main.storyboard similarity index 100% rename from PullUpControllerDemo/Base.lproj/Main.storyboard rename to Example/PullUpController/UI/Main.storyboard diff --git a/PullUpControllerDemo/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift similarity index 100% rename from PullUpControllerDemo/MapViewController.swift rename to Example/PullUpController/UI/MapViewController.swift diff --git a/PullUpControllerDemo/SearchResultCell.swift b/Example/PullUpController/UI/SearchResultCell.swift similarity index 100% rename from PullUpControllerDemo/SearchResultCell.swift rename to Example/PullUpController/UI/SearchResultCell.swift diff --git a/PullUpControllerDemo/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift similarity index 99% rename from PullUpControllerDemo/SearchViewController.swift rename to Example/PullUpController/UI/SearchViewController.swift index 8dd6f2e..ada1e41 100644 --- a/PullUpControllerDemo/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -8,6 +8,7 @@ import UIKit import MapKit +import PullUpController class SearchViewController: PullUpController { diff --git a/PullUpController.podspec b/PullUpController.podspec index bbdf54e..d720e70 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.1.0' + s.version = '0.2.0' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'Mario Iannotta' => 'info@marioiannotta.com' } s.source = { :git => 'https://github.com/MarioIannotta/PullUpController.git', :tag => s.version.to_s } s.ios.deployment_target = '9.0' - s.source_files = 'PullUpController/*.swift' - s.pod_target_xcconfig = { "SWIFT_VERSION" => "4.0" } + s.source_files = 'PullUpController/**/*.swift' + s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.1' } end diff --git a/PullUpControllerDemo.xcodeproj/project.pbxproj b/PullUpControllerDemo.xcodeproj/project.pbxproj deleted file mode 100644 index 26b70f3..0000000 --- a/PullUpControllerDemo.xcodeproj/project.pbxproj +++ /dev/null @@ -1,349 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 48; - objects = { - -/* Begin PBXBuildFile section */ - AC1A74C81FACEEAE00392CB8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1A74C71FACEEAE00392CB8 /* AppDelegate.swift */; }; - AC1A74CA1FACEEAE00392CB8 /* MapViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1A74C91FACEEAE00392CB8 /* MapViewController.swift */; }; - AC1A74CD1FACEEAE00392CB8 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC1A74CB1FACEEAE00392CB8 /* Main.storyboard */; }; - AC1A74CF1FACEEAE00392CB8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AC1A74CE1FACEEAE00392CB8 /* Assets.xcassets */; }; - AC1A74D21FACEEAE00392CB8 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC1A74D01FACEEAE00392CB8 /* LaunchScreen.storyboard */; }; - AC1A74DB1FACEED700392CB8 /* PullUpController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1A74DA1FACEED700392CB8 /* PullUpController.swift */; }; - AC1A74DD1FACF09000392CB8 /* SearchViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC1A74DC1FACF09000392CB8 /* SearchViewController.swift */; }; - ACE403581FADF1C500898D01 /* SearchResultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACE403571FADF1C500898D01 /* SearchResultCell.swift */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - AC1A74C41FACEEAD00392CB8 /* PullUpControllerDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PullUpControllerDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - AC1A74C71FACEEAE00392CB8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - AC1A74C91FACEEAE00392CB8 /* MapViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MapViewController.swift; sourceTree = ""; }; - AC1A74CC1FACEEAE00392CB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - AC1A74CE1FACEEAE00392CB8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - AC1A74D11FACEEAE00392CB8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - AC1A74D31FACEEAE00392CB8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - AC1A74DA1FACEED700392CB8 /* PullUpController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PullUpController.swift; sourceTree = ""; }; - AC1A74DC1FACF09000392CB8 /* SearchViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchViewController.swift; sourceTree = ""; }; - ACE403571FADF1C500898D01 /* SearchResultCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultCell.swift; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - AC1A74C11FACEEAD00392CB8 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - AC1A74BB1FACEEAD00392CB8 = { - isa = PBXGroup; - children = ( - AC1A74D91FACEECD00392CB8 /* PullUpController */, - AC1A74C61FACEEAD00392CB8 /* PullUpControllerDemo */, - AC1A74C51FACEEAD00392CB8 /* Products */, - ); - sourceTree = ""; - }; - AC1A74C51FACEEAD00392CB8 /* Products */ = { - isa = PBXGroup; - children = ( - AC1A74C41FACEEAD00392CB8 /* PullUpControllerDemo.app */, - ); - name = Products; - sourceTree = ""; - }; - AC1A74C61FACEEAD00392CB8 /* PullUpControllerDemo */ = { - isa = PBXGroup; - children = ( - AC1A74D31FACEEAE00392CB8 /* Info.plist */, - AC1A74C71FACEEAE00392CB8 /* AppDelegate.swift */, - AC1A74C91FACEEAE00392CB8 /* MapViewController.swift */, - AC1A74DC1FACF09000392CB8 /* SearchViewController.swift */, - ACE403571FADF1C500898D01 /* SearchResultCell.swift */, - AC1A74CE1FACEEAE00392CB8 /* Assets.xcassets */, - AC1A74D01FACEEAE00392CB8 /* LaunchScreen.storyboard */, - AC1A74CB1FACEEAE00392CB8 /* Main.storyboard */, - ); - path = PullUpControllerDemo; - sourceTree = ""; - }; - AC1A74D91FACEECD00392CB8 /* PullUpController */ = { - isa = PBXGroup; - children = ( - AC1A74DA1FACEED700392CB8 /* PullUpController.swift */, - ); - path = PullUpController; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - AC1A74C31FACEEAD00392CB8 /* PullUpControllerDemo */ = { - isa = PBXNativeTarget; - buildConfigurationList = AC1A74D61FACEEAE00392CB8 /* Build configuration list for PBXNativeTarget "PullUpControllerDemo" */; - buildPhases = ( - AC1A74C01FACEEAD00392CB8 /* Sources */, - AC1A74C11FACEEAD00392CB8 /* Frameworks */, - AC1A74C21FACEEAD00392CB8 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = PullUpControllerDemo; - productName = SliderControllerDemo; - productReference = AC1A74C41FACEEAD00392CB8 /* PullUpControllerDemo.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - AC1A74BC1FACEEAD00392CB8 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 0910; - LastUpgradeCheck = 0940; - ORGANIZATIONNAME = Mario; - TargetAttributes = { - AC1A74C31FACEEAD00392CB8 = { - CreatedOnToolsVersion = 9.1; - ProvisioningStyle = Automatic; - }; - }; - }; - buildConfigurationList = AC1A74BF1FACEEAD00392CB8 /* Build configuration list for PBXProject "PullUpControllerDemo" */; - compatibilityVersion = "Xcode 8.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = AC1A74BB1FACEEAD00392CB8; - productRefGroup = AC1A74C51FACEEAD00392CB8 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - AC1A74C31FACEEAD00392CB8 /* PullUpControllerDemo */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - AC1A74C21FACEEAD00392CB8 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - AC1A74D21FACEEAE00392CB8 /* LaunchScreen.storyboard in Resources */, - AC1A74CF1FACEEAE00392CB8 /* Assets.xcassets in Resources */, - AC1A74CD1FACEEAE00392CB8 /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - AC1A74C01FACEEAD00392CB8 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - AC1A74CA1FACEEAE00392CB8 /* MapViewController.swift in Sources */, - AC1A74DB1FACEED700392CB8 /* PullUpController.swift in Sources */, - AC1A74DD1FACF09000392CB8 /* SearchViewController.swift in Sources */, - AC1A74C81FACEEAE00392CB8 /* AppDelegate.swift in Sources */, - ACE403581FADF1C500898D01 /* SearchResultCell.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - AC1A74CB1FACEEAE00392CB8 /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - AC1A74CC1FACEEAE00392CB8 /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - AC1A74D01FACEEAE00392CB8 /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - AC1A74D11FACEEAE00392CB8 /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - AC1A74D41FACEEAE00392CB8 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - }; - name = Debug; - }; - AC1A74D51FACEEAE00392CB8 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - AC1A74D71FACEEAE00392CB8 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = PullUpControllerDemo/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.PullUpControllerDemo; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - AC1A74D81FACEEAE00392CB8 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = PullUpControllerDemo/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.PullUpControllerDemo; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - AC1A74BF1FACEEAD00392CB8 /* Build configuration list for PBXProject "PullUpControllerDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - AC1A74D41FACEEAE00392CB8 /* Debug */, - AC1A74D51FACEEAE00392CB8 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - AC1A74D61FACEEAE00392CB8 /* Build configuration list for PBXNativeTarget "PullUpControllerDemo" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - AC1A74D71FACEEAE00392CB8 /* Debug */, - AC1A74D81FACEEAE00392CB8 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = AC1A74BC1FACEEAD00392CB8 /* Project object */; -} diff --git a/_Pods.xcodeproj b/_Pods.xcodeproj new file mode 120000 index 0000000..3c5a8e7 --- /dev/null +++ b/_Pods.xcodeproj @@ -0,0 +1 @@ +Example/Pods/Pods.xcodeproj \ No newline at end of file From 03087eb60eb32fa7f7f9533f6dcaba7c2c694bbc Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 21 Jun 2018 18:08:10 +0200 Subject: [PATCH 09/73] Update README.md Add absolute url for demo image --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b314248..940cdef 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Create your own pull up controller with multiple sticky points like in iOS Maps [![Swift 4](https://img.shields.io/badge/Swift-4-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Cocoapods Compatible](https://img.shields.io/cocoapods/v/PullUpController.svg)](https://img.shields.io/cocoapods/v/PullUpController.svg) - + # Features - Multiple *sticky* points From c0a455afe2a441362073723a72fa3badaf39bf38 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 21 Jun 2018 18:20:39 +0200 Subject: [PATCH 10/73] Add onDrag closure --- Example/PullUpController/UI/MapViewController.swift | 1 + Example/PullUpController/UI/SearchViewController.swift | 8 ++++++-- PullUpController/PullUpController.swift | 8 ++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/Example/PullUpController/UI/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift index d474c6a..a737314 100644 --- a/Example/PullUpController/UI/MapViewController.swift +++ b/Example/PullUpController/UI/MapViewController.swift @@ -34,5 +34,6 @@ class MapViewController: UIViewController { mapView.setRegion(region, animated: true) } + } diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index ada1e41..727df71 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -35,13 +35,17 @@ class SearchViewController: PullUpController { tableView.attach(to: self) setupDataSource() - self.willMoveToStickyPoint = { point in + willMoveToStickyPoint = { point in print("willMoveToStickyPoint \(point)") } - self.didMoveToStickyPoint = { point in + didMoveToStickyPoint = { point in print("didMoveToStickyPoint \(point)") } + + onDrag = { point in + print("onDrag: \(point)") + } } override func viewDidLayoutSubviews() { diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 1253fac..e64f899 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -24,6 +24,12 @@ open class PullUpController: UIViewController { */ open var didMoveToStickyPoint: ((_ point: CGFloat) -> Void)? + /** + The closure to execute when the view controller's view is dragged. + The point, expressed in the pull up controller parent coordinate system, is provided in the closure parameter. + */ + open var onDrag: ((_ point: CGFloat) -> Void)? + /** The desired height in screen units expressed in the pull up controller coordinate system that will be initially showed. The default value is 50. @@ -199,6 +205,8 @@ open class PullUpController: UIViewController { topConstraint.constant = min(topConstraint.constant, parentViewHeight - pullUpControllerPreviewOffset) } + onDrag?(topConstraint.constant) + if gestureRecognizer.state == .ended { let yVelocity = gestureRecognizer.velocity(in: view).y // v = px/s let oldTopConstraintConstant = topConstraint.constant From 0c866ab93cd8c783545d10202cf86c0e1232ca30 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Mon, 9 Jul 2018 20:59:28 +0200 Subject: [PATCH 11/73] =?UTF-8?q?=E2=80=9CFix=E2=80=9D=20Issue=20#14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- PullUpController/PullUpController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index e64f899..6444462 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -285,6 +285,7 @@ extension UIViewController { - parameter pullUpController: the pull up controller to add as a child of the current view controller. */ open func addPullUpController(_ pullUpController: PullUpController) { + assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") addChildViewController(pullUpController) pullUpController.view.translatesAutoresizingMaskIntoConstraints = false From 34da665b2ea7fcaf4df4551a5d711704cf6a6bbc Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Mon, 9 Jul 2018 21:25:41 +0200 Subject: [PATCH 12/73] Improve animation APIs - Add animated to pullUpControllerMoveToVisiblePoint - Add a method to remove the pull up controller (this also fix the issue #15) --- Example/PullUpController/UI/Main.storyboard | 46 ++++++++++++++---- .../UI/MapViewController.swift | 16 ++++++- .../UI/SearchViewController.swift | 4 +- PullUpController/PullUpController.swift | 48 ++++++++++++++----- 4 files changed, 91 insertions(+), 23 deletions(-) diff --git a/Example/PullUpController/UI/Main.storyboard b/Example/PullUpController/UI/Main.storyboard index fb72773..b8ba9d8 100644 --- a/Example/PullUpController/UI/Main.storyboard +++ b/Example/PullUpController/UI/Main.storyboard @@ -1,19 +1,19 @@ - + - + - + - + @@ -46,18 +46,30 @@ + + + + + + + + + + + + - + - + @@ -120,7 +132,7 @@ - + @@ -196,7 +208,25 @@ - + + + + + + + + + + + + + + + + + + + diff --git a/Example/PullUpController/UI/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift index a737314..5ebd502 100644 --- a/Example/PullUpController/UI/MapViewController.swift +++ b/Example/PullUpController/UI/MapViewController.swift @@ -25,7 +25,7 @@ class MapViewController: UIViewController { .instantiateViewController(withIdentifier: "SearchViewController") as? SearchViewController else { return } - addPullUpController(pullUpController) + addPullUpController(pullUpController, animated: true) } func zoom(to location: CLLocationCoordinate2D) { @@ -35,5 +35,19 @@ class MapViewController: UIViewController { mapView.setRegion(region, animated: true) } + @IBAction private func addButtonTapped() { + guard + childViewControllers.filter({ $0 is SearchViewController }).count == 0 + else { return } + addPullUpController() + } + + @IBAction private func removeButtonTapped() { + guard + let pullUpController = childViewControllers.filter({ $0 is SearchViewController }).first as? SearchViewController + else { return } + removePullUpController(pullUpController, animated: true) + } + } diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index 727df71..802906c 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -94,7 +94,7 @@ extension SearchViewController: UISearchBarDelegate { func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) { if let lastStickyPoint = pullUpControllerAllStickyPoints.last { - pullUpControllerMoveToVisiblePoint(lastStickyPoint, completion: nil) + pullUpControllerMoveToVisiblePoint(lastStickyPoint, animated: true, completion: nil) } } @@ -126,7 +126,7 @@ extension SearchViewController: UITableViewDataSource, UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) view.endEditing(true) - pullUpControllerMoveToVisiblePoint(pullUpControllerMiddleStickyPoints[0], completion: nil) + pullUpControllerMoveToVisiblePoint(pullUpControllerMiddleStickyPoints[0], animated: true, completion: nil) (parent as? MapViewController)?.zoom(to: locations[indexPath.row].location) } diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 6444462..bd9a2ac 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -106,21 +106,26 @@ open class PullUpController: UIViewController { You may use on of `pullUpControllerAllStickyPoints` item to provide a valid visible point. - parameter visiblePoint: the y value to make visible, in screen units expressed in the pull up controller coordinate system. + - parameter animated: Pass true to animate the move; otherwise, pass false - parameter completion: The closure to execute after the animation is completed. This block has no return value and takes no parameters. You may specify nil for this parameter. */ - open func pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, completion: (() -> Void)?) { + open func pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, animated: Bool, completion: (() -> Void)?) { guard isPortrait else { return } topConstraint?.constant = (parent?.view.frame.height ?? 0) - visiblePoint - UIView.animate( - withDuration: 0.3, - animations: { [weak self] in - self?.parent?.view?.layoutIfNeeded() - }, - completion: { _ in - completion?() - } - ) + if animated { + UIView.animate( + withDuration: 0.3, + animations: { [weak self] in + self?.parent?.view?.layoutIfNeeded() + }, + completion: { _ in + completion?() + }) + } else { + parent?.view?.layoutIfNeeded() + completion?() + } } open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { @@ -140,7 +145,7 @@ open class PullUpController: UIViewController { coordinator.animate(alongsideTransition: { [weak self] coordinator in self?.refreshConstraints(size: size) if let targetStickyPoint = targetStickyPoint { - self?.pullUpControllerMoveToVisiblePoint(targetStickyPoint, completion: nil) + self?.pullUpControllerMoveToVisiblePoint(targetStickyPoint, animated: true, completion: nil) } }) } @@ -284,16 +289,35 @@ extension UIViewController { Adds the specified pull up view controller as a child of the current view controller. - parameter pullUpController: the pull up controller to add as a child of the current view controller. */ - open func addPullUpController(_ pullUpController: PullUpController) { + open func addPullUpController(_ pullUpController: PullUpController, animated: Bool) { assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") addChildViewController(pullUpController) pullUpController.view.translatesAutoresizingMaskIntoConstraints = false view.addSubview(pullUpController.view) + pullUpController.view.frame = CGRect(origin: CGPoint(x: pullUpController.view.frame.origin.x, + y: view.bounds.height), + size: pullUpController.view.frame.size) pullUpController.setupPanGestureRecognizer() pullUpController.setupConstraints() pullUpController.refreshConstraints(size: view.frame.size) + + if animated { + UIView.animate(withDuration: 0.3) { [weak self] in + self?.view.layoutIfNeeded() + } + } else { + view.layoutIfNeeded() + } + } + + open func removePullUpController(_ pullUpController: PullUpController, animated: Bool) { + pullUpController.pullUpControllerMoveToVisiblePoint(0, animated: animated) { + pullUpController.willMove(toParentViewController: nil) + pullUpController.view.removeFromSuperview() + pullUpController.removeFromParentViewController() + } } } From b3d919dd23c6621ec67286e5c2a6d3e680d8d8da Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Mon, 9 Jul 2018 21:30:02 +0200 Subject: [PATCH 13/73] Bump podspec version --- PullUpController.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index d720e70..d84c443 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.2.0' + s.version = '0.3.0' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } From b3363d9f9e8c4a3a257054575969db6944dae95a Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 17 Jul 2018 09:30:20 +0200 Subject: [PATCH 14/73] Add CodeClimate badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 940cdef..74456cc 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Create your own pull up controller with multiple sticky points like in iOS Maps )](https://developer.apple.com/iphone/index.action) [![Swift 4](https://img.shields.io/badge/Swift-4-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Cocoapods Compatible](https://img.shields.io/cocoapods/v/PullUpController.svg)](https://img.shields.io/cocoapods/v/PullUpController.svg) +[![Maintainability](https://api.codeclimate.com/v1/badges/ab0e3ab724774c9b5974/maintainability)](https://codeclimate.com/github/MarioIannotta/PullUpController/maintainability) From 3ccc13a541d6fe4b9809130e57fbe6887ed5f814 Mon Sep 17 00:00:00 2001 From: Christopher Hannah Date: Mon, 6 Aug 2018 11:37:26 +0100 Subject: [PATCH 15/73] Detach UIScrollView from PullUpController (#19) --- PullUpController/PullUpController.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index bd9a2ac..8211d64 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -332,4 +332,12 @@ extension UIScrollView { panGestureRecognizer.addTarget(pullUpController, action: #selector(pullUpController.handleInternalScrollViewPanGestureRecognizer(_:))) } + /** + Remove the scroll view from the pull up controller so it no longer moves with the scroll view content. + - parameter pullUpController: the pull up controller to be removed from controlling the scroll view. + */ + open func detach(from pullUpController: PullUpController) { + panGestureRecognizer.removeTarget(pullUpController, action: #selector(pullUpController.handleInternalScrollViewPanGestureRecognizer(_:))) + } + } From 5980ac874cfddaec1777c61e0c464f50242d1be2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Da=CC=A8bkowski?= <> Date: Tue, 7 Aug 2018 11:19:51 +0200 Subject: [PATCH 16/73] fix did move --- PullUpController/PullUpController.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 8211d64..6d24a59 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -253,6 +253,7 @@ open class PullUpController: UIViewController { withDuration: animationDuration, animations: { [weak self] in self?.parent?.view.layoutIfNeeded() + }, completion: { [weak self] b in let point = (self?.parent?.view.frame.height ?? 0.0) - (self?.topConstraint?.constant ?? 0.0) self?.didMoveToStickyPoint?(point) } From 69a8c95e54cd91568bf261a4a9e7397938919360 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Artur=20Da=CC=A8bkowski?= <> Date: Tue, 7 Aug 2018 14:18:39 +0200 Subject: [PATCH 17/73] Code review remarks --- PullUpController/PullUpController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 6d24a59..5d65776 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -253,7 +253,8 @@ open class PullUpController: UIViewController { withDuration: animationDuration, animations: { [weak self] in self?.parent?.view.layoutIfNeeded() - }, completion: { [weak self] b in + }, + completion: { [weak self] _ in let point = (self?.parent?.view.frame.height ?? 0.0) - (self?.topConstraint?.constant ?? 0.0) self?.didMoveToStickyPoint?(point) } From 3ef7316c9ced420381828e2692e3ffa390e04a63 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 14 Aug 2018 21:48:16 +0200 Subject: [PATCH 18/73] Fix #17 --- PullUpController/PullUpController.swift | 117 +++++++++++++++--------- 1 file changed, 72 insertions(+), 45 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 5d65776..3a3a402 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -99,6 +99,10 @@ open class PullUpController: UIViewController { private var portraitPreviousStickyPointIndex: Int? + fileprivate weak var internalScrollView: UIScrollView? + + private var initialInternalScrollViewContentOffset: CGPoint = .zero + // MARK: - Open methods /** @@ -110,7 +114,9 @@ open class PullUpController: UIViewController { - parameter completion: The closure to execute after the animation is completed. This block has no return value and takes no parameters. You may specify nil for this parameter. */ open func pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, animated: Bool, completion: (() -> Void)?) { - guard isPortrait else { return } + guard + isPortrait + else { return } topConstraint?.constant = (parent?.view.frame.height ?? 0) - visiblePoint if animated { @@ -156,13 +162,16 @@ open class PullUpController: UIViewController { panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestureRecognizer(_:))) panGestureRecognizer?.minimumNumberOfTouches = 1 panGestureRecognizer?.maximumNumberOfTouches = 1 + panGestureRecognizer?.delegate = self if let panGestureRecognizer = panGestureRecognizer { view.addGestureRecognizer(panGestureRecognizer) } } fileprivate func setupConstraints() { - guard let parentView = parent?.view else { return } + guard + let parentView = parent?.view + else { return } topConstraint = view.topAnchor.constraint(equalTo: parentView.topAnchor, constant: 0) leftConstraint = view.leftAnchor.constraint(equalTo: parentView.leftAnchor, constant: 0) @@ -197,60 +206,69 @@ open class PullUpController: UIViewController { guard isPortrait, let topConstraint = topConstraint, + let lastStickyPoint = pullUpControllerAllStickyPoints.last, let parentViewHeight = parent?.view.frame.height else { return } - let yTranslation = gestureRecognizer.translation(in: view).y - gestureRecognizer.setTranslation(.zero, in: view) - - topConstraint.constant += yTranslation - - if !pullUpControllerIsBouncingEnabled { - topConstraint.constant = max(topConstraint.constant, parentViewHeight - pullUpControllerPreferredSize.height) - topConstraint.constant = min(topConstraint.constant, parentViewHeight - pullUpControllerPreviewOffset) - } - - onDrag?(topConstraint.constant) - - if gestureRecognizer.state == .ended { + switch gestureRecognizer.state { + case .began: + initialInternalScrollViewContentOffset = internalScrollView?.contentOffset ?? .zero + + case .changed: + var shouldUpdateTopOffset = false + let scrollViewPanVelocity = internalScrollView?.panGestureRecognizer.velocity(in: view).y ?? 0 + if scrollViewPanVelocity != 0 { + let isScrollingDown = scrollViewPanVelocity > 0 + let shouldScrollingDownTriggerGestureRecognizer = isScrollingDown && internalScrollView?.contentOffset.y ?? 0 <= 0 + let shouldScrollingUpTriggerGestureRecognizer = !isScrollingDown && topConstraint.constant != parentViewHeight - lastStickyPoint + + shouldUpdateTopOffset = shouldScrollingDownTriggerGestureRecognizer || shouldScrollingUpTriggerGestureRecognizer + if shouldScrollingDownTriggerGestureRecognizer { + internalScrollView?.panGestureRecognizer.setTranslation(initialInternalScrollViewContentOffset, in: internalScrollView) + } else if shouldScrollingUpTriggerGestureRecognizer { + internalScrollView?.contentOffset = initialInternalScrollViewContentOffset + internalScrollView?.panGestureRecognizer.setTranslation(.zero, in: internalScrollView) + } + } else { + shouldUpdateTopOffset = true + } + + if shouldUpdateTopOffset { + let yTranslation = gestureRecognizer.translation(in: view).y + setTopOffset(topConstraint.constant + yTranslation) + gestureRecognizer.setTranslation(.zero, in: view) + } + + case .ended: let yVelocity = gestureRecognizer.velocity(in: view).y // v = px/s - let oldTopConstraintConstant = topConstraint.constant - topConstraint.constant = nearestStickyPointY(yVelocity: yVelocity) - let distanceToConver = oldTopConstraintConstant - topConstraint.constant // px - let animationDuration = TimeInterval(abs(distanceToConver/yVelocity)) // s = px/v - animateLayout(animationDuration: animationDuration) + let targetTopOffset = nearestStickyPointY(yVelocity: yVelocity) + let distanceToConver = topConstraint.constant - targetTopOffset // px + let animationDuration = max(0.08, min(0.3, TimeInterval(abs(distanceToConver/yVelocity)))) // s = px/v + setTopOffset(targetTopOffset, animationDuration: animationDuration) + + default: + break } } - @objc fileprivate func handleInternalScrollViewPanGestureRecognizer(_ gestureRecognizer: UIPanGestureRecognizer) { + private func setTopOffset(_ value: CGFloat, animationDuration: TimeInterval? = nil) { + var animationDuration = animationDuration guard - isPortrait, - let scrollView = gestureRecognizer.view as? UIScrollView, - let lastStickyPoint = pullUpControllerAllStickyPoints.last, - let parentViewHeight = parent?.view.frame.height, - let topConstraintValue = topConstraint?.constant + let parentViewHeight = parent?.view.frame.height else { return } - - let isScrollingDown = gestureRecognizer.translation(in: view).y > 0 - let shouldScrollingDownTriggerGestureRecognizer = isScrollingDown && scrollView.contentOffset.y <= 0 - let shouldScrollingUpTriggerGestureRecognizer = !isScrollingDown && topConstraintValue != parentViewHeight - lastStickyPoint - - if shouldScrollingDownTriggerGestureRecognizer || shouldScrollingUpTriggerGestureRecognizer { - handlePanGestureRecognizer(gestureRecognizer) + var value = value + if !pullUpControllerIsBouncingEnabled { + value = max(value, parentViewHeight - pullUpControllerPreferredSize.height) + value = min(value, parentViewHeight - pullUpControllerPreviewOffset) } - - if gestureRecognizer.state.rawValue == 3 { // for some reason gestureRecognizer.state == .ended doesn't work - topConstraint?.constant = nearestStickyPointY(yVelocity: 0) - animateLayout() + if abs(topConstraint?.constant ?? 0 - value) > 10 { + animationDuration = 0.2 } - } - - private func animateLayout(animationDuration: TimeInterval? = nil) { - let defaultAnimationDuration = 0.3 - let animationDuration = max(0.08, min(defaultAnimationDuration, animationDuration ?? defaultAnimationDuration)) + topConstraint?.constant = value + onDrag?(value) UIView.animate( - withDuration: animationDuration, + withDuration: animationDuration ?? 0, animations: { [weak self] in self?.parent?.view.layoutIfNeeded() }, @@ -285,6 +303,15 @@ open class PullUpController: UIViewController { } +extension PullUpController: UIGestureRecognizerDelegate { + + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, + shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { + return true + } + +} + extension UIViewController { /** @@ -331,7 +358,7 @@ extension UIScrollView { - parameter pullUpController: the pull up controller to move with the current scroll view content. */ open func attach(to pullUpController: PullUpController) { - panGestureRecognizer.addTarget(pullUpController, action: #selector(pullUpController.handleInternalScrollViewPanGestureRecognizer(_:))) + pullUpController.internalScrollView = self } /** @@ -339,7 +366,7 @@ extension UIScrollView { - parameter pullUpController: the pull up controller to be removed from controlling the scroll view. */ open func detach(from pullUpController: PullUpController) { - panGestureRecognizer.removeTarget(pullUpController, action: #selector(pullUpController.handleInternalScrollViewPanGestureRecognizer(_:))) + pullUpController.internalScrollView = nil } } From 6dca68274b7ef6f029077f85a62252b8f0dc367e Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 14 Aug 2018 21:50:40 +0200 Subject: [PATCH 19/73] Add `updatePreferredFrameIfNeeded(animated: Bool)` This method update the pull up controller's view size according to `pullUpControllerPreferredSize` and `pullUpControllerPreferredLandscapeFrame`. If the device is in portrait, the pull up controller's view will be attached to the nearest sticky point after the resize. --- Example/PullUpController/UI/Main.storyboard | 67 ++++++++++++- .../UI/MapViewController.swift | 59 ++++++++++-- .../UI/SearchViewController.swift | 16 +++- PullUpController/PullUpController.swift | 93 ++++++++++++------- 4 files changed, 182 insertions(+), 53 deletions(-) diff --git a/Example/PullUpController/UI/Main.storyboard b/Example/PullUpController/UI/Main.storyboard index b8ba9d8..b3e6f39 100644 --- a/Example/PullUpController/UI/Main.storyboard +++ b/Example/PullUpController/UI/Main.storyboard @@ -21,6 +21,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -37,8 +89,10 @@ + + @@ -59,7 +113,10 @@ + + + @@ -75,9 +132,9 @@ - + - + @@ -121,14 +178,14 @@ - + - + - + diff --git a/Example/PullUpController/UI/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift index 5ebd502..393370f 100644 --- a/Example/PullUpController/UI/MapViewController.swift +++ b/Example/PullUpController/UI/MapViewController.swift @@ -12,19 +12,39 @@ import MapKit class MapViewController: UIViewController { @IBOutlet private weak var mapView: MKMapView! + @IBOutlet private weak var sizeSliderView: UIView! { + didSet { + sizeSliderView.layer.cornerRadius = 10 + } + } + @IBOutlet private weak var widthSlider: UISlider! + @IBOutlet private weak var heightSlider: UISlider! + + private func makeSearchViewControllerIfNeeded() -> SearchViewController { + let currentPullUpController = childViewControllers + .filter({ $0 is SearchViewController }) + .first as? SearchViewController + if let currentPullUpController = currentPullUpController { + return currentPullUpController + } else { + return UIStoryboard(name: "Main", bundle: nil) + .instantiateViewController(withIdentifier: "SearchViewController") as! SearchViewController + } + } override func viewDidLoad() { super.viewDidLoad() - addPullUpController() + + let pullUpController = makeSearchViewControllerIfNeeded() + widthSlider.maximumValue = Float(pullUpController.portraitSize.width) + widthSlider.value = widthSlider.maximumValue + heightSlider.maximumValue = Float(pullUpController.portraitSize.height) + heightSlider.value = heightSlider.maximumValue } private func addPullUpController() { - guard - let pullUpController = UIStoryboard(name: "Main", bundle: nil) - .instantiateViewController(withIdentifier: "SearchViewController") as? SearchViewController - else { return } - + let pullUpController = makeSearchViewControllerIfNeeded() addPullUpController(pullUpController, animated: true) } @@ -43,11 +63,32 @@ class MapViewController: UIViewController { } @IBAction private func removeButtonTapped() { - guard - let pullUpController = childViewControllers.filter({ $0 is SearchViewController }).first as? SearchViewController - else { return } + let pullUpController = makeSearchViewControllerIfNeeded() removePullUpController(pullUpController, animated: true) } + @IBAction private func widthSliderValueChanged(_ sender: UISlider) { + let width = CGFloat(sender.value) + let pullUpController = makeSearchViewControllerIfNeeded() + pullUpController.portraitSize = CGSize(width: width, + height: pullUpController.portraitSize.height) + pullUpController.landscapeFrame = CGRect(origin: pullUpController.landscapeFrame.origin, + size: CGSize(width: width, + height: pullUpController.landscapeFrame.height)) + pullUpController.updatePreferredFrameIfNeeded(animated: true) + } + + @IBAction private func heightSliderValueChanged(_ sender: UISlider) { + let height = CGFloat(sender.value) + let pullUpController = makeSearchViewControllerIfNeeded() + pullUpController.portraitSize = CGSize(width: pullUpController.portraitSize.width, + height: height) + pullUpController.landscapeFrame = CGRect(origin: pullUpController.landscapeFrame.origin, + size: CGSize(width: pullUpController.landscapeFrame.width, + height: height)) + pullUpController.updatePreferredFrameIfNeeded(animated: true) + + } + } diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index 802906c..7cebecb 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -27,11 +27,18 @@ class SearchViewController: PullUpController { private var locations = [(title: String, location: CLLocationCoordinate2D)]() + public var portraitSize: CGSize = .zero + public var landscapeFrame: CGRect = .zero + // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() + portraitSize = CGSize(width: min(UIScreen.main.bounds.width, UIScreen.main.bounds.height), + height: secondPreviewView.frame.maxY) + landscapeFrame = CGRect(x: 5, y: 50, width: 280, height: 300) + tableView.attach(to: self) setupDataSource() @@ -68,7 +75,11 @@ class SearchViewController: PullUpController { // MARK: - PullUpController override var pullUpControllerPreferredSize: CGSize { - return CGSize(width: UIScreen.main.bounds.width, height: secondPreviewView.frame.maxY) + return portraitSize + } + + override var pullUpControllerPreferredLandscapeFrame: CGRect { + return landscapeFrame } override var pullUpControllerPreviewOffset: CGFloat { @@ -83,9 +94,6 @@ class SearchViewController: PullUpController { return false } - override var pullUpControllerPreferredLandscapeFrame: CGRect { - return CGRect(x: 5, y: 5, width: 280, height: UIScreen.main.bounds.height - 10) - } } // MARK: - UISearchBarDelegate diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 3a3a402..e25bab1 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -46,6 +46,14 @@ open class PullUpController: UIViewController { return CGSize(width: UIScreen.main.bounds.width, height: 400) } + /** + The desired size of the pull up controller’s view, in screen units when the device is in landscape mode. + The default value is (x: 10, y: 10, width: 300, height: UIScreen.main.bounds.height - 20). + */ + open var pullUpControllerPreferredLandscapeFrame: CGRect { + return CGRect(x: 10, y: 10, width: 300, height: UIScreen.main.bounds.height - 20) + } + /** A list of y values, in screen units expressed in the pull up controller coordinate system. At the end of the gestures the pull up controller will scroll to the nearest point in the list. @@ -67,14 +75,6 @@ open class PullUpController: UIViewController { return false } - /** - The desired size of the pull up controller’s view, in screen units when the device is in landscape mode. - The default value is (x: 10, y: 10, width: 300, height: UIScreen.main.bounds.height - 20). - */ - open var pullUpControllerPreferredLandscapeFrame: CGRect { - return CGRect(x: 10, y: 10, width: 300, height: UIScreen.main.bounds.height - 20) - } - // MARK: - Public properties /** @@ -110,7 +110,7 @@ open class PullUpController: UIViewController { You may use on of `pullUpControllerAllStickyPoints` item to provide a valid visible point. - parameter visiblePoint: the y value to make visible, in screen units expressed in the pull up controller coordinate system. - - parameter animated: Pass true to animate the move; otherwise, pass false + - parameter animated: Pass true to animate the move; otherwise, pass false. - parameter completion: The closure to execute after the animation is completed. This block has no return value and takes no parameters. You may specify nil for this parameter. */ open func pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, animated: Bool, completion: (() -> Void)?) { @@ -134,11 +134,28 @@ open class PullUpController: UIViewController { } } + /** + This method update the pull up controller's view size according to `pullUpControllerPreferredSize` and `pullUpControllerPreferredLandscapeFrame`. + If the device is in portrait, the pull up controller's view will be attached to the nearest sticky point after the resize. + - parameter animated: Pass true to animate the resize; otherwise, pass false. + */ + open func updatePreferredFrameIfNeeded(animated: Bool) { + guard + let parentView = parent?.view + else { return } + refreshConstraints(newSize: parentView.frame.size, resetTop: false) + + UIView.animate(withDuration: animated ? 0.3 : 0) { [weak self] in + self?.view.layoutIfNeeded() + } + } + + open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { - let isPortrait = size.height > size.width + let isNewSizePortrait = size.height > size.width var targetStickyPoint: CGFloat? - if !isPortrait { + if !isNewSizePortrait { portraitPreviousStickyPointIndex = currentStickyPointIndex } else if let portraitPreviousStickyPointIndex = portraitPreviousStickyPointIndex, @@ -149,7 +166,7 @@ open class PullUpController: UIViewController { } coordinator.animate(alongsideTransition: { [weak self] coordinator in - self?.refreshConstraints(size: size) + self?.refreshConstraints(newSize: size) if let targetStickyPoint = targetStickyPoint { self?.pullUpControllerMoveToVisiblePoint(targetStickyPoint, animated: true, completion: nil) } @@ -158,7 +175,19 @@ open class PullUpController: UIViewController { // MARK: - Setup - fileprivate func setupPanGestureRecognizer() { + fileprivate func setupView(superview: UIView) { + view.translatesAutoresizingMaskIntoConstraints = false + superview.addSubview(view) + view.frame = CGRect(origin: CGPoint(x: view.frame.origin.x, + y: superview.bounds.height), + size: view.frame.size) + + setupPanGestureRecognizer() + setupConstraints() + refreshConstraints(newSize: view.frame.size) + } + + private func setupPanGestureRecognizer() { panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestureRecognizer(_:))) panGestureRecognizer?.minimumNumberOfTouches = 1 panGestureRecognizer?.maximumNumberOfTouches = 1 @@ -168,7 +197,7 @@ open class PullUpController: UIViewController { } } - fileprivate func setupConstraints() { + private func setupConstraints() { guard let parentView = parent?.view else { return } @@ -181,6 +210,14 @@ open class PullUpController: UIViewController { NSLayoutConstraint.activate([topConstraint, leftConstraint, widthConstraint, heightConstraint].compactMap { $0 }) } + private func refreshConstraints(newSize: CGSize, resetTop: Bool = true) { + if newSize.height > newSize.width { + setPortraitConstraints(parentViewSize: newSize, resetTop: resetTop) + } else { + setLandscapeConstraints() + } + } + private var currentStickyPointIndex: Int { let stickyPointTreshold = (self.parent?.view.frame.height ?? 0) - (topConstraint?.constant ?? 0) let stickyPointsLessCurrentPosition = pullUpControllerAllStickyPoints.map { abs($0 - stickyPointTreshold) } @@ -279,8 +316,12 @@ open class PullUpController: UIViewController { ) } - private func setPortraitConstraints(parentViewSize: CGSize) { - topConstraint?.constant = parentViewSize.height - pullUpControllerPreviewOffset + private func setPortraitConstraints(parentViewSize: CGSize, resetTop: Bool) { + if resetTop { + topConstraint?.constant = parentViewSize.height - pullUpControllerPreviewOffset + } else { + topConstraint?.constant = nearestStickyPointY(yVelocity: 0) + } leftConstraint?.constant = (parentViewSize.width - min(pullUpControllerPreferredSize.width, parentViewSize.width))/2 widthConstraint?.constant = pullUpControllerPreferredSize.width heightConstraint?.constant = pullUpControllerPreferredSize.height @@ -293,14 +334,6 @@ open class PullUpController: UIViewController { heightConstraint?.constant = pullUpControllerPreferredLandscapeFrame.height } - fileprivate func refreshConstraints(size: CGSize) { - if size.width > size.height { - setLandscapeConstraints() - } else { - setPortraitConstraints(parentViewSize: size) - } - } - } extension PullUpController: UIGestureRecognizerDelegate { @@ -321,17 +354,7 @@ extension UIViewController { open func addPullUpController(_ pullUpController: PullUpController, animated: Bool) { assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") addChildViewController(pullUpController) - - pullUpController.view.translatesAutoresizingMaskIntoConstraints = false - view.addSubview(pullUpController.view) - pullUpController.view.frame = CGRect(origin: CGPoint(x: pullUpController.view.frame.origin.x, - y: view.bounds.height), - size: pullUpController.view.frame.size) - - pullUpController.setupPanGestureRecognizer() - pullUpController.setupConstraints() - pullUpController.refreshConstraints(size: view.frame.size) - + pullUpController.setupView(superview: view) if animated { UIView.animate(withDuration: 0.3) { [weak self] in self?.view.layoutIfNeeded() From e46313d3445eaf1f8e2354c0a4ebb74eab86d82b Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 14 Aug 2018 21:54:23 +0200 Subject: [PATCH 20/73] Bump pod version --- PullUpController.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index d84c443..b231e60 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.3.0' + s.version = '0.4.0' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } From 28032dc2e4f7654a51725d50d545826ba3b3e3b6 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 14 Aug 2018 23:24:01 +0200 Subject: [PATCH 21/73] Improve scrolling animation --- .../UI/SearchViewController.swift | 10 ++++ PullUpController/PullUpController.swift | 60 +++++++++++-------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index 7cebecb..8fe9375 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -70,6 +70,16 @@ class SearchViewController: PullUpController { locations.append(("Amsterdam", CLLocationCoordinate2D(latitude: 52.354775, longitude: 4.7585401))) locations.append(("Dublin", CLLocationCoordinate2D(latitude: 53.3244431, longitude: -6.3857869))) locations.append(("Reykjavik", CLLocationCoordinate2D(latitude: 64.1335484, longitude: -21.9224815))) + locations.append(("London", CLLocationCoordinate2D(latitude: 51.5287718, longitude: -0.2416817))) + locations.append(("Paris", CLLocationCoordinate2D(latitude: 48.8589507, longitude: 2.2770201))) + locations.append(("Amsterdam", CLLocationCoordinate2D(latitude: 52.354775, longitude: 4.7585401))) + locations.append(("Dublin", CLLocationCoordinate2D(latitude: 53.3244431, longitude: -6.3857869))) + locations.append(("Reykjavik", CLLocationCoordinate2D(latitude: 64.1335484, longitude: -21.9224815))) + locations.append(("London", CLLocationCoordinate2D(latitude: 51.5287718, longitude: -0.2416817))) + locations.append(("Paris", CLLocationCoordinate2D(latitude: 48.8589507, longitude: 2.2770201))) + locations.append(("Amsterdam", CLLocationCoordinate2D(latitude: 52.354775, longitude: 4.7585401))) + locations.append(("Dublin", CLLocationCoordinate2D(latitude: 53.3244431, longitude: -6.3857869))) + locations.append(("Reykjavik", CLLocationCoordinate2D(latitude: 64.1335484, longitude: -21.9224815))) } // MARK: - PullUpController diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index e25bab1..165873a 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -244,7 +244,7 @@ open class PullUpController: UIViewController { isPortrait, let topConstraint = topConstraint, let lastStickyPoint = pullUpControllerAllStickyPoints.last, - let parentViewHeight = parent?.view.frame.height + let parentView = parent?.view else { return } switch gestureRecognizer.state { @@ -252,29 +252,44 @@ open class PullUpController: UIViewController { initialInternalScrollViewContentOffset = internalScrollView?.contentOffset ?? .zero case .changed: - var shouldUpdateTopOffset = false - let scrollViewPanVelocity = internalScrollView?.panGestureRecognizer.velocity(in: view).y ?? 0 - if scrollViewPanVelocity != 0 { + var yTranslation = gestureRecognizer.translation(in: parentView).y + gestureRecognizer.setTranslation(.zero, in: view) + let scrollViewPanVelocity = internalScrollView?.panGestureRecognizer.velocity(in: parentView).y ?? 0 + + // the user is scrolling the internal scroll view + if scrollViewPanVelocity != 0, let scrollView = internalScrollView { + let parentViewHeight = parentView.frame.height let isScrollingDown = scrollViewPanVelocity > 0 - let shouldScrollingDownTriggerGestureRecognizer = isScrollingDown && internalScrollView?.contentOffset.y ?? 0 <= 0 - let shouldScrollingUpTriggerGestureRecognizer = !isScrollingDown && topConstraint.constant != parentViewHeight - lastStickyPoint + /* + the user should be able to drag the view down through the internal scroll view when + 1. the scroll direction is down (isScrollingDown) + 2. the internal scroll view is scrolled to the top (scrollView.contentOffset.y <= 0) + */ + let shouldDragViewDown = isScrollingDown && scrollView.contentOffset.y <= 0 + /* + the user should be able to drag the view up through the internal scroll view when + 1. the scroll direction is up (!isScrollingDown) + 2. the PullUpController's view is not at it's last sticky point (fully opened aka topConstraint.constant != parentViewHeight - lastStickyPoint) + */ + let shouldDragViewUp = !isScrollingDown && topConstraint.constant != parentViewHeight - lastStickyPoint - shouldUpdateTopOffset = shouldScrollingDownTriggerGestureRecognizer || shouldScrollingUpTriggerGestureRecognizer - if shouldScrollingDownTriggerGestureRecognizer { - internalScrollView?.panGestureRecognizer.setTranslation(initialInternalScrollViewContentOffset, in: internalScrollView) - } else if shouldScrollingUpTriggerGestureRecognizer { - internalScrollView?.contentOffset = initialInternalScrollViewContentOffset - internalScrollView?.panGestureRecognizer.setTranslation(.zero, in: internalScrollView) + if shouldDragViewDown || shouldDragViewUp { + // disable the bounces when the user is able to drag the view through the internal scroll view + scrollView.bounces = false + if isScrollingDown { + // take the initial internal scroll view content offset into account when scrolling down + yTranslation -= initialInternalScrollViewContentOffset.y + initialInternalScrollViewContentOffset = .zero + } else { + // keep the initial internal scroll view content offset when scrolling up + internalScrollView?.contentOffset = initialInternalScrollViewContentOffset + } + } else { + // reset the translation if the user should'nt be able to drag the view up through the internal scroll view + yTranslation = 0 } - } else { - shouldUpdateTopOffset = true - } - - if shouldUpdateTopOffset { - let yTranslation = gestureRecognizer.translation(in: view).y - setTopOffset(topConstraint.constant + yTranslation) - gestureRecognizer.setTranslation(.zero, in: view) } + setTopOffset(topConstraint.constant + yTranslation) case .ended: let yVelocity = gestureRecognizer.velocity(in: view).y // v = px/s @@ -282,6 +297,7 @@ open class PullUpController: UIViewController { let distanceToConver = topConstraint.constant - targetTopOffset // px let animationDuration = max(0.08, min(0.3, TimeInterval(abs(distanceToConver/yVelocity)))) // s = px/v setTopOffset(targetTopOffset, animationDuration: animationDuration) + internalScrollView?.bounces = true default: break @@ -289,7 +305,6 @@ open class PullUpController: UIViewController { } private func setTopOffset(_ value: CGFloat, animationDuration: TimeInterval? = nil) { - var animationDuration = animationDuration guard let parentViewHeight = parent?.view.frame.height else { return } @@ -298,9 +313,6 @@ open class PullUpController: UIViewController { value = max(value, parentViewHeight - pullUpControllerPreferredSize.height) value = min(value, parentViewHeight - pullUpControllerPreviewOffset) } - if abs(topConstraint?.constant ?? 0 - value) > 10 { - animationDuration = 0.2 - } topConstraint?.constant = value onDrag?(value) From 00f3494dc9ca86705327fc4f70716e6bceb0e5ff Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 15 Aug 2018 12:08:57 +0200 Subject: [PATCH 22/73] Fix inertial scroll --- PullUpController/PullUpController.swift | 76 ++++++++++++++----------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 165873a..163311f 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -247,57 +247,69 @@ open class PullUpController: UIViewController { let parentView = parent?.view else { return } + let parentViewHeight = parentView.frame.height + var yTranslation = gestureRecognizer.translation(in: parentView).y + gestureRecognizer.setTranslation(.zero, in: view) + + let scrollViewPanVelocity = internalScrollView?.panGestureRecognizer.velocity(in: parentView).y ?? 0 + let isScrollingDown = scrollViewPanVelocity > 0 + + /** + A Boolean value that controls whether the scroll view scroll should pan the parent view up **or** down. + + 1. The user should be able to drag the view down through the internal scroll view when + - the scroll direction is down (`isScrollingDown`) + - the internal scroll view is scrolled to the top (`scrollView.contentOffset.y <= 0`) + + 2. The user should be able to drag the view up through the internal scroll view when + - the scroll direction is up (`!isScrollingDown`) + - the PullUpController's view is fully opened. (`topConstraint.constant != parentViewHeight - lastStickyPoint`) + */ + let shouldDragView: Bool = { + // Condition 1 + let shouldDragViewDown = isScrollingDown && internalScrollView?.contentOffset.y ?? 0 <= 0 + // Condition 2 + let shouldDragViewUp = !isScrollingDown && topConstraint.constant != parentViewHeight - lastStickyPoint + return shouldDragViewDown || shouldDragViewUp + }() + switch gestureRecognizer.state { case .began: initialInternalScrollViewContentOffset = internalScrollView?.contentOffset ?? .zero case .changed: - var yTranslation = gestureRecognizer.translation(in: parentView).y - gestureRecognizer.setTranslation(.zero, in: view) - let scrollViewPanVelocity = internalScrollView?.panGestureRecognizer.velocity(in: parentView).y ?? 0 - // the user is scrolling the internal scroll view if scrollViewPanVelocity != 0, let scrollView = internalScrollView { - let parentViewHeight = parentView.frame.height - let isScrollingDown = scrollViewPanVelocity > 0 - /* - the user should be able to drag the view down through the internal scroll view when - 1. the scroll direction is down (isScrollingDown) - 2. the internal scroll view is scrolled to the top (scrollView.contentOffset.y <= 0) - */ - let shouldDragViewDown = isScrollingDown && scrollView.contentOffset.y <= 0 - /* - the user should be able to drag the view up through the internal scroll view when - 1. the scroll direction is up (!isScrollingDown) - 2. the PullUpController's view is not at it's last sticky point (fully opened aka topConstraint.constant != parentViewHeight - lastStickyPoint) - */ - let shouldDragViewUp = !isScrollingDown && topConstraint.constant != parentViewHeight - lastStickyPoint - - if shouldDragViewDown || shouldDragViewUp { - // disable the bounces when the user is able to drag the view through the internal scroll view - scrollView.bounces = false - if isScrollingDown { - // take the initial internal scroll view content offset into account when scrolling down - yTranslation -= initialInternalScrollViewContentOffset.y - initialInternalScrollViewContentOffset = .zero - } else { - // keep the initial internal scroll view content offset when scrolling up - internalScrollView?.contentOffset = initialInternalScrollViewContentOffset + // if the user shouldn't be able to drag the view up through the internal scroll view reset the translation + guard + shouldDragView + else { + yTranslation = 0 + return } + // disable the bounces when the user is able to drag the view through the internal scroll view + scrollView.bounces = false + if isScrollingDown { + // take the initial internal scroll view content offset into account when scrolling down + yTranslation -= initialInternalScrollViewContentOffset.y + initialInternalScrollViewContentOffset = .zero } else { - // reset the translation if the user should'nt be able to drag the view up through the internal scroll view - yTranslation = 0 + // keep the initial internal scroll view content offset when scrolling up + internalScrollView?.contentOffset = initialInternalScrollViewContentOffset } } setTopOffset(topConstraint.constant + yTranslation) case .ended: + internalScrollView?.bounces = true + guard + shouldDragView + else { return } let yVelocity = gestureRecognizer.velocity(in: view).y // v = px/s let targetTopOffset = nearestStickyPointY(yVelocity: yVelocity) let distanceToConver = topConstraint.constant - targetTopOffset // px let animationDuration = max(0.08, min(0.3, TimeInterval(abs(distanceToConver/yVelocity)))) // s = px/v setTopOffset(targetTopOffset, animationDuration: animationDuration) - internalScrollView?.bounces = true default: break From 50027c5848cca1a895bc27800489cda237f6470b Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 16 Aug 2018 19:07:20 +0200 Subject: [PATCH 23/73] Bump pod version --- PullUpController.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index b231e60..01d8d0a 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.4.0' + s.version = '0.4.1' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } From e52ad681ee553ca9216398ea009eb542080556e8 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 12 Sep 2018 21:20:34 +0200 Subject: [PATCH 24/73] Fix initial pull up controller state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit will add the new parameter `initialStickyPointOffset` to the method `addPullUpController` in order to provide a way to set the initial state of the pull up controller’s view. Previusly that was not possible since the initial offset was set by `pullUpControllerPreviewOffset`. This ticket should fix the issues #21 and #22. --- Example/PullUpController/UI/Main.storyboard | 31 ++++++++--- .../UI/MapViewController.swift | 15 ++++-- .../UI/SearchViewController.swift | 27 ++++++++-- PullUpController/PullUpController.swift | 51 +++++++++++-------- 4 files changed, 86 insertions(+), 38 deletions(-) diff --git a/Example/PullUpController/UI/Main.storyboard b/Example/PullUpController/UI/Main.storyboard index b3e6f39..25788db 100644 --- a/Example/PullUpController/UI/Main.storyboard +++ b/Example/PullUpController/UI/Main.storyboard @@ -22,13 +22,13 @@ - + - + - + - + @@ -45,7 +45,7 @@ - + - + + + + + + + + + + + + + + @@ -114,6 +132,7 @@ + diff --git a/Example/PullUpController/UI/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift index 393370f..2f0b0fc 100644 --- a/Example/PullUpController/UI/MapViewController.swift +++ b/Example/PullUpController/UI/MapViewController.swift @@ -19,17 +19,19 @@ class MapViewController: UIViewController { } @IBOutlet private weak var widthSlider: UISlider! @IBOutlet private weak var heightSlider: UISlider! + @IBOutlet private weak var initialStateSegmentedControl: UISegmentedControl! private func makeSearchViewControllerIfNeeded() -> SearchViewController { let currentPullUpController = childViewControllers .filter({ $0 is SearchViewController }) .first as? SearchViewController - if let currentPullUpController = currentPullUpController { - return currentPullUpController + let pullUpController: SearchViewController = currentPullUpController ?? UIStoryboard(name: "Main",bundle: nil).instantiateViewController(withIdentifier: "SearchViewController") as! SearchViewController + if initialStateSegmentedControl.selectedSegmentIndex == 0 { + pullUpController.initialState = .contracted } else { - return UIStoryboard(name: "Main", bundle: nil) - .instantiateViewController(withIdentifier: "SearchViewController") as! SearchViewController + pullUpController.initialState = .expanded } + return pullUpController } override func viewDidLoad() { @@ -45,7 +47,10 @@ class MapViewController: UIViewController { private func addPullUpController() { let pullUpController = makeSearchViewControllerIfNeeded() - addPullUpController(pullUpController, animated: true) + _ = pullUpController.view // call pullUpController.viewDidLoad() + addPullUpController(pullUpController, + initialStickyPointOffset: pullUpController.initialPointOffset, + animated: true) } func zoom(to location: CLLocationCoordinate2D) { diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index 8fe9375..90d96ee 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -12,6 +12,13 @@ import PullUpController class SearchViewController: PullUpController { + enum InitialState { + case contracted + case expanded + } + + var initialState: InitialState = .contracted + // MARK: - IBOutlets @IBOutlet private weak var visualEffectView: UIVisualEffectView! @@ -24,6 +31,15 @@ class SearchViewController: PullUpController { @IBOutlet private weak var firstPreviewView: UIView! @IBOutlet private weak var secondPreviewView: UIView! @IBOutlet private weak var tableView: UITableView! + + var initialPointOffset: CGFloat { + switch initialState { + case .contracted: + return searchBoxContainerView?.frame.height ?? 0 + case .expanded: + return pullUpControllerPreferredSize.height + } + } private var locations = [(title: String, location: CLLocationCoordinate2D)]() @@ -92,12 +108,13 @@ class SearchViewController: PullUpController { return landscapeFrame } - override var pullUpControllerPreviewOffset: CGFloat { - return searchBoxContainerView.frame.height - } - override var pullUpControllerMiddleStickyPoints: [CGFloat] { - return [firstPreviewView.frame.maxY] + switch initialState { + case .contracted: + return [firstPreviewView.frame.maxY] + case .expanded: + return [searchBoxContainerView.frame.maxY, firstPreviewView.frame.maxY] + } } override var pullUpControllerIsBouncingEnabled: Bool { diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 163311f..d002504 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -30,14 +30,6 @@ open class PullUpController: UIViewController { */ open var onDrag: ((_ point: CGFloat) -> Void)? - /** - The desired height in screen units expressed in the pull up controller coordinate system that will be initially showed. - The default value is 50. - */ - open var pullUpControllerPreviewOffset: CGFloat { - return 50 - } - /** The desired size of the pull up controller’s view, in screen units. The default value is width: UIScreen.main.bounds.width, height: 400. @@ -82,7 +74,7 @@ open class PullUpController: UIViewController { At the end of the gesture the pull up controller will scroll at the nearest point in the list. */ public final var pullUpControllerAllStickyPoints: [CGFloat] { - var sc_allStickyPoints = [pullUpControllerPreviewOffset, pullUpControllerPreferredSize.height] + var sc_allStickyPoints = [initialStickyPointOffset, pullUpControllerPreferredSize.height].compactMap { $0 } sc_allStickyPoints.append(contentsOf: pullUpControllerMiddleStickyPoints) return sc_allStickyPoints.sorted() } @@ -102,6 +94,7 @@ open class PullUpController: UIViewController { fileprivate weak var internalScrollView: UIScrollView? private var initialInternalScrollViewContentOffset: CGPoint = .zero + private var initialStickyPointOffset: CGFloat? // MARK: - Open methods @@ -143,7 +136,8 @@ open class PullUpController: UIViewController { guard let parentView = parent?.view else { return } - refreshConstraints(newSize: parentView.frame.size, resetTop: false) + refreshConstraints(newSize: parentView.frame.size, + customTopOffset: parentView.frame.size.height - (pullUpControllerAllStickyPoints.first ?? 0)) UIView.animate(withDuration: animated ? 0.3 : 0) { [weak self] in self?.view.layoutIfNeeded() @@ -175,7 +169,8 @@ open class PullUpController: UIViewController { // MARK: - Setup - fileprivate func setupView(superview: UIView) { + fileprivate func setup(superview: UIView, initialStickyPointOffset: CGFloat) { + self.initialStickyPointOffset = initialStickyPointOffset view.translatesAutoresizingMaskIntoConstraints = false superview.addSubview(view) view.frame = CGRect(origin: CGPoint(x: view.frame.origin.x, @@ -184,7 +179,8 @@ open class PullUpController: UIViewController { setupPanGestureRecognizer() setupConstraints() - refreshConstraints(newSize: view.frame.size) + refreshConstraints(newSize: view.frame.size, + customTopOffset: superview.frame.height - initialStickyPointOffset) } private func setupPanGestureRecognizer() { @@ -210,9 +206,9 @@ open class PullUpController: UIViewController { NSLayoutConstraint.activate([topConstraint, leftConstraint, widthConstraint, heightConstraint].compactMap { $0 }) } - private func refreshConstraints(newSize: CGSize, resetTop: Bool = true) { + private func refreshConstraints(newSize: CGSize, customTopOffset: CGFloat? = nil) { if newSize.height > newSize.width { - setPortraitConstraints(parentViewSize: newSize, resetTop: resetTop) + setPortraitConstraints(parentViewSize: newSize, customTopOffset: customTopOffset) } else { setLandscapeConstraints() } @@ -321,9 +317,11 @@ open class PullUpController: UIViewController { let parentViewHeight = parent?.view.frame.height else { return } var value = value - if !pullUpControllerIsBouncingEnabled { - value = max(value, parentViewHeight - pullUpControllerPreferredSize.height) - value = min(value, parentViewHeight - pullUpControllerPreviewOffset) + if !pullUpControllerIsBouncingEnabled, + let firstStickyPoint = pullUpControllerAllStickyPoints.first, + let lastStickyPoint = pullUpControllerAllStickyPoints.last { + value = max(value, parentViewHeight - lastStickyPoint) + value = min(value, parentViewHeight - firstStickyPoint) } topConstraint?.constant = value onDrag?(value) @@ -340,9 +338,9 @@ open class PullUpController: UIViewController { ) } - private func setPortraitConstraints(parentViewSize: CGSize, resetTop: Bool) { - if resetTop { - topConstraint?.constant = parentViewSize.height - pullUpControllerPreviewOffset + private func setPortraitConstraints(parentViewSize: CGSize, customTopOffset: CGFloat? = nil) { + if let customTopOffset = customTopOffset { + topConstraint?.constant = customTopOffset } else { topConstraint?.constant = nearestStickyPointY(yVelocity: 0) } @@ -374,11 +372,15 @@ extension UIViewController { /** Adds the specified pull up view controller as a child of the current view controller. - parameter pullUpController: the pull up controller to add as a child of the current view controller. + - parameter initialStickyPointOffset: The point where the provided `pullUpController`'s view will be initially placed expressed in screen units of the pull up controller coordinate system. If this value is not provided, the `pullUpController`'s view will be initially placed expressed + - parameter animated: Pass true to animate the adding; otherwise, pass false. */ - open func addPullUpController(_ pullUpController: PullUpController, animated: Bool) { + open func addPullUpController(_ pullUpController: PullUpController, + initialStickyPointOffset: CGFloat, + animated: Bool) { assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") addChildViewController(pullUpController) - pullUpController.setupView(superview: view) + pullUpController.setup(superview: view, initialStickyPointOffset: initialStickyPointOffset) if animated { UIView.animate(withDuration: 0.3) { [weak self] in self?.view.layoutIfNeeded() @@ -388,6 +390,11 @@ extension UIViewController { } } + /** + Adds the specified pull up view controller as a child of the current view controller. + - parameter pullUpController: the pull up controller to remove as a child from the current view controller. + - parameter animated: Pass true to animate the removing; otherwise, pass false. + */ open func removePullUpController(_ pullUpController: PullUpController, animated: Bool) { pullUpController.pullUpControllerMoveToVisiblePoint(0, animated: animated) { pullUpController.willMove(toParentViewController: nil) From b14675b7f8bbe7330d76c1999526456ffe4a21c6 Mon Sep 17 00:00:00 2001 From: Rinat Muhamedgaliev Date: Tue, 18 Sep 2018 09:55:55 +0300 Subject: [PATCH 25/73] Migrate to swift 4.2 --- Example/Pods/Pods.xcodeproj/project.pbxproj | 16 ++++++++-------- PullUpController.podspec | 4 ++-- PullUpController/PullUpController.swift | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 1702cb5..fb2c3b7 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -31,23 +31,23 @@ 13054176DE8FD7682EA5876D0559D994 /* Pods-PullUpController_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-PullUpController_Example-umbrella.h"; sourceTree = ""; }; 21F144D6F2B3882BC5FD9933E31927EA /* Pods-PullUpController_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PullUpController_Example.release.xcconfig"; sourceTree = ""; }; 23CC8DB9AF358116FE5F077A38A91D66 /* PullUpController-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PullUpController-umbrella.h"; sourceTree = ""; }; - 2C5AA6A33D63B64686BB7A5B6B78E35B /* PullUpController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = PullUpController.framework; path = PullUpController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 3C31DAEE49BC012D13D12539B321D0A3 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; + 2C5AA6A33D63B64686BB7A5B6B78E35B /* PullUpController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PullUpController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 3C31DAEE49BC012D13D12539B321D0A3 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 40664F6BBDF3B9CD293C19FB51C67E34 /* Pods-PullUpController_Example-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-PullUpController_Example-acknowledgements.markdown"; sourceTree = ""; }; 483D1843AE28A17CB5FD474CEE4AF6BB /* PullUpController-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "PullUpController-prefix.pch"; sourceTree = ""; }; - 50E3AF474793B9EE7DE53500151B8954 /* PullUpController.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; path = PullUpController.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 50E3AF474793B9EE7DE53500151B8954 /* PullUpController.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; path = PullUpController.podspec; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 6604A7D69453B4569E4E4827FB9155A9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 79F4FAA2380B9E03FF9DE31DABF0669C /* Pods-PullUpController_Example-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-PullUpController_Example-resources.sh"; sourceTree = ""; }; 8AAE02B10DCAF71B4C8DA0F59BB3F4D4 /* PullUpController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = PullUpController.swift; path = PullUpController/PullUpController.swift; sourceTree = ""; }; - 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 9F56E5FB334BA9037FAA64158F05C7D6 /* PullUpController.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = PullUpController.modulemap; sourceTree = ""; }; BB536EBEECAC21C47D62C1DF0D798356 /* Pods-PullUpController_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-PullUpController_Example-dummy.m"; sourceTree = ""; }; BB9F8EA9DDF18EABDC0BB608ACF09769 /* Pods-PullUpController_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-PullUpController_Example-acknowledgements.plist"; sourceTree = ""; }; - BF0DB4470D13394EFA28A938F1A38755 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + BF0DB4470D13394EFA28A938F1A38755 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; C5B8751D4FDEC7CA05976A501C20CE94 /* PullUpController-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "PullUpController-dummy.m"; sourceTree = ""; }; C8FA5C2BF2D4AFB310AB73255CE621BC /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; D755ED3538F9C07483D9251773906FF9 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - DA07B630F7B2CEB638C65108EE8C97AF /* Pods_PullUpController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_PullUpController_Example.framework; path = "Pods-PullUpController_Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + DA07B630F7B2CEB638C65108EE8C97AF /* Pods_PullUpController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PullUpController_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DCF8A9AF865D53B852B08F7253C08494 /* Pods-PullUpController_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-PullUpController_Example.debug.xcconfig"; sourceTree = ""; }; DD9FE163A3EEF9FA109361613CC05E88 /* Pods-PullUpController_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-PullUpController_Example.modulemap"; sourceTree = ""; }; DE129AA35E6DD8D1AC44CED9A162F31F /* PullUpController.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = PullUpController.xcconfig; sourceTree = ""; }; @@ -352,7 +352,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -385,7 +385,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; diff --git a/PullUpController.podspec b/PullUpController.podspec index 01d8d0a..73206cf 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.4.1' + s.version = '0.4.2' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } @@ -8,5 +8,5 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/MarioIannotta/PullUpController.git', :tag => s.version.to_s } s.ios.deployment_target = '9.0' s.source_files = 'PullUpController/**/*.swift' - s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.1' } + s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.2' } end diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 163311f..9b9f681 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -377,7 +377,7 @@ extension UIViewController { */ open func addPullUpController(_ pullUpController: PullUpController, animated: Bool) { assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") - addChildViewController(pullUpController) + addChild(pullUpController) pullUpController.setupView(superview: view) if animated { UIView.animate(withDuration: 0.3) { [weak self] in @@ -390,9 +390,9 @@ extension UIViewController { open func removePullUpController(_ pullUpController: PullUpController, animated: Bool) { pullUpController.pullUpControllerMoveToVisiblePoint(0, animated: animated) { - pullUpController.willMove(toParentViewController: nil) + pullUpController.willMove(toParent: nil) pullUpController.view.removeFromSuperview() - pullUpController.removeFromParentViewController() + pullUpController.removeFromParent() } } From ac91f2b761dedd1c808a4da07f9d5dc13f8519ba Mon Sep 17 00:00:00 2001 From: Filipp Fediakov Date: Fri, 28 Sep 2018 15:04:27 +0100 Subject: [PATCH 26/73] Fix using wrong view to refresh constraints --- PullUpController/PullUpController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 9b9f681..e1c330d 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -184,7 +184,7 @@ open class PullUpController: UIViewController { setupPanGestureRecognizer() setupConstraints() - refreshConstraints(newSize: view.frame.size) + refreshConstraints(newSize: superview.frame.size) } private func setupPanGestureRecognizer() { From 26b010df7c6a8fd4d86b4bead4f88908d0e03ef2 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Fri, 28 Sep 2018 19:12:11 +0200 Subject: [PATCH 27/73] Bump pod version --- PullUpController.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index 73206cf..95df732 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.4.2' + s.version = '0.5.0' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } From a90001258182a800a11c1ce5a8db6fe03de5ebfe Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Fri, 28 Sep 2018 19:32:25 +0200 Subject: [PATCH 28/73] Update .swift-version --- .swift-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swift-version b/.swift-version index 5186d07..bf77d54 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -4.0 +4.2 From 2ea1fe49dc670fb6051cd298a12e5e91b9d478bb Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Sun, 28 Oct 2018 18:57:10 +0100 Subject: [PATCH 29/73] Fix blank space at bottom when bouncing is enabled --- Example/PullUpController/UI/Main.storyboard | 17 +++++------ .../UI/SearchViewController.swift | 2 +- PullUpController/PullUpController.swift | 30 ++++++++++++++----- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/Example/PullUpController/UI/Main.storyboard b/Example/PullUpController/UI/Main.storyboard index 25788db..a0c6b1d 100644 --- a/Example/PullUpController/UI/Main.storyboard +++ b/Example/PullUpController/UI/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -151,16 +151,16 @@ - + - + - + @@ -247,10 +247,10 @@ - + @@ -258,18 +258,15 @@ - - - + - diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index 90d96ee..e793095 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -118,7 +118,7 @@ class SearchViewController: PullUpController { } override var pullUpControllerIsBouncingEnabled: Bool { - return false + return true } } diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index eeb44cd..9f0bea2 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -81,6 +81,7 @@ open class PullUpController: UIViewController { private var leftConstraint: NSLayoutConstraint? private var topConstraint: NSLayoutConstraint? + private var bottomConstraint: NSLayoutConstraint? private var widthConstraint: NSLayoutConstraint? private var heightConstraint: NSLayoutConstraint? private var panGestureRecognizer: UIPanGestureRecognizer? @@ -198,12 +199,19 @@ open class PullUpController: UIViewController { let parentView = parent?.view else { return } - topConstraint = view.topAnchor.constraint(equalTo: parentView.topAnchor, constant: 0) - leftConstraint = view.leftAnchor.constraint(equalTo: parentView.leftAnchor, constant: 0) + topConstraint = view.topAnchor.constraint(equalTo: parentView.topAnchor) + leftConstraint = view.leftAnchor.constraint(equalTo: parentView.leftAnchor) widthConstraint = view.widthAnchor.constraint(equalToConstant: pullUpControllerPreferredSize.width) heightConstraint = view.heightAnchor.constraint(equalToConstant: pullUpControllerPreferredSize.height) + heightConstraint?.priority = .defaultLow + bottomConstraint = parentView.bottomAnchor.constraint(equalTo: view.bottomAnchor) - NSLayoutConstraint.activate([topConstraint, leftConstraint, widthConstraint, heightConstraint].compactMap { $0 }) + let constraintsToActivate = [topConstraint, + leftConstraint, + widthConstraint, + heightConstraint, + bottomConstraint].compactMap { $0 } + NSLayoutConstraint.activate(constraintsToActivate) } private func refreshConstraints(newSize: CGSize, customTopOffset: CGFloat? = nil) { @@ -347,13 +355,21 @@ open class PullUpController: UIViewController { leftConstraint?.constant = (parentViewSize.width - min(pullUpControllerPreferredSize.width, parentViewSize.width))/2 widthConstraint?.constant = pullUpControllerPreferredSize.width heightConstraint?.constant = pullUpControllerPreferredSize.height + heightConstraint?.priority = .defaultLow + bottomConstraint?.constant = 0 } private func setLandscapeConstraints() { - topConstraint?.constant = pullUpControllerPreferredLandscapeFrame.origin.y - leftConstraint?.constant = pullUpControllerPreferredLandscapeFrame.origin.x - widthConstraint?.constant = pullUpControllerPreferredLandscapeFrame.width - heightConstraint?.constant = pullUpControllerPreferredLandscapeFrame.height + guard + let parentViewHeight = parent?.view.frame.height + else { return } + let landscapeFrame = pullUpControllerPreferredLandscapeFrame + topConstraint?.constant = landscapeFrame.origin.y + leftConstraint?.constant = landscapeFrame.origin.x + widthConstraint?.constant = landscapeFrame.width + heightConstraint?.constant = landscapeFrame.height + heightConstraint?.priority = .defaultHigh + bottomConstraint?.constant = parentViewHeight - landscapeFrame.height - landscapeFrame.origin.y } } From 723d26c863f66b9edeae69199205d4603b7a24d6 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Sun, 28 Oct 2018 21:31:35 +0100 Subject: [PATCH 30/73] Clean up code --- PullUpController/PullUpController.swift | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 9f0bea2..df9c09a 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -96,6 +96,12 @@ open class PullUpController: UIViewController { private var initialInternalScrollViewContentOffset: CGPoint = .zero private var initialStickyPointOffset: CGFloat? + private var currentStickyPointIndex: Int { + let stickyPointTreshold = (self.parent?.view.frame.height ?? 0) - (topConstraint?.constant ?? 0) + let stickyPointsLessCurrentPosition = pullUpControllerAllStickyPoints.map { abs($0 - stickyPointTreshold) } + guard let minStickyPointDifference = stickyPointsLessCurrentPosition.min() else { return 0 } + return stickyPointsLessCurrentPosition.index(of: minStickyPointDifference) ?? 0 + } // MARK: - Open methods @@ -145,7 +151,6 @@ open class PullUpController: UIViewController { } } - open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { let isNewSizePortrait = size.height > size.width var targetStickyPoint: CGFloat? @@ -222,13 +227,6 @@ open class PullUpController: UIViewController { } } - private var currentStickyPointIndex: Int { - let stickyPointTreshold = (self.parent?.view.frame.height ?? 0) - (topConstraint?.constant ?? 0) - let stickyPointsLessCurrentPosition = pullUpControllerAllStickyPoints.map { abs($0 - stickyPointTreshold) } - guard let minStickyPointDifference = stickyPointsLessCurrentPosition.min() else { return 0 } - return stickyPointsLessCurrentPosition.index(of: minStickyPointDifference) ?? 0 - } - private func nearestStickyPointY(yVelocity: CGFloat) -> CGFloat { var currentStickyPointIndex = self.currentStickyPointIndex if abs(yVelocity) > 700 { // 1000 points/sec = "fast" scroll From ed64c03038d75f3ba206e84f6bc3c977056149f0 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Sun, 28 Oct 2018 21:48:53 +0100 Subject: [PATCH 31/73] Provide a way to customize the animations This will also fix #33 --- .../UI/SearchViewController.swift | 12 +++++++ PullUpController/PullUpController.swift | 36 ++++++++++++++----- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index e793095..a026666 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -121,6 +121,18 @@ class SearchViewController: PullUpController { return true } + override func pullUpControllerAnimate(withDuration duration: TimeInterval, + animations: @escaping () -> Void, + completion: ((Bool) -> Void)?) { + UIView.animate(withDuration: 0.3, + delay: 0, + usingSpringWithDamping: 0.7, + initialSpringVelocity: 0, + options: .curveEaseInOut, + animations: animations, + completion: completion) + } + } // MARK: - UISearchBarDelegate diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index df9c09a..5f2fbb5 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -120,7 +120,7 @@ open class PullUpController: UIViewController { topConstraint?.constant = (parent?.view.frame.height ?? 0) - visiblePoint if animated { - UIView.animate( + pullUpControllerAnimate( withDuration: 0.3, animations: { [weak self] in self?.parent?.view?.layoutIfNeeded() @@ -146,9 +146,26 @@ open class PullUpController: UIViewController { refreshConstraints(newSize: parentView.frame.size, customTopOffset: parentView.frame.size.height - (pullUpControllerAllStickyPoints.first ?? 0)) - UIView.animate(withDuration: animated ? 0.3 : 0) { [weak self] in - self?.view.layoutIfNeeded() - } + pullUpControllerAnimate( + withDuration: animated ? 0.3 : 0, + animations: { [weak self] in + self?.view.layoutIfNeeded() + }, + completion: nil) + } + + /** + This method will be called when an animation needs to be performed. + You can consider override this method and customize the animation using the method + `UIView.animate(withDuration:, delay:, usingSpringWithDamping:, initialSpringVelocity:, options:, animations:, completion:)` + - parameter duration: The total duration of the animations, measured in seconds. If you specify a negative value or 0, the changes are made without animating them. + - parameter animations: A block object containing the changes to commit to the views. + - parameter completion: A block object to be executed when the animation sequence ends. + */ + open func pullUpControllerAnimate(withDuration duration: TimeInterval, + animations: @escaping () -> Void, + completion: ((Bool) -> Void)?) { + UIView.animate(withDuration: duration, animations: animations, completion: completion) } open override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { @@ -332,7 +349,7 @@ open class PullUpController: UIViewController { topConstraint?.constant = value onDrag?(value) - UIView.animate( + pullUpControllerAnimate( withDuration: animationDuration ?? 0, animations: { [weak self] in self?.parent?.view.layoutIfNeeded() @@ -396,9 +413,12 @@ extension UIViewController { addChild(pullUpController) pullUpController.setup(superview: view, initialStickyPointOffset: initialStickyPointOffset) if animated { - UIView.animate(withDuration: 0.3) { [weak self] in - self?.view.layoutIfNeeded() - } + pullUpController.pullUpControllerAnimate( + withDuration: 0.3, + animations: { [weak self] in + self?.view.layoutIfNeeded() + }, + completion: nil) } else { view.layoutIfNeeded() } From 14df11d01ddfb311666241d9bf49abd57a10cecc Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Sun, 28 Oct 2018 21:49:08 +0100 Subject: [PATCH 32/73] Bump podspec version --- PullUpController.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index 95df732..05d8494 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.5.0' + s.version = '0.5.1' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } From 26e254eee6462b643db201d6c47a0e728aceb99d Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Sun, 28 Oct 2018 21:58:13 +0100 Subject: [PATCH 33/73] Update readme --- README.md | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 74456cc..e0925c3 100644 --- a/README.md +++ b/README.md @@ -17,19 +17,19 @@ Create your own pull up controller with multiple sticky points like in iOS Maps # Setup 1. Add `pod 'PullUpController'` to your Podfile or copy `PullUpController.swift` into your project 2. Make sure the view controller that will be your pull up controller inherits from `PullUpController` -3. Add the controller as child of your main controller using `addPullUpController(<#T##PullUpController#>)` +3. Add the controller as child of your main controller using `addPullUpController(<#T##PullUpController#>, initialStickyPointOffset: <#T##CGFloat#>, animated: <#T##Bool#>)` # Customization You can customize the controller behavior by overriding the followings properties: -`pullUpControllerPreviewOffset: CGFloat` ->The desired height in screen units expressed in the pull up controller coordinate system that will be initially showed. ->The default value is ```50``` - `pullUpControllerPreferredSize: CGSize` >The desired size of the pull up controller’s view, in screen units. >The default value is width: `UIScreen.main.bounds.width, height: 400`. +`pullUpControllerPreferredLandscapeFrame: CGRect` +>The desired size of the pull up controller’s view, in screen units when the device is in landscape mode. +>The default value is `(x: 10, y: 10, width: 300, height: UIScreen.main.bounds.height - 20)`. + `pullUpControllerMiddleStickyPoints: [CGFloat]` >A list of y values, in screen units expressed in the pull up controller coordinate system. >At the end of the gestures the pull up controller will scroll to the nearest point in the list. @@ -39,19 +39,11 @@ You can customize the controller behavior by overriding the followings propertie > >For a complete list of all the sticky points you can use `pullUpControllerAllStickyPoints` -`pullUpControllerAllStickyPoints: [CGFloat]` ->A list of y values, in screen units expressed in the pull up controller coordinate system. ->At the end of the gesture the pull up controller will scroll at the nearest point in the list. - `pullUpControllerIsBouncingEnabled: Bool` >A Boolean value that determines whether bouncing occurs when scrolling reaches the end of the pull up controller's view size. >The default value is `false`. -`pullUpControllerPreferredLandscapeFrame: CGRect` ->The desired size of the pull up controller’s view, in screen units when the device is in landscape mode. ->The default value is `(x: 10, y: 10, width: 300, height: UIScreen.main.bounds.height - 20)`. - -It's possible to change the view controller's view position by using the method +It's possible to change the view controller's view position programmatically by using the method `pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, completion: (() -> Void)?)` >This method will move the pull up controller's view in order to show the provided visible point. @@ -60,6 +52,15 @@ It's possible to change the view controller's view position by using the method >- `visiblePoint`: the y value to make visible, in screen units expressed in the pull up controller coordinate system. >- `completion`: The closure to execute after the animation is completed. This block has no return value and takes no parameters. You may specify nil for this parameter. +By overriding the following method it is possible to customize all the animations performed by the controller's view. + +`pullUpControllerAnimate(withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)?)` + +To observe the PullUpController's view state there're some usefull callbacks such as: +- `willMoveToStickyPoint: ((_ point: CGFloat) -> Void)?` +- `didMoveToStickyPoint: ((_ point: CGFloat) -> Void)?` +- `onDrag: ((_ point: CGFloat) -> Void)?` + PullUpController is easy draggable even if your `PullUpController`'s view contains a `UIScrollView`, just attach it to the controller itself with the following method: `<#T##UIScrollView#>.attach(to: <#T##PullUpController#>)` >Attach the scroll view to the provided pull up controller in order to move it with the scroll view content. From 03d1070f89b935e696a21ff350e0cd2787ca73c5 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 1 Nov 2018 17:54:24 +0100 Subject: [PATCH 34/73] Use old build system to prevent cocoapod issues on xcode 10 https://github.com/CocoaPods/CocoaPods/issues/8073 --- .../xcshareddata/WorkspaceSettings.xcsettings | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Example/PullUpController.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings diff --git a/Example/PullUpController.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/Example/PullUpController.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..949b678 --- /dev/null +++ b/Example/PullUpController.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + BuildSystemType + Original + + From c3a39f6e3abf627d2d744571d2af9847d1ff0506 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 1 Nov 2018 17:54:57 +0100 Subject: [PATCH 35/73] Add the possibility to customize the bounce offset by overriding `pullUpControllerBounceOffset` --- PullUpController/PullUpController.swift | 49 +++++++++++++------------ 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 5f2fbb5..65fff8e 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -60,11 +60,11 @@ open class PullUpController: UIViewController { } /** - A Boolean value that determines whether bouncing occurs when scrolling reaches the end of the pull up controller's view size. - The default value is false. + A CGFloat value that determines how much the pull up controller's view can bounce outside it's size. + The default value is 0 and that means the the view cannot expand beyond its size. */ - open var pullUpControllerIsBouncingEnabled: Bool { - return false + open var pullUpControllerBounceOffset: CGFloat { + return 0 } // MARK: - Public properties @@ -309,18 +309,26 @@ open class PullUpController: UIViewController { // disable the bounces when the user is able to drag the view through the internal scroll view scrollView.bounces = false if isScrollingDown { - // take the initial internal scroll view content offset into account when scrolling down - yTranslation -= initialInternalScrollViewContentOffset.y + if pullUpControllerBounceOffset <= 0 { + // take the initial internal scroll view content offset into account when scrolling down is the bouncing is not enabled + yTranslation -= initialInternalScrollViewContentOffset.y + } initialInternalScrollViewContentOffset = .zero } else { - // keep the initial internal scroll view content offset when scrolling up - internalScrollView?.contentOffset = initialInternalScrollViewContentOffset + if abs(scrollViewPanVelocity) > 1000 { + scrollView.isScrollEnabled = false + } + if topConstraint.constant > parentViewHeight - lastStickyPoint - pullUpControllerBounceOffset { + // keep the initial internal scroll view content offset when scrolling up + internalScrollView?.contentOffset = initialInternalScrollViewContentOffset + } } } setTopOffset(topConstraint.constant + yTranslation) case .ended: internalScrollView?.bounces = true + internalScrollView?.isScrollEnabled = true guard shouldDragView else { return } @@ -340,15 +348,14 @@ open class PullUpController: UIViewController { let parentViewHeight = parent?.view.frame.height else { return } var value = value - if !pullUpControllerIsBouncingEnabled, - let firstStickyPoint = pullUpControllerAllStickyPoints.first, + if let firstStickyPoint = pullUpControllerAllStickyPoints.first, let lastStickyPoint = pullUpControllerAllStickyPoints.last { - value = max(value, parentViewHeight - lastStickyPoint) - value = min(value, parentViewHeight - firstStickyPoint) + value = max(value, parentViewHeight - lastStickyPoint - pullUpControllerBounceOffset) + value = min(value, parentViewHeight - firstStickyPoint + pullUpControllerBounceOffset) } topConstraint?.constant = value onDrag?(value) - + pullUpControllerAnimate( withDuration: animationDuration ?? 0, animations: { [weak self] in @@ -412,16 +419,12 @@ extension UIViewController { assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") addChild(pullUpController) pullUpController.setup(superview: view, initialStickyPointOffset: initialStickyPointOffset) - if animated { - pullUpController.pullUpControllerAnimate( - withDuration: 0.3, - animations: { [weak self] in - self?.view.layoutIfNeeded() - }, - completion: nil) - } else { - view.layoutIfNeeded() - } + pullUpController.pullUpControllerAnimate( + withDuration: animated ? 0.3 : 0, + animations: { [weak self] in + self?.view.layoutIfNeeded() + }, + completion: nil) } /** From e39ba2b2edb9ab49187f253044d743431e939654 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 1 Nov 2018 17:58:13 +0100 Subject: [PATCH 36/73] Document code --- PullUpController/PullUpController.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 65fff8e..73c0bf7 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -246,6 +246,7 @@ open class PullUpController: UIViewController { private func nearestStickyPointY(yVelocity: CGFloat) -> CGFloat { var currentStickyPointIndex = self.currentStickyPointIndex + // TODO: - allow this property to be customized if abs(yVelocity) > 700 { // 1000 points/sec = "fast" scroll if yVelocity > 0 { currentStickyPointIndex = max(currentStickyPointIndex - 1, 0) @@ -315,6 +316,8 @@ open class PullUpController: UIViewController { } initialInternalScrollViewContentOffset = .zero } else { + // If the user is scrolling "fast" disable the interna scroll view scroll + // TODO: - allow this property to be customized if abs(scrollViewPanVelocity) > 1000 { scrollView.isScrollEnabled = false } From d98cd907b7134066ad5bcdfda24fa9b8787ea413 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 1 Nov 2018 18:07:01 +0100 Subject: [PATCH 37/73] Fix `willMoveToStickyPoint` and `didMoveToStickyPoint` handling --- PullUpController/PullUpController.swift | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 73c0bf7..86e0388 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -255,7 +255,6 @@ open class PullUpController: UIViewController { } } - willMoveToStickyPoint?(pullUpControllerAllStickyPoints[currentStickyPointIndex]) return (parent?.view.frame.height ?? 0) - pullUpControllerAllStickyPoints[currentStickyPointIndex] } @@ -356,17 +355,27 @@ open class PullUpController: UIViewController { value = max(value, parentViewHeight - lastStickyPoint - pullUpControllerBounceOffset) value = min(value, parentViewHeight - firstStickyPoint + pullUpControllerBounceOffset) } + let targetPoint = parentViewHeight - value + /* + `willMoveToStickyPoint` and `didMoveToStickyPoint` should be + called only if the user has ended the gesture + */ + let shouldNotifyObserver = animationDuration != nil topConstraint?.constant = value onDrag?(value) + if shouldNotifyObserver { + willMoveToStickyPoint?(targetPoint) + } pullUpControllerAnimate( withDuration: animationDuration ?? 0, animations: { [weak self] in self?.parent?.view.layoutIfNeeded() }, completion: { [weak self] _ in - let point = (self?.parent?.view.frame.height ?? 0.0) - (self?.topConstraint?.constant ?? 0.0) - self?.didMoveToStickyPoint?(point) + if shouldNotifyObserver { + self?.didMoveToStickyPoint?(targetPoint) + } } ) } From 21a8fd83df2ada256cd7309286c62c3cd7a75556 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 1 Nov 2018 18:07:15 +0100 Subject: [PATCH 38/73] Fix `onDrag` point coordinate system MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This should also fix #38 since with the `onDrag` closure it is always possible to know the pull up controller’s view position --- PullUpController/PullUpController.swift | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 86e0388..0253ea7 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -362,8 +362,7 @@ open class PullUpController: UIViewController { */ let shouldNotifyObserver = animationDuration != nil topConstraint?.constant = value - onDrag?(value) - + onDrag?(targetPoint) if shouldNotifyObserver { willMoveToStickyPoint?(targetPoint) } From 6c661d1c8cbe71155d362ca2009484b0b6265f96 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 1 Nov 2018 18:13:00 +0100 Subject: [PATCH 39/73] Use newest bounce api --- Example/PullUpController/UI/SearchViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index a026666..e3c2879 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -117,8 +117,8 @@ class SearchViewController: PullUpController { } } - override var pullUpControllerIsBouncingEnabled: Bool { - return true + override var pullUpControllerBounceOffset: CGFloat { + return 20 } override func pullUpControllerAnimate(withDuration duration: TimeInterval, From a31ff5f095155f9534e1dda2232b4698f514d4c5 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 1 Nov 2018 18:13:35 +0100 Subject: [PATCH 40/73] Call `willMoveToStickyPoint` and `didMoveToStickyPoint` in `moveToVisiblePoint` Fix #35 --- PullUpController/PullUpController.swift | 29 +++++++++++-------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 0253ea7..d3542da 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -115,23 +115,20 @@ open class PullUpController: UIViewController { */ open func pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, animated: Bool, completion: (() -> Void)?) { guard - isPortrait + isPortrait, + let parentViewHeight = parent?.view.frame.height else { return } - topConstraint?.constant = (parent?.view.frame.height ?? 0) - visiblePoint - - if animated { - pullUpControllerAnimate( - withDuration: 0.3, - animations: { [weak self] in - self?.parent?.view?.layoutIfNeeded() - }, - completion: { _ in - completion?() - }) - } else { - parent?.view?.layoutIfNeeded() - completion?() - } + topConstraint?.constant = parentViewHeight - visiblePoint + willMoveToStickyPoint?(visiblePoint) + pullUpControllerAnimate( + withDuration: animated ? 0.3 : 0, + animations: { [weak self] in + self?.parent?.view?.layoutIfNeeded() + }, + completion: { [weak self] _ in + self?.didMoveToStickyPoint?(visiblePoint) + completion?() + }) } /** From 19b3522de3883dbf19ab0634df1f829554691e23 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Thu, 1 Nov 2018 18:22:33 +0100 Subject: [PATCH 41/73] Fix #38: Expose the current point offset --- PullUpController/PullUpController.swift | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index d3542da..cdef663 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -67,6 +67,17 @@ open class PullUpController: UIViewController { return 0 } + /** + A CGFloat value that represent the current point, expressed in the pull up controller coordinate system, + where the pull up controller's view is positioned. + */ + open var pullUpControllerCurrentPointOffset: CGFloat { + guard + let parentViewHeight = parent?.view.frame.height + else { return 0 } + return parentViewHeight - (topConstraint?.constant ?? 0) + } + // MARK: - Public properties /** From dcaff4d2a65bc78782213b7d9d7503754b11435e Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Fri, 2 Nov 2018 20:32:25 +0100 Subject: [PATCH 42/73] =?UTF-8?q?Remove=20height=20slider=20(it=20wasn?= =?UTF-8?q?=E2=80=99t=20working=20anymore=20anyway)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Example/PullUpController/UI/Main.storyboard | 38 +++++-------------- .../UI/MapViewController.swift | 26 +++---------- 2 files changed, 16 insertions(+), 48 deletions(-) diff --git a/Example/PullUpController/UI/Main.storyboard b/Example/PullUpController/UI/Main.storyboard index a0c6b1d..bdb5226 100644 --- a/Example/PullUpController/UI/Main.storyboard +++ b/Example/PullUpController/UI/Main.storyboard @@ -22,10 +22,10 @@ - + - + @@ -36,7 +36,7 @@ - + @@ -44,25 +44,8 @@ - - - - - - - - - - - - - + - + @@ -131,7 +114,6 @@ - @@ -190,21 +172,21 @@ - + - + - + - + - + diff --git a/Example/PullUpController/UI/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift index 2f0b0fc..ca1b259 100644 --- a/Example/PullUpController/UI/MapViewController.swift +++ b/Example/PullUpController/UI/MapViewController.swift @@ -18,9 +18,10 @@ class MapViewController: UIViewController { } } @IBOutlet private weak var widthSlider: UISlider! - @IBOutlet private weak var heightSlider: UISlider! @IBOutlet private weak var initialStateSegmentedControl: UISegmentedControl! + private var originalPullUpControllerViewSize: CGSize = .zero + private func makeSearchViewControllerIfNeeded() -> SearchViewController { let currentPullUpController = childViewControllers .filter({ $0 is SearchViewController }) @@ -31,18 +32,15 @@ class MapViewController: UIViewController { } else { pullUpController.initialState = .expanded } + if originalPullUpControllerViewSize == .zero { + originalPullUpControllerViewSize = pullUpController.view.bounds.size + } return pullUpController } override func viewDidLoad() { super.viewDidLoad() addPullUpController() - - let pullUpController = makeSearchViewControllerIfNeeded() - widthSlider.maximumValue = Float(pullUpController.portraitSize.width) - widthSlider.value = widthSlider.maximumValue - heightSlider.maximumValue = Float(pullUpController.portraitSize.height) - heightSlider.value = heightSlider.maximumValue } private func addPullUpController() { @@ -73,8 +71,8 @@ class MapViewController: UIViewController { } @IBAction private func widthSliderValueChanged(_ sender: UISlider) { - let width = CGFloat(sender.value) let pullUpController = makeSearchViewControllerIfNeeded() + let width = originalPullUpControllerViewSize.width * CGFloat(sender.value) pullUpController.portraitSize = CGSize(width: width, height: pullUpController.portraitSize.height) pullUpController.landscapeFrame = CGRect(origin: pullUpController.landscapeFrame.origin, @@ -83,17 +81,5 @@ class MapViewController: UIViewController { pullUpController.updatePreferredFrameIfNeeded(animated: true) } - @IBAction private func heightSliderValueChanged(_ sender: UISlider) { - let height = CGFloat(sender.value) - let pullUpController = makeSearchViewControllerIfNeeded() - pullUpController.portraitSize = CGSize(width: pullUpController.portraitSize.width, - height: height) - pullUpController.landscapeFrame = CGRect(origin: pullUpController.landscapeFrame.origin, - size: CGSize(width: pullUpController.landscapeFrame.width, - height: height)) - pullUpController.updatePreferredFrameIfNeeded(animated: true) - - } - } From cded1c673abafe6fd59cd81588f91628d8f6b067 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Fri, 2 Nov 2018 20:34:42 +0100 Subject: [PATCH 43/73] Add my bundle id and dev team When you need to test on device you know things got serious :) --- Example/PullUpController.xcodeproj/project.pbxproj | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Example/PullUpController.xcodeproj/project.pbxproj b/Example/PullUpController.xcodeproj/project.pbxproj index fafdee2..6b82650 100644 --- a/Example/PullUpController.xcodeproj/project.pbxproj +++ b/Example/PullUpController.xcodeproj/project.pbxproj @@ -165,6 +165,7 @@ TargetAttributes = { 607FACCF1AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; + DevelopmentTeam = X9253HG4XT; LastSwiftMigration = 0900; }; }; @@ -362,10 +363,11 @@ baseConfigurationReference = 9AB34C6007A366EB15327B6E /* Pods-PullUpController_Example.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = X9253HG4XT; INFOPLIST_FILE = "$(SRCROOT)/PullUpController/Supporting files/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.test; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; @@ -377,10 +379,11 @@ baseConfigurationReference = 6D13751B90ADB8E6A7085A3F /* Pods-PullUpController_Example.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = X9253HG4XT; INFOPLIST_FILE = "$(SRCROOT)/PullUpController/Supporting files/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MODULE_NAME = ExampleApp; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.demo.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.test; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_SWIFT3_OBJC_INFERENCE = Default; SWIFT_VERSION = 4.0; From b07dbd545ee0baf804e24c95e97513246bec2d62 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Fri, 2 Nov 2018 21:51:55 +0100 Subject: [PATCH 44/73] Refactor gesture recognizers handling --- PullUpController/PullUpController.swift | 136 +++++++++++------------- 1 file changed, 63 insertions(+), 73 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index cdef663..83a7da7 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -215,10 +215,10 @@ open class PullUpController: UIViewController { } private func setupPanGestureRecognizer() { + internalScrollView?.panGestureRecognizer.addTarget(self, action: #selector(handleScrollViewGestureRecognizer(_:))) panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestureRecognizer(_:))) panGestureRecognizer?.minimumNumberOfTouches = 1 panGestureRecognizer?.maximumNumberOfTouches = 1 - panGestureRecognizer?.delegate = self if let panGestureRecognizer = panGestureRecognizer { view.addGestureRecognizer(panGestureRecognizer) } @@ -266,93 +266,92 @@ open class PullUpController: UIViewController { return (parent?.view.frame.height ?? 0) - pullUpControllerAllStickyPoints[currentStickyPointIndex] } - @objc private func handlePanGestureRecognizer(_ gestureRecognizer: UIPanGestureRecognizer) { + @objc private func handleScrollViewGestureRecognizer(_ gestureRecognizer: UIPanGestureRecognizer) { guard isPortrait, + let scrollView = internalScrollView, let topConstraint = topConstraint, let lastStickyPoint = pullUpControllerAllStickyPoints.last, - let parentView = parent?.view + let parentViewHeight = parent?.view.bounds.height else { return } - let parentViewHeight = parentView.frame.height - var yTranslation = gestureRecognizer.translation(in: parentView).y - gestureRecognizer.setTranslation(.zero, in: view) + let isFullOpened = topConstraint.constant <= parentViewHeight - lastStickyPoint + let yTranslation = gestureRecognizer.translation(in: scrollView).y + let isScrollingDown = gestureRecognizer.velocity(in: scrollView).y > 0 - let scrollViewPanVelocity = internalScrollView?.panGestureRecognizer.velocity(in: parentView).y ?? 0 - let isScrollingDown = scrollViewPanVelocity > 0 + /** + The user should be able to drag the view down through the internal scroll view when + - the scroll direction is down (`isScrollingDown`) + - the internal scroll view is scrolled to the top (`scrollView.contentOffset.y <= 0`) + */ + let shouldDragViewDown = isScrollingDown && scrollView.contentOffset.y <= 0 /** - A Boolean value that controls whether the scroll view scroll should pan the parent view up **or** down. - - 1. The user should be able to drag the view down through the internal scroll view when - - the scroll direction is down (`isScrollingDown`) - - the internal scroll view is scrolled to the top (`scrollView.contentOffset.y <= 0`) - - 2. The user should be able to drag the view up through the internal scroll view when - - the scroll direction is up (`!isScrollingDown`) - - the PullUpController's view is fully opened. (`topConstraint.constant != parentViewHeight - lastStickyPoint`) + The user should be able to drag the view up through the internal scroll view when + - the scroll direction is up (`!isScrollingDown`) + - the PullUpController's view is fully opened. (`topConstraint.constant <= parentViewHeight - lastStickyPoint`) */ - let shouldDragView: Bool = { - // Condition 1 - let shouldDragViewDown = isScrollingDown && internalScrollView?.contentOffset.y ?? 0 <= 0 - // Condition 2 - let shouldDragViewUp = !isScrollingDown && topConstraint.constant != parentViewHeight - lastStickyPoint - return shouldDragViewDown || shouldDragViewUp - }() + let shouldDragViewUp = !isScrollingDown && !isFullOpened + let shouldDragView = shouldDragViewDown || shouldDragViewUp + + if shouldDragViewUp { + scrollView.setContentOffset(.zero, animated: false) + } switch gestureRecognizer.state { case .began: - initialInternalScrollViewContentOffset = internalScrollView?.contentOffset ?? .zero + initialInternalScrollViewContentOffset = scrollView.contentOffset case .changed: - // the user is scrolling the internal scroll view - if scrollViewPanVelocity != 0, let scrollView = internalScrollView { - // if the user shouldn't be able to drag the view up through the internal scroll view reset the translation - guard - shouldDragView - else { - yTranslation = 0 - return - } - // disable the bounces when the user is able to drag the view through the internal scroll view - scrollView.bounces = false - if isScrollingDown { - if pullUpControllerBounceOffset <= 0 { - // take the initial internal scroll view content offset into account when scrolling down is the bouncing is not enabled - yTranslation -= initialInternalScrollViewContentOffset.y - } - initialInternalScrollViewContentOffset = .zero - } else { - // If the user is scrolling "fast" disable the interna scroll view scroll - // TODO: - allow this property to be customized - if abs(scrollViewPanVelocity) > 1000 { - scrollView.isScrollEnabled = false - } - if topConstraint.constant > parentViewHeight - lastStickyPoint - pullUpControllerBounceOffset { - // keep the initial internal scroll view content offset when scrolling up - internalScrollView?.contentOffset = initialInternalScrollViewContentOffset - } - } - } + guard + shouldDragView + else { break } + scrollView.bounces = false + setTopOffset(topConstraint.constant + yTranslation - initialInternalScrollViewContentOffset.y) + gestureRecognizer.setTranslation(initialInternalScrollViewContentOffset, in: scrollView) + + case .ended: + scrollView.bounces = true + goToNearestStickyPoint(verticalVelocity: gestureRecognizer.velocity(in: view).y) + + default: + break + } + + } + + @objc private func handlePanGestureRecognizer(_ gestureRecognizer: UIPanGestureRecognizer) { + guard + isPortrait, + let topConstraint = topConstraint + else { return } + + let yTranslation = gestureRecognizer.translation(in: view).y + + switch gestureRecognizer.state { + case .changed: setTopOffset(topConstraint.constant + yTranslation) + gestureRecognizer.setTranslation(.zero, in: view) case .ended: - internalScrollView?.bounces = true - internalScrollView?.isScrollEnabled = true - guard - shouldDragView - else { return } - let yVelocity = gestureRecognizer.velocity(in: view).y // v = px/s - let targetTopOffset = nearestStickyPointY(yVelocity: yVelocity) - let distanceToConver = topConstraint.constant - targetTopOffset // px - let animationDuration = max(0.08, min(0.3, TimeInterval(abs(distanceToConver/yVelocity)))) // s = px/v - setTopOffset(targetTopOffset, animationDuration: animationDuration) + goToNearestStickyPoint(verticalVelocity: gestureRecognizer.velocity(in: view).y) default: break } } + private func goToNearestStickyPoint(verticalVelocity: CGFloat) { + guard + isPortrait, + let topConstraint = topConstraint + else { return } + let targetTopOffset = nearestStickyPointY(yVelocity: verticalVelocity) // v = px/s + let distanceToConver = topConstraint.constant - targetTopOffset // px + let animationDuration = max(0.08, min(0.3, TimeInterval(abs(distanceToConver/verticalVelocity)))) // s = px/v + setTopOffset(targetTopOffset, animationDuration: animationDuration) + } + private func setTopOffset(_ value: CGFloat, animationDuration: TimeInterval? = nil) { guard let parentViewHeight = parent?.view.frame.height @@ -415,15 +414,6 @@ open class PullUpController: UIViewController { } -extension PullUpController: UIGestureRecognizerDelegate { - - public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, - shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool { - return true - } - -} - extension UIViewController { /** From 62f6cca9f5cac11f484a5c7062b9f49314e1b787 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Sun, 4 Nov 2018 12:19:07 +0100 Subject: [PATCH 45/73] Disable content bounce when swiping to the bottom --- PullUpController/PullUpController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 83a7da7..ebe7c21 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -294,7 +294,7 @@ open class PullUpController: UIViewController { let shouldDragViewUp = !isScrollingDown && !isFullOpened let shouldDragView = shouldDragViewDown || shouldDragViewUp - if shouldDragViewUp { + if shouldDragView { scrollView.setContentOffset(.zero, animated: false) } From f51ba41d771d6a02db6d0300c56ee2ae33c4cbce Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Sun, 4 Nov 2018 18:44:12 +0100 Subject: [PATCH 46/73] Fix bouncing issue This should also fix #36 --- PullUpController/PullUpController.swift | 27 ++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index ebe7c21..0374de5 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -295,6 +295,7 @@ open class PullUpController: UIViewController { let shouldDragView = shouldDragViewDown || shouldDragViewUp if shouldDragView { + scrollView.bounces = false scrollView.setContentOffset(.zero, animated: false) } @@ -306,7 +307,6 @@ open class PullUpController: UIViewController { guard shouldDragView else { break } - scrollView.bounces = false setTopOffset(topConstraint.constant + yTranslation - initialInternalScrollViewContentOffset.y) gestureRecognizer.setTranslation(initialInternalScrollViewContentOffset, in: scrollView) @@ -330,7 +330,7 @@ open class PullUpController: UIViewController { switch gestureRecognizer.state { case .changed: - setTopOffset(topConstraint.constant + yTranslation) + setTopOffset(topConstraint.constant + yTranslation, allowBounce: true) gestureRecognizer.setTranslation(.zero, in: view) case .ended: @@ -352,16 +352,25 @@ open class PullUpController: UIViewController { setTopOffset(targetTopOffset, animationDuration: animationDuration) } - private func setTopOffset(_ value: CGFloat, animationDuration: TimeInterval? = nil) { + private func setTopOffset(_ value: CGFloat, + animationDuration: TimeInterval? = nil, + allowBounce: Bool = false) { guard let parentViewHeight = parent?.view.frame.height else { return } - var value = value - if let firstStickyPoint = pullUpControllerAllStickyPoints.first, - let lastStickyPoint = pullUpControllerAllStickyPoints.last { - value = max(value, parentViewHeight - lastStickyPoint - pullUpControllerBounceOffset) - value = min(value, parentViewHeight - firstStickyPoint + pullUpControllerBounceOffset) - } + // Apply right value bounding for the provided bounce offset if needed + let value: CGFloat = { + guard + let firstStickyPoint = pullUpControllerAllStickyPoints.first, + let lastStickyPoint = pullUpControllerAllStickyPoints.last + else { + return value + } + let bounceOffset = allowBounce ? pullUpControllerBounceOffset : 0 + let minValue = parentViewHeight - lastStickyPoint - bounceOffset + let maxValue = parentViewHeight - firstStickyPoint + bounceOffset + return max(min(value, maxValue), minValue) + }() let targetPoint = parentViewHeight - value /* `willMoveToStickyPoint` and `didMoveToStickyPoint` should be From 341dbe66bb3ff6b1ef7751a6991d785381dd80c5 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 20 Nov 2018 22:53:14 +0100 Subject: [PATCH 47/73] Add action to the method `pullUpControllerAnimate` in order to better customize animations --- PullUpController/PullUpController.swift | 47 +++++++++++++++++++++---- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 0374de5..09a2201 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -10,6 +10,21 @@ import UIKit open class PullUpController: UIViewController { + public enum Action { + /** + The action used when the pull up controller's view is added to its parent view + */ + case add + /** + The action used when the pull up controller's view is removed to its parent view + */ + case remove + /** + The action used when the pull up controller's view position change + */ + case move + } + // MARK: - Open properties /** @@ -132,6 +147,7 @@ open class PullUpController: UIViewController { topConstraint?.constant = parentViewHeight - visiblePoint willMoveToStickyPoint?(visiblePoint) pullUpControllerAnimate( + action: .move, withDuration: animated ? 0.3 : 0, animations: { [weak self] in self?.parent?.view?.layoutIfNeeded() @@ -155,6 +171,7 @@ open class PullUpController: UIViewController { customTopOffset: parentView.frame.size.height - (pullUpControllerAllStickyPoints.first ?? 0)) pullUpControllerAnimate( + action: .move, withDuration: animated ? 0.3 : 0, animations: { [weak self] in self?.view.layoutIfNeeded() @@ -166,11 +183,13 @@ open class PullUpController: UIViewController { This method will be called when an animation needs to be performed. You can consider override this method and customize the animation using the method `UIView.animate(withDuration:, delay:, usingSpringWithDamping:, initialSpringVelocity:, options:, animations:, completion:)` + - parameter action: The action that is about to be performed, see `PullUpController.Action` for more info - parameter duration: The total duration of the animations, measured in seconds. If you specify a negative value or 0, the changes are made without animating them. - parameter animations: A block object containing the changes to commit to the views. - parameter completion: A block object to be executed when the animation sequence ends. */ - open func pullUpControllerAnimate(withDuration duration: TimeInterval, + open func pullUpControllerAnimate(action: Action, + withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)?) { UIView.animate(withDuration: duration, animations: animations, completion: completion) @@ -383,6 +402,7 @@ open class PullUpController: UIViewController { willMoveToStickyPoint?(targetPoint) } pullUpControllerAnimate( + action: .move, withDuration: animationDuration ?? 0, animations: { [weak self] in self?.parent?.view.layoutIfNeeded() @@ -421,6 +441,13 @@ open class PullUpController: UIViewController { bottomConstraint?.constant = parentViewHeight - landscapeFrame.height - landscapeFrame.origin.y } + fileprivate func hide() { + guard + let parentViewHeight = parent?.view.frame.height + else { return } + topConstraint?.constant = parentViewHeight + } + } extension UIViewController { @@ -438,6 +465,7 @@ extension UIViewController { addChild(pullUpController) pullUpController.setup(superview: view, initialStickyPointOffset: initialStickyPointOffset) pullUpController.pullUpControllerAnimate( + action: .add, withDuration: animated ? 0.3 : 0, animations: { [weak self] in self?.view.layoutIfNeeded() @@ -451,11 +479,18 @@ extension UIViewController { - parameter animated: Pass true to animate the removing; otherwise, pass false. */ open func removePullUpController(_ pullUpController: PullUpController, animated: Bool) { - pullUpController.pullUpControllerMoveToVisiblePoint(0, animated: animated) { - pullUpController.willMove(toParent: nil) - pullUpController.view.removeFromSuperview() - pullUpController.removeFromParent() - } + pullUpController.hide() + pullUpController.pullUpControllerAnimate( + action: .remove, + withDuration: animated ? 0.3 : 0, + animations: { [weak self] in + self?.view.layoutIfNeeded() + }, + completion: { _ in + pullUpController.willMove(toParent: nil) + pullUpController.view.removeFromSuperview() + pullUpController.removeFromParent() + }) } } From 4ceffcae014b24dfb0b04ca2749ee4676ad41b1e Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 20 Nov 2018 23:14:48 +0100 Subject: [PATCH 48/73] Refactor `willMoveToStickyPoint`, `didMoveToStickyPoint` and`onDrag` The closure are now function to make everything more transparent, easy to understand and more iOS-SDK like. This will also fix #40 --- .../UI/SearchViewController.swift | 48 ++++++++++-------- PullUpController/PullUpController.swift | 49 ++++++++++--------- 2 files changed, 54 insertions(+), 43 deletions(-) diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index e3c2879..dc99819 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -57,18 +57,6 @@ class SearchViewController: PullUpController { tableView.attach(to: self) setupDataSource() - - willMoveToStickyPoint = { point in - print("willMoveToStickyPoint \(point)") - } - - didMoveToStickyPoint = { point in - print("didMoveToStickyPoint \(point)") - } - - onDrag = { point in - print("onDrag: \(point)") - } } override func viewDidLayoutSubviews() { @@ -77,6 +65,18 @@ class SearchViewController: PullUpController { view.layer.cornerRadius = 12 } + override func pullUpControllerWillMove(to stickyPoint: CGFloat) { + print("will move to \(stickyPoint)") + } + + override func pullUpControllerDidMove(to stickyPoint: CGFloat) { + print("did move to \(stickyPoint)") + } + + override func pullUpControllerDidDrag(to point: CGFloat) { + print("did drag to \(point)") + } + private func setupDataSource() { locations.append(("Rome", CLLocationCoordinate2D(latitude: 41.9004041, longitude: 12.4432921))) locations.append(("Milan", CLLocationCoordinate2D(latitude: 45.4625319, longitude: 9.1574741))) @@ -121,16 +121,24 @@ class SearchViewController: PullUpController { return 20 } - override func pullUpControllerAnimate(withDuration duration: TimeInterval, + override func pullUpControllerAnimate(action: PullUpController.Action, + withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)?) { - UIView.animate(withDuration: 0.3, - delay: 0, - usingSpringWithDamping: 0.7, - initialSpringVelocity: 0, - options: .curveEaseInOut, - animations: animations, - completion: completion) + switch action { + case .move: + UIView.animate(withDuration: 0.3, + delay: 0, + usingSpringWithDamping: 0.7, + initialSpringVelocity: 0, + options: .curveEaseInOut, + animations: animations, + completion: completion) + default: + UIView.animate(withDuration: 0.3, + animations: animations, + completion: completion) + } } } diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 09a2201..89f6287 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -27,24 +27,6 @@ open class PullUpController: UIViewController { // MARK: - Open properties - /** - The closure to execute before the view controller's view move to a sticky point. - The target sticky point, expressed in the pull up controller coordinate system, is provided in the closure parameter. - */ - open var willMoveToStickyPoint: ((_ point: CGFloat) -> Void)? - - /** - The closure to execute after the view controller's view move to a sticky point. - The sticky point, expressed in the pull up controller coordinate system, is provided in the closure parameter. - */ - open var didMoveToStickyPoint: ((_ point: CGFloat) -> Void)? - - /** - The closure to execute when the view controller's view is dragged. - The point, expressed in the pull up controller parent coordinate system, is provided in the closure parameter. - */ - open var onDrag: ((_ point: CGFloat) -> Void)? - /** The desired size of the pull up controller’s view, in screen units. The default value is width: UIScreen.main.bounds.width, height: 400. @@ -131,6 +113,27 @@ open class PullUpController: UIViewController { // MARK: - Open methods + /** + This method is called before the pull up controller's view move to a sticky point. + The default implementation of this method does nothing. + - parameter stickyPoint: The targer sticky point, expressed in the pull up controller coordinate system + */ + open func pullUpControllerWillMove(to stickyPoint: CGFloat) { } + + /** + This method is called after the pull up controller's view move to a sticky point. + The default implementation of this method does nothing. + - parameter stickyPoint: The targer sticky point, expressed in the pull up controller coordinate system + */ + open func pullUpControllerDidMove(to stickyPoint: CGFloat) { } + + /** + This method is called after the pull up controller's view is dragged to a point. + The default implementation of this method does nothing. + - parameter stickyPoint: The targer point, expressed in the pull up controller coordinate system + */ + open func pullUpControllerDidDrag(to point: CGFloat) { } + /** This method will move the pull up controller's view in order to show the provided visible point. @@ -145,7 +148,7 @@ open class PullUpController: UIViewController { let parentViewHeight = parent?.view.frame.height else { return } topConstraint?.constant = parentViewHeight - visiblePoint - willMoveToStickyPoint?(visiblePoint) + pullUpControllerWillMove(to: visiblePoint) pullUpControllerAnimate( action: .move, withDuration: animated ? 0.3 : 0, @@ -153,7 +156,7 @@ open class PullUpController: UIViewController { self?.parent?.view?.layoutIfNeeded() }, completion: { [weak self] _ in - self?.didMoveToStickyPoint?(visiblePoint) + self?.pullUpControllerDidMove(to: visiblePoint) completion?() }) } @@ -397,9 +400,9 @@ open class PullUpController: UIViewController { */ let shouldNotifyObserver = animationDuration != nil topConstraint?.constant = value - onDrag?(targetPoint) + pullUpControllerDidDrag(to: targetPoint) if shouldNotifyObserver { - willMoveToStickyPoint?(targetPoint) + pullUpControllerWillMove(to: targetPoint) } pullUpControllerAnimate( action: .move, @@ -409,7 +412,7 @@ open class PullUpController: UIViewController { }, completion: { [weak self] _ in if shouldNotifyObserver { - self?.didMoveToStickyPoint?(targetPoint) + self?.pullUpControllerDidMove(to: targetPoint) } } ) From 90bca9b5076168365029570f74880ca1a8b25080 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 20 Nov 2018 23:23:14 +0100 Subject: [PATCH 49/73] Clean up code and docs Fix 35 --- PullUpController/PullUpController.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 89f6287..d287f84 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -116,21 +116,21 @@ open class PullUpController: UIViewController { /** This method is called before the pull up controller's view move to a sticky point. The default implementation of this method does nothing. - - parameter stickyPoint: The targer sticky point, expressed in the pull up controller coordinate system + - parameter point: The target point, expressed in the pull up controller coordinate system */ - open func pullUpControllerWillMove(to stickyPoint: CGFloat) { } + open func pullUpControllerWillMove(to point: CGFloat) { } /** This method is called after the pull up controller's view move to a sticky point. The default implementation of this method does nothing. - - parameter stickyPoint: The targer sticky point, expressed in the pull up controller coordinate system + - parameter point: The target point, expressed in the pull up controller coordinate system */ - open func pullUpControllerDidMove(to stickyPoint: CGFloat) { } + open func pullUpControllerDidMove(to point: CGFloat) { } /** This method is called after the pull up controller's view is dragged to a point. The default implementation of this method does nothing. - - parameter stickyPoint: The targer point, expressed in the pull up controller coordinate system + - parameter stickyPoint: The target point, expressed in the pull up controller coordinate system */ open func pullUpControllerDidDrag(to point: CGFloat) { } From 4318fd7322fb103745a457d2cd70a9d28b0221a2 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 20 Nov 2018 23:28:26 +0100 Subject: [PATCH 50/73] Expose `pullUpControllerSkipPointVerticalVelocityThreshold` --- PullUpController/PullUpController.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index d287f84..bfbe103 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -75,6 +75,14 @@ open class PullUpController: UIViewController { return parentViewHeight - (topConstraint?.constant ?? 0) } + /** + A CGFloat value that represent the vertical velocity threshold (expressed in points/sec) beyond wich + the target sticky point is skippend and the view is positioned to the next one. + */ + open var pullUpControllerSkipPointVerticalVelocityThreshold: CGFloat { + return 700 + } + // MARK: - Public properties /** @@ -276,8 +284,7 @@ open class PullUpController: UIViewController { private func nearestStickyPointY(yVelocity: CGFloat) -> CGFloat { var currentStickyPointIndex = self.currentStickyPointIndex - // TODO: - allow this property to be customized - if abs(yVelocity) > 700 { // 1000 points/sec = "fast" scroll + if abs(yVelocity) > pullUpControllerSkipPointVerticalVelocityThreshold { if yVelocity > 0 { currentStickyPointIndex = max(currentStickyPointIndex - 1, 0) } else { From b0ae04ebbc54abae3ad331d1473405bcbab3ad71 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 20 Nov 2018 23:29:12 +0100 Subject: [PATCH 51/73] Bump podspec version --- PullUpController.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index 05d8494..4fec38b 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.5.1' + s.version = '0.6.0' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } From ed71118cbb21da7900f17f6838f3f8c1f30e835d Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Fri, 23 Nov 2018 18:53:56 +0100 Subject: [PATCH 52/73] Update docs --- .../UI/SearchViewController.swift | 6 +-- PullUpController/PullUpController.swift | 4 +- README.md | 42 ++++++++++++------- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index dc99819..46b4d08 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -66,15 +66,15 @@ class SearchViewController: PullUpController { } override func pullUpControllerWillMove(to stickyPoint: CGFloat) { - print("will move to \(stickyPoint)") +// print("will move to \(stickyPoint)") } override func pullUpControllerDidMove(to stickyPoint: CGFloat) { - print("did move to \(stickyPoint)") +// print("did move to \(stickyPoint)") } override func pullUpControllerDidDrag(to point: CGFloat) { - print("did drag to \(point)") +// print("did drag to \(point)") } private func setupDataSource() { diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index bfbe103..18a195a 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -122,14 +122,14 @@ open class PullUpController: UIViewController { // MARK: - Open methods /** - This method is called before the pull up controller's view move to a sticky point. + This method is called before the pull up controller's view move to a point. The default implementation of this method does nothing. - parameter point: The target point, expressed in the pull up controller coordinate system */ open func pullUpControllerWillMove(to point: CGFloat) { } /** - This method is called after the pull up controller's view move to a sticky point. + This method is called after the pull up controller's view move to a point. The default implementation of this method does nothing. - parameter point: The target point, expressed in the pull up controller coordinate system */ diff --git a/README.md b/README.md index e0925c3..9262f91 100644 --- a/README.md +++ b/README.md @@ -34,32 +34,44 @@ You can customize the controller behavior by overriding the followings propertie >A list of y values, in screen units expressed in the pull up controller coordinate system. >At the end of the gestures the pull up controller will scroll to the nearest point in the list. > ->Please keep in mind that this array should contains only sticky points in the middle of the pull up controller's view; ->There is therefore no need to add the fist one (`pullUpControllerPreviewOffset`), and/or the last one (`pullUpControllerPreferredSize.height`). -> >For a complete list of all the sticky points you can use `pullUpControllerAllStickyPoints` -`pullUpControllerIsBouncingEnabled: Bool` ->A Boolean value that determines whether bouncing occurs when scrolling reaches the end of the pull up controller's view size. ->The default value is `false`. +`pullUpControllerBounceOffset: CGFloat` +>A CGFloat value that determines how much the pull up controller's view can bounce outside it's size. +>The default value is 0 and that means the the view cannot expand beyond its size. It's possible to change the view controller's view position programmatically by using the method -`pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, completion: (() -> Void)?)` +`pullUpControllerMoveToVisiblePoint(_ visiblePoint: CGFloat, animated: Bool, completion: (() -> Void)?)` >This method will move the pull up controller's view in order to show the provided visible point. > >You may use on of `pullUpControllerAllStickyPoints` item to provide a valid visible point. >- `visiblePoint`: the y value to make visible, in screen units expressed in the pull up controller coordinate system. ->- `completion`: The closure to execute after the animation is completed. This block has no return value and takes no parameters. You may specify nil for this parameter. +>- `animated`: a true value will move the view with an animation. +>- `completion`: the closure to execute after the animation is completed. This block has no return value and takes no parameters. You may specify nil for this parameter. By overriding the following method it is possible to customize all the animations performed by the controller's view. - -`pullUpControllerAnimate(withDuration duration: TimeInterval, animations: @escaping () -> Void, completion: ((Bool) -> Void)?)` - -To observe the PullUpController's view state there're some usefull callbacks such as: -- `willMoveToStickyPoint: ((_ point: CGFloat) -> Void)?` -- `didMoveToStickyPoint: ((_ point: CGFloat) -> Void)?` -- `onDrag: ((_ point: CGFloat) -> Void)?` +` pullUpControllerAnimate(action: Action, + withDuration duration: TimeInterval, + animations: @escaping () -> Void, + completion: ((Bool) -> Void)?)` + +>You can consider override this method and customize the animation using the method +>`UIView.animate(withDuration:, delay:, usingSpringWithDamping:, initialSpringVelocity:, options:, animations:, completion:)` +>- `parameter`: The action that is about to be performed (.add, .remove or .move) +>- `duration`: The total duration of the animations, measured in seconds. If you specify a negative value or 0, the changes are made without animating them. +>-`animations`: A block object containing the changes to commit to the views. +>`completion`: A block object to be executed when the animation sequence ends. + +It is possible to observe the PullUpController's view state by overriding those methods: +`pullUpControllerWillMove(to point: CGFloat)` +>This method is called before the pull up controller's view move to a sticky point. + +`pullUpControllerDidMove(to point: CGFloat)` +>This method is called after the pull up controller's view move to a point. + +`pullUpControllerDidDrag(to point: CGFloat)` +>This method is called after the pull up controller's view is dragged to a point. PullUpController is easy draggable even if your `PullUpController`'s view contains a `UIScrollView`, just attach it to the controller itself with the following method: `<#T##UIScrollView#>.attach(to: <#T##PullUpController#>)` From 959672454f8ed38b03d36a17dd994602a71a01db Mon Sep 17 00:00:00 2001 From: Avihu Turzion Date: Tue, 2 Apr 2019 14:51:45 +0300 Subject: [PATCH 53/73] When attaching a scroll view it will now connect it to the PullUpController's pan gesture recognizer. --- PullUpController.podspec | 2 +- PullUpController/PullUpController.swift | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index 4fec38b..cb7cf89 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.6.0' + s.version = '0.6.1' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 18a195a..0473017 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -244,8 +244,12 @@ open class PullUpController: UIViewController { customTopOffset: superview.frame.height - initialStickyPointOffset) } - private func setupPanGestureRecognizer() { + fileprivate func setupPanGenstureRecognizerForInternalScrollView() { internalScrollView?.panGestureRecognizer.addTarget(self, action: #selector(handleScrollViewGestureRecognizer(_:))) + } + + private func setupPanGestureRecognizer() { + setupPanGenstureRecognizerForInternalScrollView() panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestureRecognizer(_:))) panGestureRecognizer?.minimumNumberOfTouches = 1 panGestureRecognizer?.maximumNumberOfTouches = 1 @@ -513,6 +517,7 @@ extension UIScrollView { */ open func attach(to pullUpController: PullUpController) { pullUpController.internalScrollView = self + pullUpController.setupPanGenstureRecognizerForInternalScrollView() } /** From f88c1464d65932ea0df0b51d698b0b5b4d8c1045 Mon Sep 17 00:00:00 2001 From: Avihu Turzion Date: Tue, 2 Apr 2019 16:22:49 +0300 Subject: [PATCH 54/73] Removed podspec update and made the current scroll view to detach before attaching a new one. --- PullUpController.podspec | 2 +- PullUpController/PullUpController.swift | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index cb7cf89..4fec38b 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.6.1' + s.version = '0.6.0' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 0473017..3c473f9 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -516,6 +516,7 @@ extension UIScrollView { - parameter pullUpController: the pull up controller to move with the current scroll view content. */ open func attach(to pullUpController: PullUpController) { + pullUpController.internalScrollView?.detach(from: pullUpController) pullUpController.internalScrollView = self pullUpController.setupPanGenstureRecognizerForInternalScrollView() } From 7a15b88bbb72a3fd2474b28bf3b70c4ca5aa4144 Mon Sep 17 00:00:00 2001 From: Avihu Turzion Date: Tue, 2 Apr 2019 16:57:10 +0300 Subject: [PATCH 55/73] When a scroll view is detached from a PullUpController, handling its gesture recognizer's interaction will also be removed. --- PullUpController/PullUpController.swift | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 3c473f9..ed87fbf 100644 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -244,12 +244,16 @@ open class PullUpController: UIViewController { customTopOffset: superview.frame.height - initialStickyPointOffset) } - fileprivate func setupPanGenstureRecognizerForInternalScrollView() { + fileprivate func setupPanGenstureRecognizerOfInternalScrollView() { internalScrollView?.panGestureRecognizer.addTarget(self, action: #selector(handleScrollViewGestureRecognizer(_:))) } + fileprivate func removePanGestureRecognizerOfInternalScrollView() { + internalScrollView?.panGestureRecognizer.removeTarget(self, action: #selector(handleScrollViewGestureRecognizer(_:))) + } + private func setupPanGestureRecognizer() { - setupPanGenstureRecognizerForInternalScrollView() + setupPanGenstureRecognizerOfInternalScrollView() panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestureRecognizer(_:))) panGestureRecognizer?.minimumNumberOfTouches = 1 panGestureRecognizer?.maximumNumberOfTouches = 1 @@ -518,7 +522,7 @@ extension UIScrollView { open func attach(to pullUpController: PullUpController) { pullUpController.internalScrollView?.detach(from: pullUpController) pullUpController.internalScrollView = self - pullUpController.setupPanGenstureRecognizerForInternalScrollView() + pullUpController.setupPanGenstureRecognizerOfInternalScrollView() } /** @@ -526,6 +530,7 @@ extension UIScrollView { - parameter pullUpController: the pull up controller to be removed from controlling the scroll view. */ open func detach(from pullUpController: PullUpController) { + pullUpController.removePanGestureRecognizerOfInternalScrollView() pullUpController.internalScrollView = nil } From 0fc601be8f3ed8dbad7cc183b38d21db5773b363 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 3 Apr 2019 18:17:01 +0200 Subject: [PATCH 56/73] Clean up code --- PullUpController/PullUpController.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) mode change 100644 => 100755 PullUpController/PullUpController.swift diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift old mode 100644 new mode 100755 index ed87fbf..e3e2d15 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -244,16 +244,16 @@ open class PullUpController: UIViewController { customTopOffset: superview.frame.height - initialStickyPointOffset) } - fileprivate func setupPanGenstureRecognizerOfInternalScrollView() { + fileprivate func addInternalScrollViewPanGesture() { internalScrollView?.panGestureRecognizer.addTarget(self, action: #selector(handleScrollViewGestureRecognizer(_:))) } - fileprivate func removePanGestureRecognizerOfInternalScrollView() { + fileprivate func removeInternalScrollViewPanGestureRecognizer() { internalScrollView?.panGestureRecognizer.removeTarget(self, action: #selector(handleScrollViewGestureRecognizer(_:))) } private func setupPanGestureRecognizer() { - setupPanGenstureRecognizerOfInternalScrollView() + addInternalScrollViewPanGesture() panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handlePanGestureRecognizer(_:))) panGestureRecognizer?.minimumNumberOfTouches = 1 panGestureRecognizer?.maximumNumberOfTouches = 1 @@ -522,7 +522,7 @@ extension UIScrollView { open func attach(to pullUpController: PullUpController) { pullUpController.internalScrollView?.detach(from: pullUpController) pullUpController.internalScrollView = self - pullUpController.setupPanGenstureRecognizerOfInternalScrollView() + pullUpController.addInternalScrollViewPanGesture() } /** @@ -530,7 +530,7 @@ extension UIScrollView { - parameter pullUpController: the pull up controller to be removed from controlling the scroll view. */ open func detach(from pullUpController: PullUpController) { - pullUpController.removePanGestureRecognizerOfInternalScrollView() + pullUpController.removeInternalScrollViewPanGestureRecognizer() pullUpController.internalScrollView = nil } From ba1008610e3c08bfe67abada9c27503e7beadc1a Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 3 Apr 2019 18:26:25 +0200 Subject: [PATCH 57/73] Migrate to Xcode 10.2 and Swift 5 --- Example/Pods/Pods.xcodeproj/project.pbxproj | 16 ++++++++++++---- .../PullUpController.xcodeproj/project.pbxproj | 14 +++++++------- .../xcschemes/PullUpController-Example.xcscheme | 2 +- Example/PullUpController/AppDelegate.swift | 2 +- .../PullUpController/UI/MapViewController.swift | 6 +++--- PullUpController/PullUpController.swift | 2 +- 6 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index fb2c3b7..0806211 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -242,14 +242,20 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0930; - LastUpgradeCheck = 0930; + LastUpgradeCheck = 1020; + TargetAttributes = { + 88A21A82856B75E85E451F68BE9B66F7 = { + LastSwiftMigration = 1020; + }; + }; }; buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 7DB346D0F39D3F0E887471402A8071AB; productRefGroup = B9052FE89FBCC9091AC04DA17B7D5702 /* Products */; @@ -352,7 +358,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -385,7 +391,7 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 4.2; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -396,6 +402,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -459,6 +466,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; diff --git a/Example/PullUpController.xcodeproj/project.pbxproj b/Example/PullUpController.xcodeproj/project.pbxproj index 6b82650..96db8a5 100644 --- a/Example/PullUpController.xcodeproj/project.pbxproj +++ b/Example/PullUpController.xcodeproj/project.pbxproj @@ -160,19 +160,19 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0830; - LastUpgradeCheck = 0940; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = CocoaPods; TargetAttributes = { 607FACCF1AFB9204008FA782 = { CreatedOnToolsVersion = 6.3.1; DevelopmentTeam = X9253HG4XT; - LastSwiftMigration = 0900; + LastSwiftMigration = 1020; }; }; }; buildConfigurationList = 607FACCB1AFB9204008FA782 /* Build configuration list for PBXProject "PullUpController" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -259,6 +259,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -314,6 +315,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -369,8 +371,7 @@ MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.test; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -385,8 +386,7 @@ MODULE_NAME = ExampleApp; PRODUCT_BUNDLE_IDENTIFIER = com.marioiannotta.test; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_SWIFT3_OBJC_INFERENCE = Default; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme b/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme index 463c029..5090c88 100644 --- a/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme +++ b/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme @@ -1,6 +1,6 @@ Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } diff --git a/Example/PullUpController/UI/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift index ca1b259..ec74ee3 100644 --- a/Example/PullUpController/UI/MapViewController.swift +++ b/Example/PullUpController/UI/MapViewController.swift @@ -23,7 +23,7 @@ class MapViewController: UIViewController { private var originalPullUpControllerViewSize: CGSize = .zero private func makeSearchViewControllerIfNeeded() -> SearchViewController { - let currentPullUpController = childViewControllers + let currentPullUpController = children .filter({ $0 is SearchViewController }) .first as? SearchViewController let pullUpController: SearchViewController = currentPullUpController ?? UIStoryboard(name: "Main",bundle: nil).instantiateViewController(withIdentifier: "SearchViewController") as! SearchViewController @@ -53,14 +53,14 @@ class MapViewController: UIViewController { func zoom(to location: CLLocationCoordinate2D) { let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05) - let region = MKCoordinateRegionMake(location, span) + let region = MKCoordinateRegion(center: location, span: span) mapView.setRegion(region, animated: true) } @IBAction private func addButtonTapped() { guard - childViewControllers.filter({ $0 is SearchViewController }).count == 0 + children.filter({ $0 is SearchViewController }).count == 0 else { return } addPullUpController() } diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index e3e2d15..4a7ef39 100755 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -116,7 +116,7 @@ open class PullUpController: UIViewController { let stickyPointTreshold = (self.parent?.view.frame.height ?? 0) - (topConstraint?.constant ?? 0) let stickyPointsLessCurrentPosition = pullUpControllerAllStickyPoints.map { abs($0 - stickyPointTreshold) } guard let minStickyPointDifference = stickyPointsLessCurrentPosition.min() else { return 0 } - return stickyPointsLessCurrentPosition.index(of: minStickyPointDifference) ?? 0 + return stickyPointsLessCurrentPosition.firstIndex(of: minStickyPointDifference) ?? 0 } // MARK: - Open methods From dfb0534fc6b71caf27206a009fa49763d8cb24e1 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 3 Apr 2019 18:27:02 +0200 Subject: [PATCH 58/73] Bump pod version --- PullUpController.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index 4fec38b..a82f84d 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.6.0' + s.version = '0.7.0' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } @@ -8,5 +8,5 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/MarioIannotta/PullUpController.git', :tag => s.version.to_s } s.ios.deployment_target = '9.0' s.source_files = 'PullUpController/**/*.swift' - s.pod_target_xcconfig = { 'SWIFT_VERSION' => '4.2' } + s.pod_target_xcconfig = { 'SWIFT_VERSION' => '5' } end From b6ebe8f78084892fd1573a93e576415d95237a90 Mon Sep 17 00:00:00 2001 From: Sergey Maslov Date: Wed, 12 Jun 2019 14:58:29 +0400 Subject: [PATCH 59/73] Fix Hide/Close without animation. Also add Switch controls to show how it's working. --- Example/PullUpController/UI/Main.storyboard | 38 ++++++++++++++-- .../UI/MapViewController.swift | 31 +++++++------ PullUpController/PullUpController.swift | 45 ++++++++++++------- 3 files changed, 79 insertions(+), 35 deletions(-) diff --git a/Example/PullUpController/UI/Main.storyboard b/Example/PullUpController/UI/Main.storyboard index bdb5226..7428e03 100644 --- a/Example/PullUpController/UI/Main.storyboard +++ b/Example/PullUpController/UI/Main.storyboard @@ -1,11 +1,11 @@ - + - + @@ -22,10 +22,10 @@ - + - + @@ -62,6 +62,34 @@ + + + + + + + + + + + + + + + + + + @@ -114,6 +142,8 @@ + + diff --git a/Example/PullUpController/UI/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift index ec74ee3..8e8d82d 100644 --- a/Example/PullUpController/UI/MapViewController.swift +++ b/Example/PullUpController/UI/MapViewController.swift @@ -19,8 +19,10 @@ class MapViewController: UIViewController { } @IBOutlet private weak var widthSlider: UISlider! @IBOutlet private weak var initialStateSegmentedControl: UISegmentedControl! - + private var originalPullUpControllerViewSize: CGSize = .zero + @IBOutlet weak var animateShowSwitch: UISwitch! + @IBOutlet weak var animateHideSwitch: UISwitch! private func makeSearchViewControllerIfNeeded() -> SearchViewController { let currentPullUpController = children @@ -35,41 +37,42 @@ class MapViewController: UIViewController { if originalPullUpControllerViewSize == .zero { originalPullUpControllerViewSize = pullUpController.view.bounds.size } + return pullUpController } - + var animated = false override func viewDidLoad() { super.viewDidLoad() - addPullUpController() + addPullUpController(animated: animated) } - - private func addPullUpController() { + + private func addPullUpController(animated: Bool) { let pullUpController = makeSearchViewControllerIfNeeded() _ = pullUpController.view // call pullUpController.viewDidLoad() addPullUpController(pullUpController, initialStickyPointOffset: pullUpController.initialPointOffset, - animated: true) + animated: animated) } - + func zoom(to location: CLLocationCoordinate2D) { let span = MKCoordinateSpan(latitudeDelta: 0.05, longitudeDelta: 0.05) let region = MKCoordinateRegion(center: location, span: span) - + mapView.setRegion(region, animated: true) } - + @IBAction private func addButtonTapped() { guard children.filter({ $0 is SearchViewController }).count == 0 else { return } - addPullUpController() + addPullUpController(animated: animateShowSwitch.isOn) } - + @IBAction private func removeButtonTapped() { let pullUpController = makeSearchViewControllerIfNeeded() - removePullUpController(pullUpController, animated: true) + removePullUpController(pullUpController, animated: animateHideSwitch.isOn) } - + @IBAction private func widthSliderValueChanged(_ sender: UISlider) { let pullUpController = makeSearchViewControllerIfNeeded() let width = originalPullUpControllerViewSize.width * CGFloat(sender.value) @@ -80,6 +83,6 @@ class MapViewController: UIViewController { height: pullUpController.landscapeFrame.height)) pullUpController.updatePreferredFrameIfNeeded(animated: true) } - + } diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 4a7ef39..0238909 100755 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -482,13 +482,17 @@ extension UIViewController { assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") addChild(pullUpController) pullUpController.setup(superview: view, initialStickyPointOffset: initialStickyPointOffset) - pullUpController.pullUpControllerAnimate( - action: .add, - withDuration: animated ? 0.3 : 0, - animations: { [weak self] in - self?.view.layoutIfNeeded() - }, - completion: nil) + if animated { + pullUpController.pullUpControllerAnimate( + action: .add, + withDuration: 0.3, + animations: { [weak self] in + self?.view.layoutIfNeeded() + }, + completion: nil) + } else { + view.layoutIfNeeded() + } } /** @@ -498,17 +502,24 @@ extension UIViewController { */ open func removePullUpController(_ pullUpController: PullUpController, animated: Bool) { pullUpController.hide() - pullUpController.pullUpControllerAnimate( - action: .remove, - withDuration: animated ? 0.3 : 0, - animations: { [weak self] in - self?.view.layoutIfNeeded() - }, - completion: { _ in - pullUpController.willMove(toParent: nil) - pullUpController.view.removeFromSuperview() - pullUpController.removeFromParent() + if animated { + pullUpController.pullUpControllerAnimate( + action: .remove, + withDuration: 0.3, + animations: { [weak self] in + self?.view.layoutIfNeeded() + }, + completion: { _ in + pullUpController.willMove(toParent: nil) + pullUpController.view.removeFromSuperview() + pullUpController.removeFromParent() }) + } else { + view.layoutIfNeeded() + pullUpController.willMove(toParent: nil) + pullUpController.view.removeFromSuperview() + pullUpController.removeFromParent() + } } } From cd29504439b54a45c3bfae2d0602aab611d72423 Mon Sep 17 00:00:00 2001 From: Sergey Maslov Date: Wed, 12 Jun 2019 14:59:49 +0400 Subject: [PATCH 60/73] Remove redundant code --- Example/PullUpController/UI/MapViewController.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Example/PullUpController/UI/MapViewController.swift b/Example/PullUpController/UI/MapViewController.swift index 8e8d82d..88f7136 100644 --- a/Example/PullUpController/UI/MapViewController.swift +++ b/Example/PullUpController/UI/MapViewController.swift @@ -40,10 +40,10 @@ class MapViewController: UIViewController { return pullUpController } - var animated = false + override func viewDidLoad() { super.viewDidLoad() - addPullUpController(animated: animated) + addPullUpController(animated: animateShowSwitch.isOn) } private func addPullUpController(animated: Bool) { From 3df970f324e98185108f799f01e12ed881af6b82 Mon Sep 17 00:00:00 2001 From: kangas08 Date: Sun, 5 Jan 2020 21:42:36 +1030 Subject: [PATCH 61/73] Update PullUpController.podspec --- PullUpController.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index a82f84d..ffab770 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -8,5 +8,5 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/MarioIannotta/PullUpController.git', :tag => s.version.to_s } s.ios.deployment_target = '9.0' s.source_files = 'PullUpController/**/*.swift' - s.pod_target_xcconfig = { 'SWIFT_VERSION' => '5' } + s.swift_version = '5' end From 1b7f6129f06ec804ee396d7f09541e395f1f0dd1 Mon Sep 17 00:00:00 2001 From: Ryan Meisters Date: Mon, 10 Feb 2020 15:15:14 -0800 Subject: [PATCH 62/73] Expose show/hide completion handlers --- PullUpController/PullUpController.swift | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 0238909..5ed348b 100755 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -478,7 +478,8 @@ extension UIViewController { */ open func addPullUpController(_ pullUpController: PullUpController, initialStickyPointOffset: CGFloat, - animated: Bool) { + animated: Bool, + completion: ((Bool) -> Void)? = nil) { assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") addChild(pullUpController) pullUpController.setup(superview: view, initialStickyPointOffset: initialStickyPointOffset) @@ -489,7 +490,7 @@ extension UIViewController { animations: { [weak self] in self?.view.layoutIfNeeded() }, - completion: nil) + completion: completion) } else { view.layoutIfNeeded() } @@ -500,7 +501,9 @@ extension UIViewController { - parameter pullUpController: the pull up controller to remove as a child from the current view controller. - parameter animated: Pass true to animate the removing; otherwise, pass false. */ - open func removePullUpController(_ pullUpController: PullUpController, animated: Bool) { + open func removePullUpController(_ pullUpController: PullUpController, + animated: Bool, + completion: ((Bool) -> Void)? = nil) { pullUpController.hide() if animated { pullUpController.pullUpControllerAnimate( @@ -509,16 +512,18 @@ extension UIViewController { animations: { [weak self] in self?.view.layoutIfNeeded() }, - completion: { _ in + completion: { didComplete in pullUpController.willMove(toParent: nil) pullUpController.view.removeFromSuperview() pullUpController.removeFromParent() + completion?(didComplete) }) } else { view.layoutIfNeeded() pullUpController.willMove(toParent: nil) pullUpController.view.removeFromSuperview() pullUpController.removeFromParent() + completion?(didComplete) } } From 94b4ad45c7b565766b8b4a6e86dec535c0d23ac6 Mon Sep 17 00:00:00 2001 From: Ryan Meisters Date: Wed, 12 Feb 2020 10:13:46 -0800 Subject: [PATCH 63/73] Added completion param to doc comments --- PullUpController/PullUpController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 5ed348b..6bfeac4 100755 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -475,6 +475,7 @@ extension UIViewController { - parameter pullUpController: the pull up controller to add as a child of the current view controller. - parameter initialStickyPointOffset: The point where the provided `pullUpController`'s view will be initially placed expressed in screen units of the pull up controller coordinate system. If this value is not provided, the `pullUpController`'s view will be initially placed expressed - parameter animated: Pass true to animate the adding; otherwise, pass false. + - parameter completion: Optional completion handler to be called after the PullUpController is added. */ open func addPullUpController(_ pullUpController: PullUpController, initialStickyPointOffset: CGFloat, @@ -500,6 +501,7 @@ extension UIViewController { Adds the specified pull up view controller as a child of the current view controller. - parameter pullUpController: the pull up controller to remove as a child from the current view controller. - parameter animated: Pass true to animate the removing; otherwise, pass false. + - parameter completion: Optional completion handler to be called after the PullUpController is removed. */ open func removePullUpController(_ pullUpController: PullUpController, animated: Bool, From 48d23912f67afdff368385f1d3132f7a907f4985 Mon Sep 17 00:00:00 2001 From: Ryan Meisters Date: Sun, 23 Feb 2020 09:57:23 -0800 Subject: [PATCH 64/73] Fixes completion callbacks Yikes, my last PR broke master. Sorry! This fixes, and also adds missing completion handler call when adding a PullUpController without animation --- PullUpController/PullUpController.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 6bfeac4..449cdd5 100755 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -494,6 +494,7 @@ extension UIViewController { completion: completion) } else { view.layoutIfNeeded() + completion?(true) } } @@ -525,7 +526,7 @@ extension UIViewController { pullUpController.willMove(toParent: nil) pullUpController.view.removeFromSuperview() pullUpController.removeFromParent() - completion?(didComplete) + completion?(true) } } From e1df156369ab276fc91b22dc77d32b9cf1baa14b Mon Sep 17 00:00:00 2001 From: Ryan Meisters Date: Sun, 23 Feb 2020 10:09:39 -0800 Subject: [PATCH 65/73] Add missing `didMove(toParent: ..)` call When adding a child view controller, the container view controller implementation is required to call `didMove(toParent:..)` after the child's view is added to the view hierarchy. Docs [here](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621405-didmove) > If you are implementing your own container view controller, it must call the didMove(toParent:) method of the child view controller after the transition to the new controller is complete or, if there is no transition, immediately after calling the addChild(_:) method. --- PullUpController/PullUpController.swift | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 449cdd5..44241e3 100755 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -491,9 +491,14 @@ extension UIViewController { animations: { [weak self] in self?.view.layoutIfNeeded() }, - completion: completion) + completion: { didComplete in + pullUpController.didMove(toParent: self) + completion?(didComplete) + } + ) } else { view.layoutIfNeeded() + pullUpController.didMove(toParent: self) completion?(true) } } From 22701699d01a7b2ee57a3b16bc4ddfe693bf378f Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Mon, 24 Feb 2020 09:19:01 +0100 Subject: [PATCH 66/73] Improve layout for devices with safe area --- .gitignore | 1 + .../project.pbxproj | 12 ++++++ .../Extensions/UIViewController+.swift | 22 ++++++++++ Example/PullUpController/UI/Main.storyboard | 40 +++++++++---------- .../UI/SearchViewController.swift | 8 +++- 5 files changed, 60 insertions(+), 23 deletions(-) create mode 100644 Example/PullUpController/Extensions/UIViewController+.swift diff --git a/.gitignore b/.gitignore index d534044..a4b4a49 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,4 @@ fastlane/report.xml fastlane/Preview.html fastlane/screenshots fastlane/test_output +.DS_Store diff --git a/Example/PullUpController.xcodeproj/project.pbxproj b/Example/PullUpController.xcodeproj/project.pbxproj index 96db8a5..3951a4c 100644 --- a/Example/PullUpController.xcodeproj/project.pbxproj +++ b/Example/PullUpController.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ AC44912520DBFFBE00F98838 /* SearchResultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC44911E20DBFFBE00F98838 /* SearchResultCell.swift */; }; AC44912620DBFFBE00F98838 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AC44911F20DBFFBE00F98838 /* Main.storyboard */; }; AC44912720DBFFBE00F98838 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = AC44912020DBFFBE00F98838 /* Assets.xcassets */; }; + ACA1B1C52403BBB600B6A7B6 /* UIViewController+.swift in Sources */ = {isa = PBXBuildFile; fileRef = ACA1B1C42403BBB600B6A7B6 /* UIViewController+.swift */; }; E969182522AF18CFABF54185 /* Pods_PullUpController_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFA23D4840D57C4607249C0D /* Pods_PullUpController_Example.framework */; }; /* End PBXBuildFile section */ @@ -33,6 +34,7 @@ AC44911E20DBFFBE00F98838 /* SearchResultCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SearchResultCell.swift; sourceTree = ""; }; AC44911F20DBFFBE00F98838 /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; AC44912020DBFFBE00F98838 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + ACA1B1C42403BBB600B6A7B6 /* UIViewController+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+.swift"; sourceTree = ""; }; BFA23D4840D57C4607249C0D /* Pods_PullUpController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_PullUpController_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; F59F16287664980C2DF5643A /* Pods-PullUpController_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PullUpController_Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-PullUpController_Tests/Pods-PullUpController_Tests.release.xcconfig"; sourceTree = ""; }; F97967A110801D095B7F4727 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; @@ -74,6 +76,7 @@ children = ( 607FACD51AFB9204008FA782 /* AppDelegate.swift */, AC44912020DBFFBE00F98838 /* Assets.xcassets */, + ACA1B1C32403BBAD00B6A7B6 /* Extensions */, AC44911820DBFFBE00F98838 /* Supporting files */, AC44911B20DBFFBE00F98838 /* UI */, ); @@ -131,6 +134,14 @@ path = UI; sourceTree = ""; }; + ACA1B1C32403BBAD00B6A7B6 /* Extensions */ = { + isa = PBXGroup; + children = ( + ACA1B1C42403BBB600B6A7B6 /* UIViewController+.swift */, + ); + path = Extensions; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -247,6 +258,7 @@ files = ( AC44912320DBFFBE00F98838 /* SearchViewController.swift in Sources */, AC44912420DBFFBE00F98838 /* MapViewController.swift in Sources */, + ACA1B1C52403BBB600B6A7B6 /* UIViewController+.swift in Sources */, AC44912520DBFFBE00F98838 /* SearchResultCell.swift in Sources */, 607FACD61AFB9204008FA782 /* AppDelegate.swift in Sources */, ); diff --git a/Example/PullUpController/Extensions/UIViewController+.swift b/Example/PullUpController/Extensions/UIViewController+.swift new file mode 100644 index 0000000..7662f09 --- /dev/null +++ b/Example/PullUpController/Extensions/UIViewController+.swift @@ -0,0 +1,22 @@ +// +// UIViewController+.swift +// PullUpController_Example +// +// Created by Mario on 24/02/2020. +// Copyright © 2020 CocoaPods. All rights reserved. +// + +import UIKit + +extension UIViewController { + + var hasSafeArea: Bool { + guard + #available(iOS 11.0, tvOS 11.0, *) + else { + return false + } + return UIApplication.shared.delegate?.window??.safeAreaInsets.top ?? 0 > 20 + } + +} diff --git a/Example/PullUpController/UI/Main.storyboard b/Example/PullUpController/UI/Main.storyboard index 7428e03..4cbefb0 100644 --- a/Example/PullUpController/UI/Main.storyboard +++ b/Example/PullUpController/UI/Main.storyboard @@ -1,11 +1,9 @@ - - - - + + - + @@ -22,13 +20,13 @@ - + - + - + - + @@ -45,7 +43,7 @@ - + - + @@ -63,30 +61,30 @@ - + - + - + - + @@ -224,11 +222,11 @@ - + - + @@ -301,7 +299,7 @@ - + diff --git a/Example/PullUpController/UI/SearchViewController.swift b/Example/PullUpController/UI/SearchViewController.swift index 46b4d08..24ad4ad 100644 --- a/Example/PullUpController/UI/SearchViewController.swift +++ b/Example/PullUpController/UI/SearchViewController.swift @@ -35,7 +35,7 @@ class SearchViewController: PullUpController { var initialPointOffset: CGFloat { switch initialState { case .contracted: - return searchBoxContainerView?.frame.height ?? 0 + return (searchBoxContainerView?.frame.height ?? 0) + safeAreaAdditionalOffset case .expanded: return pullUpControllerPreferredSize.height } @@ -45,6 +45,10 @@ class SearchViewController: PullUpController { public var portraitSize: CGSize = .zero public var landscapeFrame: CGRect = .zero + + private var safeAreaAdditionalOffset: CGFloat { + hasSafeArea ? 20 : 0 + } // MARK: - Lifecycle @@ -113,7 +117,7 @@ class SearchViewController: PullUpController { case .contracted: return [firstPreviewView.frame.maxY] case .expanded: - return [searchBoxContainerView.frame.maxY, firstPreviewView.frame.maxY] + return [searchBoxContainerView.frame.maxY + safeAreaAdditionalOffset, firstPreviewView.frame.maxY] } } From bb51df355ff67d4a91f6cb56a0955425ed994fa7 Mon Sep 17 00:00:00 2001 From: Artyom Rudakov Date: Wed, 4 Mar 2020 13:35:12 +0200 Subject: [PATCH 67/73] Adds Package.swift --- Package.swift | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 Package.swift diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..1d6591c --- /dev/null +++ b/Package.swift @@ -0,0 +1,20 @@ +// swift-tools-version:5.0 + +import PackageDescription + +let package = Package( + name: "PullUpController", + platforms: [.iOS(.v9)], + products: [ + .library( + name: "PullUpController", + targets: ["PullUpController"] + ) + ], + targets: [ + .target( + name: "PullUpController", + path: "PullUpController" + ) + ] +) From 58c7a10ddd4f16a3e04cba6883aabe7686888654 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 4 Mar 2020 20:56:00 +0100 Subject: [PATCH 68/73] Bump pod version --- PullUpController.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullUpController.podspec b/PullUpController.podspec index ffab770..1857235 100644 --- a/PullUpController.podspec +++ b/PullUpController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'PullUpController' - s.version = '0.7.0' + s.version = '0.8.0' s.summary = 'Pull up controller with multiple sticky points like in iOS Maps.' s.homepage = 'https://github.com/MarioIannotta/PullUpController' s.license = { :type => 'MIT', :file => 'LICENSE' } From 1d7894e1c1b4ccc963285c8482441e6bb4a02907 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 4 Mar 2020 20:56:06 +0100 Subject: [PATCH 69/73] Fix swift version --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9262f91..617aa06 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ Create your own pull up controller with multiple sticky points like in iOS Maps [![Platform](http://img.shields.io/badge/platform-ios-red.svg?style=flat )](https://developer.apple.com/iphone/index.action) -[![Swift 4](https://img.shields.io/badge/Swift-4-orange.svg?style=flat)](https://developer.apple.com/swift/) +[![Swift 5](https://img.shields.io/badge/Swift-5-orange.svg?style=flat)](https://developer.apple.com/swift/) [![Cocoapods Compatible](https://img.shields.io/cocoapods/v/PullUpController.svg)](https://img.shields.io/cocoapods/v/PullUpController.svg) [![Maintainability](https://api.codeclimate.com/v1/badges/ab0e3ab724774c9b5974/maintainability)](https://codeclimate.com/github/MarioIannotta/PullUpController/maintainability) From c51756446aab87e60a89b681771af028ee71fa48 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 4 Mar 2020 20:56:20 +0100 Subject: [PATCH 70/73] Update project file --- Example/Pods/Pods.xcodeproj/project.pbxproj | 2 +- .../PullUpController-Example.xcscheme | 24 ++++++++----------- .../xcshareddata/WorkspaceSettings.xcsettings | 2 +- 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 0806211..9bc9b90 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -242,7 +242,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0930; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1130; TargetAttributes = { 88A21A82856B75E85E451F68BE9B66F7 = { LastSwiftMigration = 1020; diff --git a/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme b/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme index 5090c88..b8494d3 100644 --- a/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme +++ b/Example/PullUpController.xcodeproj/xcshareddata/xcschemes/PullUpController-Example.xcscheme @@ -1,6 +1,6 @@ + + + + @@ -53,17 +62,6 @@ - - - - - - - - BuildSystemType - Original + Latest From 1c9a6c82c87a95ecf25420776c7d65bc046199c0 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 4 Mar 2020 20:56:44 +0100 Subject: [PATCH 71/73] Update gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d534044..a4b4a49 100644 --- a/.gitignore +++ b/.gitignore @@ -65,3 +65,4 @@ fastlane/report.xml fastlane/Preview.html fastlane/screenshots fastlane/test_output +.DS_Store From 6192b4745a4423e8fd2dc0a4eb8d34ca247a5163 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Wed, 4 Mar 2020 21:01:06 +0100 Subject: [PATCH 72/73] Remove .swift-version file --- .swift-version | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .swift-version diff --git a/.swift-version b/.swift-version deleted file mode 100644 index bf77d54..0000000 --- a/.swift-version +++ /dev/null @@ -1 +0,0 @@ -4.2 From b82611ae2c635a9625c0539c3db6042a9990e9b9 Mon Sep 17 00:00:00 2001 From: Mario Iannotta Date: Tue, 8 Oct 2024 19:35:07 +0200 Subject: [PATCH 73/73] Print instead of assert --- PullUpController/PullUpController.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/PullUpController/PullUpController.swift b/PullUpController/PullUpController.swift index 44241e3..f23e06e 100755 --- a/PullUpController/PullUpController.swift +++ b/PullUpController/PullUpController.swift @@ -481,7 +481,9 @@ extension UIViewController { initialStickyPointOffset: CGFloat, animated: Bool, completion: ((Bool) -> Void)? = nil) { - assert(!(self is UITableViewController), "It's not possible to attach a PullUpController to a UITableViewController. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") + if (self is UITableViewController) { + print("⚠️ Attaching a `PullUpController` to a `UITableViewController` is discouraged. Check this issue for more information: https://github.com/MarioIannotta/PullUpController/issues/14") + } addChild(pullUpController) pullUpController.setup(superview: view, initialStickyPointOffset: initialStickyPointOffset) if animated {