From b847e09e40a833593b29475f2f1c94e8260befe2 Mon Sep 17 00:00:00 2001 From: Mikhail Maslo <52037202+mikhailmaslo@users.noreply.github.com> Date: Sat, 4 Feb 2023 00:08:37 +0100 Subject: [PATCH] Introduce Swiftformat (#14) * Introduce Swiftformat * Inline let * Run swift format --- .swiftformat | 133 ++++++++++++++++++ BottomSheetDemo.xcodeproj/project.pbxproj | 22 +++ .../xcshareddata/swiftpm/Package.resolved | 24 ++-- .../Helpers/UIControl+EventHandling.swift | 7 +- .../Screens/Resize/ResizeViewController.swift | 62 ++++---- .../Screens/Root/RootViewController.swift | 15 +- .../Supporting Files/AppDelegate.swift | 8 +- BuildTools/Empty.swift | 0 BuildTools/Package.resolved | 14 ++ BuildTools/Package.swift | 11 ++ Package.swift | 4 +- .../BottomSheetTransitioningDelegate.swift | 11 +- .../UIViewController+Convenience.swift | 2 +- .../BottomSheetNavigationController.swift | 17 +-- ...ntroller+CustomInteractiveTransition.swift | 2 +- .../BottomSheetPresentationController.swift | 41 +++--- .../Helpers/UI/CGRect+Helpers.swift | 6 +- .../Helpers/UI/CGSize+Helpers.swift | 4 +- .../UI/UIViewController+Lifecycle.swift | 32 ++--- 19 files changed, 295 insertions(+), 120 deletions(-) create mode 100644 .swiftformat create mode 100644 BuildTools/Empty.swift create mode 100644 BuildTools/Package.resolved create mode 100644 BuildTools/Package.swift diff --git a/.swiftformat b/.swiftformat new file mode 100644 index 0000000..983abc8 --- /dev/null +++ b/.swiftformat @@ -0,0 +1,133 @@ +# Tool options +--minversion 0.48.11 +--swiftversion 5.4 + +# Format options +--assetliterals visual-width +--beforemarks +# Uncomment if we decide to enable `organizeDeclarations` rule +#--categorymark "MARK: - %c" +--conflictmarkers reject +--exponentcase lowercase +--extensionmark "MARK: - %t + %c" +--fragment false +--funcattributes prev-line +--groupedextension "MARK: %c" +--guardelse auto +--header ignore +--hexgrouping none +--hexliteralcase lowercase +--ifdef no-indent +--importgrouping alpha +--indent 4 +--indentcase false +--lifecycle +--linebreaks lf +--markextensions always +--marktypes always +--maxwidth none +--modifierorder acl,setteracl,override,dynamic,mutators,lazy,final,class,static,required,convenience,typemethods,owned +--nevertrailing +--nospaceoperators ...,..< +--nowrapoperators +--octalgrouping none +--organizetypes actor,class,enum,struct +--patternlet inline +--ranges spaced # ??? +--redundanttype inferred +--self init-only +--selfrequired +--semicolons never +--smarttabs enabled +# Uncomment if we decide to enable `unusedArguments` rule +#--stripunusedargs closure-only +--structthreshold 0 +--tabwidth unspecified +--trailingclosures +--trimwhitespace always +--typeattributes prev-line +--typemark "MARK: - %t" +--varattributes prev-line +--voidtype void +--wraparguments before-first +--wrapcollections before-first +--wrapconditions before-first +--wrapparameters before-first +--wrapreturntype preserve +--xcodeindentation disabled + +# Rules +--rules andOperator +--rules anyObjectProtocol +--rules blankLinesAroundMark +--rules blankLinesAtEndOfScope +--rules blankLinesAtStartOfScope +--rules blankLinesBetweenScopes +--rules braces +--rules consecutiveBlankLines +--rules consecutiveSpaces +--rules duplicateImports +--rules elseOnSameLine +--rules emptyBraces +--disable enumNamespaces +--rules extensionAccessControl +--disable fileHeader +--rules hoistPatternLet +--rules indent +--rules initCoderUnavailable +--disable isEmpty +--rules leadingDelimiters +--rules linebreakAtEndOfFile +--rules linebreaks +--disable markTypes +--rules modifierOrder +--rules numberFormatting +--disable organizeDeclarations +--disable preferKeyPath +--rules redundantBackticks +--rules redundantBreak +--rules redundantExtensionACL +--rules redundantFileprivate +--rules redundantGet +--rules redundantInit +--rules redundantLet +--rules redundantLetError +--rules redundantNilInit +--rules redundantObjc +--rules redundantParens +--rules redundantPattern +--rules redundantRawValues +--rules redundantReturn +--rules redundantSelf +--rules redundantType +--rules redundantVoidReturnType +--rules semicolons +--rules sortedImports +--disable sortedSwitchCases +--rules spaceAroundBraces +--rules spaceAroundBrackets +--rules spaceAroundComments +--rules spaceAroundGenerics +--rules spaceAroundOperators +--rules spaceAroundParens +--rules spaceInsideBraces +--rules spaceInsideBrackets +--rules spaceInsideComments +--rules spaceInsideGenerics +--rules spaceInsideParens +--rules strongOutlets +--rules strongifiedSelf +--rules todos +--rules trailingClosures +--rules trailingCommas +--rules trailingSpace +--rules typeSugar +--disable unusedArguments +--rules void +--disable wrap +--rules wrapArguments +--rules wrapAttributes +--rules wrapEnumCases +--rules wrapMultilineStatementBraces +--disable wrapSwitchCases +--rules yodaConditions diff --git a/BottomSheetDemo.xcodeproj/project.pbxproj b/BottomSheetDemo.xcodeproj/project.pbxproj index e178868..3af0a93 100644 --- a/BottomSheetDemo.xcodeproj/project.pbxproj +++ b/BottomSheetDemo.xcodeproj/project.pbxproj @@ -393,6 +393,7 @@ isa = PBXNativeTarget; buildConfigurationList = 7D05F32E274139E100EBDBB1 /* Build configuration list for PBXNativeTarget "BottomSheet" */; buildPhases = ( + 7D1A478E298DC8C2004832D4 /* Swiftformat */, 7D05F326274139E100EBDBB1 /* Sources */, 7D05F327274139E100EBDBB1 /* Frameworks */, 7D05F328274139E100EBDBB1 /* CopyFiles */, @@ -488,6 +489,27 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 7D1A478E298DC8C2004832D4 /* Swiftformat */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = Swiftformat; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "cd BuildTools\nSDKROOT=(xcrun --sdk macosx --show-sdk-path)\nswift run -c release swiftformat \"$SRCROOT\"\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 7D05F2FD2741359800EBDBB1 /* Sources */ = { isa = PBXSourcesBuildPhase; diff --git a/BottomSheetDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/BottomSheetDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index e7ecf86..b7ee2e8 100644 --- a/BottomSheetDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/BottomSheetDemo.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,16 +1,14 @@ { - "object": { - "pins": [ - { - "package": "SnapKit", - "repositoryURL": "https://github.com/SnapKit/SnapKit", - "state": { - "branch": null, - "revision": "d458564516e5676af9c70b4f4b2a9178294f1bc6", - "version": "5.0.1" - } + "pins" : [ + { + "identity" : "snapkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/SnapKit/SnapKit", + "state" : { + "revision" : "d458564516e5676af9c70b4f4b2a9178294f1bc6", + "version" : "5.0.1" } - ] - }, - "version": 1 + } + ], + "version" : 2 } diff --git a/BottomSheetDemo/Sources/User Interface/Helpers/UIControl+EventHandling.swift b/BottomSheetDemo/Sources/User Interface/Helpers/UIControl+EventHandling.swift index d137dc4..43cff33 100644 --- a/BottomSheetDemo/Sources/User Interface/Helpers/UIControl+EventHandling.swift +++ b/BottomSheetDemo/Sources/User Interface/Helpers/UIControl+EventHandling.swift @@ -14,7 +14,6 @@ struct ButtonAction { let handler: () -> Void } - extension UIButton { private final class ButtonAdapter { private let handler: () -> Void @@ -24,14 +23,14 @@ extension UIButton { self.handler = handler self.controlEvent = controlEvent } - + @objc func handle() { handler() } } - static private var key: UInt8 = 0 + private static var key: UInt8 = 0 private var adapters: [ButtonAdapter] { get { @@ -49,7 +48,7 @@ extension UIButton { setTitle(buttonAction.title, for: .normal) addEventHandler(handler: buttonAction.handler, controlEvent: .touchUpInside) } - + func addEventHandler(handler: @escaping () -> Void, controlEvent: UIControl.Event) { let adapter = ButtonAdapter(handler: handler, controlEvent: controlEvent) addTarget(adapter, action: #selector(ButtonAdapter.handle), for: controlEvent) diff --git a/BottomSheetDemo/Sources/User Interface/Screens/Resize/ResizeViewController.swift b/BottomSheetDemo/Sources/User Interface/Screens/Resize/ResizeViewController.swift index e465435..1260ca2 100644 --- a/BottomSheetDemo/Sources/User Interface/Screens/Resize/ResizeViewController.swift +++ b/BottomSheetDemo/Sources/User Interface/Screens/Resize/ResizeViewController.swift @@ -6,42 +6,42 @@ // Copyright © 2021 Joom. All rights reserved. // -import UIKit import BottomSheet +import UIKit final class ResizeViewController: UIViewController { // MARK: - Subviews - + private let contentSizeLabel: UILabel = { let label = UILabel() label.textAlignment = .center return label }() - + var isShowNextButtonHidden: Bool { navigationController == nil } - + var isShowRootButtonHidden: Bool { navigationController?.viewControllers.count ?? 0 <= 1 } - + private let showNextButton: UIButton = { let button = UIButton() button.backgroundColor = .systemBlue button.setTitle("Show next", for: .normal) return button }() - + private let showRootButton: UIButton = { let button = UIButton() button.backgroundColor = .systemPink button.setTitle("Show root", for: .normal) return button }() - + private let _scrollView = UIScrollView() - + // MARK: - Private properties private lazy var actions = [ @@ -58,55 +58,56 @@ final class ResizeViewController: UIViewController { updateContentHeight(newValue: currentHeight - 100) }), ] - + private var currentHeight: CGFloat { didSet { updatePreferredContentSize() } } - + // MARK: - Init init(initialHeight: CGFloat) { - currentHeight = initialHeight + self.currentHeight = initialHeight super.init(nibName: nil, bundle: nil) } - + + @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + // MARK: - UIViewCoontroller - + override func viewDidLoad() { super.viewDidLoad() - + setupSubviews() updatePreferredContentSize() } - + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - + view.setNeedsLayout() } - + // MARK: - Setup - + private func setupSubviews() { view.backgroundColor = .white - + view.addSubview(_scrollView) _scrollView.snp.makeConstraints { $0.edges.equalToSuperview() } _scrollView.alwaysBounceVertical = true - + _scrollView.addSubview(contentSizeLabel) contentSizeLabel.snp.makeConstraints { $0.leading.top.trailing.equalToSuperview() } - + let buttons = actions.map(UIButton.init(buttonAction:)) let stackView = UIStackView(arrangedSubviews: buttons) stackView.distribution = .fillEqually @@ -119,7 +120,7 @@ final class ResizeViewController: UIViewController { $0.leading.trailing.equalToSuperview().inset(16) $0.height.equalTo(44) } - + if !isShowNextButtonHidden { _scrollView.addSubview(showNextButton) showNextButton.addTarget(self, action: #selector(handleShowNext), for: .touchUpInside) @@ -130,7 +131,7 @@ final class ResizeViewController: UIViewController { $0.height.equalTo(50) } } - + if !isShowRootButtonHidden { _scrollView.addSubview(showRootButton) showRootButton.addTarget(self, action: #selector(handleShowRoot), for: .touchUpInside) @@ -142,17 +143,17 @@ final class ResizeViewController: UIViewController { } } } - + // MARK: - Private methods - + private func updatePreferredContentSize() { _scrollView.contentSize = CGSize(width: UIScreen.main.bounds.width, height: currentHeight) contentSizeLabel.text = "preferredContentHeight = \(currentHeight)" preferredContentSize = _scrollView.contentSize } - + private func updateContentHeight(newValue: CGFloat) { - guard newValue >= 200 && newValue < 5000 else { return } + guard newValue >= 200, newValue < 5000 else { return } let updates = { [self] in currentHeight = newValue @@ -165,18 +166,17 @@ final class ResizeViewController: UIViewController { updates() } } - + @objc private func handleShowNext() { let viewController = ResizeViewController(initialHeight: currentHeight) navigationController?.pushViewController(viewController, animated: true) } - + @objc private func handleShowRoot() { navigationController?.popToRootViewController(animated: true) } - } // MARK: - ScrollableBottomSheetPresentedController diff --git a/BottomSheetDemo/Sources/User Interface/Screens/Root/RootViewController.swift b/BottomSheetDemo/Sources/User Interface/Screens/Root/RootViewController.swift index f000f8a..67317f2 100644 --- a/BottomSheetDemo/Sources/User Interface/Screens/Root/RootViewController.swift +++ b/BottomSheetDemo/Sources/User Interface/Screens/Root/RootViewController.swift @@ -6,9 +6,9 @@ // Copyright © 2021 Joom. All rights reserved. // -import UIKit -import SnapKit import BottomSheet +import SnapKit +import UIKit final class RootViewController: UIViewController { private let button: UIButton = { @@ -21,17 +21,18 @@ final class RootViewController: UIViewController { init() { super.init(nibName: nil, bundle: nil) } - + + @available(*, unavailable) required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } - + override func viewDidLoad() { super.viewDidLoad() - + setupSubviews() } - + private func setupSubviews() { if #available(iOS 13.0, *) { view.backgroundColor = .systemBackground @@ -47,7 +48,7 @@ final class RootViewController: UIViewController { $0.height.equalTo(44) } } - + @objc private func handleShowBottomSheet() { let viewController = ResizeViewController(initialHeight: 300) diff --git a/BottomSheetDemo/Supporting Files/AppDelegate.swift b/BottomSheetDemo/Supporting Files/AppDelegate.swift index 9dd71e5..5fcaf8c 100644 --- a/BottomSheetDemo/Supporting Files/AppDelegate.swift +++ b/BottomSheetDemo/Supporting Files/AppDelegate.swift @@ -6,8 +6,8 @@ // Copyright © 2021 Joom. All rights reserved. // -import UIKit import BottomSheet +import UIKit @main class AppDelegate: UIResponder, UIApplicationDelegate { @@ -19,16 +19,16 @@ class AppDelegate: UIResponder, UIApplicationDelegate { ) -> Bool { setupWindow() invokeLoad() - + return true } - + private func setupWindow() { window = UIWindow(frame: UIScreen.main.bounds) window?.rootViewController = RootViewController() window?.makeKeyAndVisible() } - + private func invokeLoad() { UIViewController.swiftLoad() } diff --git a/BuildTools/Empty.swift b/BuildTools/Empty.swift new file mode 100644 index 0000000..e69de29 diff --git a/BuildTools/Package.resolved b/BuildTools/Package.resolved new file mode 100644 index 0000000..06074d8 --- /dev/null +++ b/BuildTools/Package.resolved @@ -0,0 +1,14 @@ +{ + "pins" : [ + { + "identity" : "swiftformat", + "kind" : "remoteSourceControl", + "location" : "https://github.com/nicklockwood/SwiftFormat", + "state" : { + "revision" : "ae4d0b672cd7094ae513097c617951a5ac714418", + "version" : "0.50.8" + } + } + ], + "version" : 2 +} diff --git a/BuildTools/Package.swift b/BuildTools/Package.swift new file mode 100644 index 0000000..ba04d7d --- /dev/null +++ b/BuildTools/Package.swift @@ -0,0 +1,11 @@ +// swift-tools-version:5.7 +import PackageDescription + +let package = Package( + name: "BuildTools", + platforms: [.macOS(.v10_11)], + dependencies: [ + .package(url: "https://github.com/nicklockwood/SwiftFormat", from: "0.50.8"), + ], + targets: [.target(name: "BuildTools", path: "")] +) diff --git a/Package.swift b/Package.swift index 3f9d6ff..af4acdd 100644 --- a/Package.swift +++ b/Package.swift @@ -6,13 +6,13 @@ import PackageDescription let package = Package( name: "BottomSheet", platforms: [ - .iOS(.v12) + .iOS(.v12), ], products: [ .library( name: "BottomSheet", targets: ["BottomSheet"] - ) + ), ], targets: [ .target( diff --git a/Sources/BottomSheet/Core/BottomSheetTransitioningDelegate.swift b/Sources/BottomSheet/Core/BottomSheetTransitioningDelegate.swift index 725f9d3..0b88908 100644 --- a/Sources/BottomSheet/Core/BottomSheetTransitioningDelegate.swift +++ b/Sources/BottomSheet/Core/BottomSheetTransitioningDelegate.swift @@ -20,13 +20,13 @@ public final class BottomSheetTransitioningDelegate: NSObject, UIViewControllerT private weak var presentationController: BottomSheetPresentationController? private let presentationControllerFactory: BottomSheetPresentationControllerFactory - + // MARK: - Init public init(presentationControllerFactory: BottomSheetPresentationControllerFactory) { self.presentationControllerFactory = presentationControllerFactory } - + // MARK: - UIViewControllerTransitioningDelegate public func animationController( @@ -37,17 +37,14 @@ public final class BottomSheetTransitioningDelegate: NSObject, UIViewControllerT _presentationController(forPresented: presented, presenting: presenting, source: source) } - public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { presentationController } - public func interactionControllerForPresentation(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { presentationController?.interactiveTransition } - public func interactionControllerForDismissal(using animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { presentationController?.interactiveTransition } @@ -59,9 +56,9 @@ public final class BottomSheetTransitioningDelegate: NSObject, UIViewControllerT ) -> UIPresentationController? { _presentationController(forPresented: presented, presenting: presenting, source: source) } - + // MARK: - Private methods - + private func _presentationController( forPresented presented: UIViewController, presenting: UIViewController?, diff --git a/Sources/BottomSheet/Core/Extensions/UIViewController+Convenience.swift b/Sources/BottomSheet/Core/Extensions/UIViewController+Convenience.swift index e72106e..990a51f 100644 --- a/Sources/BottomSheet/Core/Extensions/UIViewController+Convenience.swift +++ b/Sources/BottomSheet/Core/Extensions/UIViewController+Convenience.swift @@ -61,7 +61,7 @@ public final class DefaultBottomSheetModalDismissalHandler: BottomSheetModalDism // MARK: - BottomSheetModalDismissalHandler - public let canBeDismissed: Bool = true + public let canBeDismissed = true public func performDismissal(animated: Bool) { presentingViewController?.presentedViewController?.dismiss(animated: animated, completion: dismissCompletion) diff --git a/Sources/BottomSheet/Core/NavigationController/BottomSheetNavigationController.swift b/Sources/BottomSheet/Core/NavigationController/BottomSheetNavigationController.swift index bdd4827..bb7d297 100644 --- a/Sources/BottomSheet/Core/NavigationController/BottomSheetNavigationController.swift +++ b/Sources/BottomSheet/Core/NavigationController/BottomSheetNavigationController.swift @@ -14,7 +14,7 @@ public final class BottomSheetNavigationController: UINavigationController { private var isUpdatingNavigationStack = false private var canAnimatePreferredContentSizeUpdates = false - + private weak var lastTransitionViewController: UIViewController? private let configuration: BottomSheetConfiguration @@ -26,6 +26,7 @@ public final class BottomSheetNavigationController: UINavigationController { super.init(rootViewController: rootViewController) } + @available(*, unavailable) required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } @@ -34,7 +35,7 @@ public final class BottomSheetNavigationController: UINavigationController { public override func viewDidLoad() { super.viewDidLoad() - + delegate = self view.clipsToBounds = true @@ -42,7 +43,7 @@ public final class BottomSheetNavigationController: UINavigationController { modalPresentationStyle = .custom } - + // MARK: - UINavigationController public override func setViewControllers(_ viewControllers: [UIViewController], animated: Bool) { @@ -66,7 +67,7 @@ public final class BottomSheetNavigationController: UINavigationController { return viewController } - + public override func popToRootViewController(animated: Bool) -> [UIViewController]? { var viewControllers: [UIViewController]? @@ -88,7 +89,7 @@ public final class BottomSheetNavigationController: UINavigationController { updatePreferredContentSize() view.layoutIfNeeded() } - + if canAnimatePreferredContentSizeUpdates { UIView.animate(withDuration: 0.25, animations: updates) } else { @@ -97,7 +98,7 @@ public final class BottomSheetNavigationController: UINavigationController { canAnimatePreferredContentSizeUpdates = true } - + // MARK: - Private methods private func updateNavigationStack(animated: Bool, applyChanges: () -> Void) { @@ -139,11 +140,11 @@ extension BottomSheetNavigationController: UINavigationControllerDelegate { if operation == .push { toVC.setupCustomInteractivePopTransition() } - + lastTransitionViewController = fromVC return BottomSheetNavigationAnimatedTransitioning(operation: operation, configuration: configuration) } - + public func navigationController( _ navigationController: UINavigationController, interactionControllerFor animationController: UIViewControllerAnimatedTransitioning diff --git a/Sources/BottomSheet/Core/NavigationController/UIViewController+CustomInteractiveTransition.swift b/Sources/BottomSheet/Core/NavigationController/UIViewController+CustomInteractiveTransition.swift index 018ef3d..4103f36 100644 --- a/Sources/BottomSheet/Core/NavigationController/UIViewController+CustomInteractiveTransition.swift +++ b/Sources/BottomSheet/Core/NavigationController/UIViewController+CustomInteractiveTransition.swift @@ -53,7 +53,7 @@ public extension UIViewController { } // MARK: - Private methods - + @objc private func handleGestureRecognizer(_ recognizer: UIScreenEdgePanGestureRecognizer) { switch recognizer.state { diff --git a/Sources/BottomSheet/Core/Presentation/BottomSheetPresentationController.swift b/Sources/BottomSheet/Core/Presentation/BottomSheetPresentationController.swift index c54a889..a74fbab 100644 --- a/Sources/BottomSheet/Core/Presentation/BottomSheetPresentationController.swift +++ b/Sources/BottomSheet/Core/Presentation/BottomSheetPresentationController.swift @@ -6,8 +6,8 @@ // Copyright © 2021 Joom. All rights reserved. // -import UIKit import Combine +import UIKit public protocol ScrollableBottomSheetPresentedController: AnyObject { var scrollView: UIScrollView? { get } @@ -286,9 +286,9 @@ public final class BottomSheetPresentationController: UIPresentationController { private func addShadow(containerView: UIView) { var shadingView = UIView() if let blur = configuration.shadowConfiguration.blur { - shadingView = UIVisualEffectView.init(effect: UIBlurEffect.init(style: blur)) + shadingView = UIVisualEffectView(effect: UIBlurEffect(style: blur)) } - + shadingView.backgroundColor = configuration.shadowConfiguration.backgroundColor containerView.addSubview(shadingView) shadingView.frame = containerView.bounds @@ -300,7 +300,7 @@ public final class BottomSheetPresentationController: UIPresentationController { self.shadingView = shadingView } - + @objc private func handleShadingViewTapGesture() { dismissIfPossible() @@ -374,25 +374,25 @@ extension BottomSheetPresentationController: UIScrollViewDelegate { // We don't want bounces inside bottom sheet let previousTranslation = scrollViewTranslation scrollViewTranslation = scrollView.panGestureRecognizer.translation(in: scrollView).y - + didStartDragging = shouldDragOverlay(following: scrollView) if didStartDragging { startInteractiveTransitionIfNeeded() overlayTranslation += scrollViewTranslation - previousTranslation - + // Update scrollView contentInset without invoking scrollViewDidScroll(_:) scrollView.bounds.origin.y = -scrollView.adjustedContentInset.top - + updateInteractionControllerProgress(verticalTranslation: overlayTranslation) } else { lastContentOffsetBeforeDragging = scrollView.panGestureRecognizer.translation(in: scrollView) } } - + public func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { isDragging = true } - + public func scrollViewWillEndDragging( _ scrollView: UIScrollView, withVelocity velocity: CGPoint, @@ -408,32 +408,32 @@ extension BottomSheetPresentationController: UIScrollViewDelegate { } else { endInteractiveTransition(isCancelled: true) } - + overlayTranslation = 0 scrollViewTranslation = 0 lastContentOffsetBeforeDragging = .zero didStartDragging = false isDragging = false } - + private func startInteractiveTransitionIfNeeded() { guard interactionController == nil else { return } - + startInteractiveTransition() } - + private func shouldDragOverlay(following scrollView: UIScrollView) -> Bool { guard scrollView.isTracking, isInteractiveTransitionCanBeHandled else { return false } - + if let percentComplete = interactionController?.percentComplete { if percentComplete.isAlmostEqual(to: 0) { return scrollView.isContentOriginInBounds && scrollView.scrollsDown } - + return true } else { return scrollView.isContentOriginInBounds && scrollView.scrollsDown @@ -489,10 +489,10 @@ extension BottomSheetPresentationController: UINavigationControllerDelegate { else { return } - + trackedScrollView?.multicastingDelegate.removeDelegate(self) scrollView.multicastingDelegate.addDelegate(self) - self.trackedScrollView = scrollView + trackedScrollView = scrollView } } @@ -565,19 +565,18 @@ extension BottomSheetPresentationController: UIViewControllerAnimatedTransitioni UIView.animate(withDuration: transitionDurationValue, delay: 0, options: options, animations: animations, completion: completion) } - public func animationEnded(_ transitionCompleted: Bool) { - } + public func animationEnded(_ transitionCompleted: Bool) {} } private extension UIScrollView { var scrollsUp: Bool { panGestureRecognizer.velocity(in: nil).y < 0 } - + var scrollsDown: Bool { !scrollsUp } - + var isContentOriginInBounds: Bool { contentOffset.y <= -adjustedContentInset.top } diff --git a/Sources/BottomSheet/Helpers/UI/CGRect+Helpers.swift b/Sources/BottomSheet/Helpers/UI/CGRect+Helpers.swift index 209b209..685d883 100644 --- a/Sources/BottomSheet/Helpers/UI/CGRect+Helpers.swift +++ b/Sources/BottomSheet/Helpers/UI/CGRect+Helpers.swift @@ -19,13 +19,13 @@ public extension CGRect { origin = CGPoint(x: newValue.x - width * 0.5, y: newValue.y - height * 0.5) } } - + // MARK: - Equality - + func isAlmostEqual(to other: CGRect) -> Bool { size.isAlmostEqual(to: other.size) && origin.isAlmostEqual(to: other.origin) } - + func isAlmostEqual(to other: CGRect, error: CGFloat) -> Bool { size.isAlmostEqual(to: other.size, error: error) && origin.isAlmostEqual(to: other.origin, error: error) } diff --git a/Sources/BottomSheet/Helpers/UI/CGSize+Helpers.swift b/Sources/BottomSheet/Helpers/UI/CGSize+Helpers.swift index 27f0390..90cfd37 100644 --- a/Sources/BottomSheet/Helpers/UI/CGSize+Helpers.swift +++ b/Sources/BottomSheet/Helpers/UI/CGSize+Helpers.swift @@ -12,13 +12,13 @@ extension CGSize { static func uniform(_ side: CGFloat) -> CGSize { CGSize(width: side, height: side) } - + // MARK: - Equality func isAlmostEqual(to other: CGSize) -> Bool { width.isAlmostEqual(to: other.width) && height.isAlmostEqual(to: other.height) } - + func isAlmostEqual(to other: CGSize, error: CGFloat) -> Bool { width.isAlmostEqual(to: other.width, error: error) && height.isAlmostEqual(to: other.height, error: error) } diff --git a/Sources/BottomSheet/Helpers/UI/UIViewController+Lifecycle.swift b/Sources/BottomSheet/Helpers/UI/UIViewController+Lifecycle.swift index bf37604..ba78e6d 100644 --- a/Sources/BottomSheet/Helpers/UI/UIViewController+Lifecycle.swift +++ b/Sources/BottomSheet/Helpers/UI/UIViewController+Lifecycle.swift @@ -19,15 +19,15 @@ public enum ViewControllerEvent: Int { public extension UIViewController { private static var key: UInt8 = 0 - + typealias EventListener = () -> Void - + private var listeners: [EventListener] { get { guard let listeners = objc_getAssociatedObject(self, &Self.key) as? [EventListener] else { return [] } - + return listeners } set { @@ -41,70 +41,70 @@ public extension UIViewController { } let originalToSwizzled = [ - #selector(viewDidLoad) : #selector(swizzled_viewDidLoad), - #selector(viewWillAppear(_:)) : #selector(swizzled_viewWillAppear(_:)), - #selector(viewDidAppear(_:)) : #selector(swizzled_viewDidAppear(_:)), + #selector(viewDidLoad): #selector(swizzled_viewDidLoad), + #selector(viewWillAppear(_:)): #selector(swizzled_viewWillAppear(_:)), + #selector(viewDidAppear(_:)): #selector(swizzled_viewDidAppear(_:)), #selector(viewWillDisappear(_:)): #selector(swizzled_viewWillDisappear(_:)), - #selector(viewDidDisappear(_:)) : #selector(swizzled_viewDidDisappear(_:)) + #selector(viewDidDisappear(_:)): #selector(swizzled_viewDidDisappear(_:)), ] for (originalSelector, swizzledSelector) in originalToSwizzled { guard let originalMethod = class_getInstanceMethod(self, originalSelector), let swizzledMethod = class_getInstanceMethod(self, swizzledSelector) - else { return } + else { return } let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)) if didAddMethod { class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)) } else { - method_exchangeImplementations(originalMethod, swizzledMethod); + method_exchangeImplementations(originalMethod, swizzledMethod) } } } @objc private func swizzled_viewDidLoad() { - self.swizzled_viewDidLoad() + swizzled_viewDidLoad() notifyEvent(.viewDidLoad) } @objc private func swizzled_viewWillAppear(_ animated: Bool) { - self.swizzled_viewWillAppear(animated) + swizzled_viewWillAppear(animated) notifyEvent(.viewWillAppear) } @objc private func swizzled_viewDidAppear(_ animated: Bool) { - self.swizzled_viewDidAppear(animated) + swizzled_viewDidAppear(animated) notifyEvent(.viewDidAppear) } @objc private func swizzled_viewWillDisappear(_ animated: Bool) { - self.swizzled_viewWillDisappear(animated) + swizzled_viewWillDisappear(animated) notifyEvent(.viewWillDisappear) } @objc private func swizzled_viewDidDisappear(_ animated: Bool) { - self.swizzled_viewDidDisappear(animated) + swizzled_viewDidDisappear(animated) notifyEvent(.viewDidDisappear) } - + private func notifyEvent(_ event: ViewControllerEvent) { listeners.forEach { $0() } } - + func subscribe(onEvent: ViewControllerEvent, listener: @escaping EventListener) { listeners.append(listener) }