diff --git a/DLAutoSlidePageViewController.podspec b/DLAutoSlidePageViewController.podspec index d31b06d..1df6f79 100644 --- a/DLAutoSlidePageViewController.podspec +++ b/DLAutoSlidePageViewController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'DLAutoSlidePageViewController' - s.version = '1.2.1' + s.version = '1.3.1' s.summary = 'An auto slide PageViewController.' s.description = <<-DESC diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj index 7eb118b..7e4b2d9 100644 --- a/Example/Pods/Pods.xcodeproj/project.pbxproj +++ b/Example/Pods/Pods.xcodeproj/project.pbxproj @@ -16,6 +16,7 @@ 664D3991F9141C16D6EA21E756F87FF2 /* AutoSlideConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 90E90EFDA331852780D0EE8805CD8B7B /* AutoSlideConfiguration.swift */; }; 9CEAE55E9569C5451CA65ABA3765378B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; 9FE73A71A4B3BD25B6D32FFC99B46883 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; + E268787D269BB12D00C63186 /* AutoSlideHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = E268787C269BB12D00C63186 /* AutoSlideHelper.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -38,21 +39,22 @@ 372DE4C08CC282D920921A34B5109D06 /* Pods-DLAutoSlidePageViewController Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DLAutoSlidePageViewController Example-frameworks.sh"; sourceTree = ""; }; 447C75119D623A228A3FAAE74CD8A027 /* DLAutoSlidePageViewController-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "DLAutoSlidePageViewController-Info.plist"; sourceTree = ""; }; 4844082F6FA57C68A8218D2E261617C6 /* DLAutoSlidePageViewController.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = DLAutoSlidePageViewController.debug.xcconfig; sourceTree = ""; }; - 60AD8DB0E1367FE5E52CEA71C1A48AAA /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = ""; }; - 72C3E605083DD1F1DF7DE790F0961593 /* DLAutoSlidePageViewController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = DLAutoSlidePageViewController.framework; path = DLAutoSlidePageViewController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 60AD8DB0E1367FE5E52CEA71C1A48AAA /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + 72C3E605083DD1F1DF7DE790F0961593 /* DLAutoSlidePageViewController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DLAutoSlidePageViewController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 90E90EFDA331852780D0EE8805CD8B7B /* AutoSlideConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AutoSlideConfiguration.swift; path = Sources/AutoSlideConfiguration.swift; sourceTree = ""; }; - 977B4B9729D28650FEAB25F99F13B64F /* DLAutoSlidePageViewController.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = DLAutoSlidePageViewController.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 977B4B9729D28650FEAB25F99F13B64F /* DLAutoSlidePageViewController.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = DLAutoSlidePageViewController.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; + 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; A59DD88EAE2E5F2BE1FEE08E5B1BBEF6 /* Pods-DLAutoSlidePageViewController Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-DLAutoSlidePageViewController Example-umbrella.h"; sourceTree = ""; }; A849C9E5763763966F469812F22856DF /* DLAutoSlidePageViewController-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "DLAutoSlidePageViewController-dummy.m"; sourceTree = ""; }; - ABB1B551650CD5A96ECF46580855589C /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = ""; }; + ABB1B551650CD5A96ECF46580855589C /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; B0AD21977CB12429D3A0A6785AA1A343 /* Pods-DLAutoSlidePageViewController Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-DLAutoSlidePageViewController Example-Info.plist"; sourceTree = ""; }; - B1A017D5C355C1C89C853F86B24738F6 /* Pods_DLAutoSlidePageViewController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_DLAutoSlidePageViewController_Example.framework; path = "Pods-DLAutoSlidePageViewController Example.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; + B1A017D5C355C1C89C853F86B24738F6 /* Pods_DLAutoSlidePageViewController_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DLAutoSlidePageViewController_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B403E2AD8C59B88B7AC8D935227315CC /* DefaultAutoSlideConfiguration.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DefaultAutoSlideConfiguration.swift; path = Sources/DefaultAutoSlideConfiguration.swift; sourceTree = ""; }; D9F31ACE498732F5F6EE8BBDA4681175 /* DLAutoSlidePageViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = DLAutoSlidePageViewController.swift; path = Sources/DLAutoSlidePageViewController.swift; sourceTree = ""; }; DC68CA978B9BECBC6EF830C65F369642 /* DLAutoSlidePageViewController.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = DLAutoSlidePageViewController.modulemap; sourceTree = ""; }; DE137974C36B1F5C84E5F9785564E5DF /* Pods-DLAutoSlidePageViewController Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DLAutoSlidePageViewController Example.debug.xcconfig"; sourceTree = ""; }; + E268787C269BB12D00C63186 /* AutoSlideHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AutoSlideHelper.swift; path = Sources/AutoSlideHelper.swift; sourceTree = ""; }; E9045BD7C63975F9B953AA3EDA1D62ED /* DLAutoSlidePageViewController-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DLAutoSlidePageViewController-umbrella.h"; sourceTree = ""; }; EAEDEFE6DBC73AE22929456D3275B7A8 /* DLAutoSlidePageViewController-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "DLAutoSlidePageViewController-prefix.pch"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -123,6 +125,7 @@ C29724712C6904EF8DE93BC6B4285DC7 /* DLAutoSlidePageViewController */ = { isa = PBXGroup; children = ( + E268787C269BB12D00C63186 /* AutoSlideHelper.swift */, 90E90EFDA331852780D0EE8805CD8B7B /* AutoSlideConfiguration.swift */, B403E2AD8C59B88B7AC8D935227315CC /* DefaultAutoSlideConfiguration.swift */, D9F31ACE498732F5F6EE8BBDA4681175 /* DLAutoSlidePageViewController.swift */, @@ -302,6 +305,7 @@ buildActionMask = 2147483647; files = ( 664D3991F9141C16D6EA21E756F87FF2 /* AutoSlideConfiguration.swift in Sources */, + E268787D269BB12D00C63186 /* AutoSlideHelper.swift in Sources */, 00CADED749FDF58827498C5701397E08 /* DefaultAutoSlideConfiguration.swift in Sources */, 53CD553D44050556F61BAB49EA51A6BF /* DLAutoSlidePageViewController-dummy.m in Sources */, 5219658C939FC70180628D6E41752462 /* DLAutoSlidePageViewController.swift in Sources */, @@ -471,8 +475,7 @@ MTL_FAST_MATH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 5.0; SYMROOT = "${SRCROOT}/../build"; }; diff --git a/README.md b/README.md index f2f685f..367101b 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ let pageViewController = DLAutoSlidePageViewController(pages: pages, configurati | timeInterval | TimeInterval | Time interval to be used for each page automatic transition. | | transitionStyle | UIPageViewController.TransitionStyle | Styles for the page-turn transition. | | navigationOrientation | UIPageViewController.NavigationOrientation | Orientations for page-turn transitions. | +| navigationDirection | UIPageViewController.NavigationDirection | Directions for page-turn transitions. | | interPageSpacing | Float | Space between pages. | | spineLocation | UIPageViewController.SpineLocation | Locations for the spine. Only valid if the transition style is UIPageViewController.TransitionStyle.pageCurl. | | hidePageControl | Bool | Decides if page control is going to be shown or not. | diff --git a/Sources/AutoSlideConfiguration.swift b/Sources/AutoSlideConfiguration.swift index 5fbd391..941fd6b 100644 --- a/Sources/AutoSlideConfiguration.swift +++ b/Sources/AutoSlideConfiguration.swift @@ -18,6 +18,9 @@ public protocol AutoSlideConfiguration { /// Orientations for page-turn transitions. var navigationOrientation: UIPageViewController.NavigationOrientation { get } + /// Directions for page-turn transitions. + var navigationDirection: UIPageViewController.NavigationDirection { get } + /// Space between pages. var interPageSpacing: Float { get } @@ -45,6 +48,7 @@ public extension AutoSlideConfiguration { var timeInterval: TimeInterval { 3.0 } var transitionStyle: UIPageViewController.TransitionStyle { .scroll } var navigationOrientation: UIPageViewController.NavigationOrientation { .horizontal } + var navigationDirection: UIPageViewController.NavigationDirection { .forward } var interPageSpacing: Float { 0.0 } var spineLocation: UIPageViewController.SpineLocation { .none } var hidePageControl: Bool { false } diff --git a/Sources/AutoSlideHelper.swift b/Sources/AutoSlideHelper.swift new file mode 100644 index 0000000..ca468ae --- /dev/null +++ b/Sources/AutoSlideHelper.swift @@ -0,0 +1,25 @@ +// +// AutoSlideHelper.swift +// DLAutoSlidePageViewController +// +// Created by Alonso on 11/07/21. +// + +import UIKit + +final class AutoSlideHelper { + + class func pageIndex(for currentPageIndex: Int, + totalPageCount: Int, + direction: UIPageViewController.NavigationDirection) -> Int { + switch direction { + case .reverse: + return currentPageIndex > 0 ? currentPageIndex - 1 : totalPageCount - 1 + case .forward: + fallthrough + @unknown default: + return currentPageIndex < totalPageCount - 1 ? currentPageIndex + 1 : 0 + } + } + +} diff --git a/Sources/DLAutoSlidePageViewController.swift b/Sources/DLAutoSlidePageViewController.swift index 9d503a8..9dfdf2b 100644 --- a/Sources/DLAutoSlidePageViewController.swift +++ b/Sources/DLAutoSlidePageViewController.swift @@ -10,14 +10,17 @@ import UIKit open class DLAutoSlidePageViewController: UIPageViewController { - fileprivate(set) var pages: [UIViewController] = [] + private var pages: [UIViewController] = [] - fileprivate var currentPageIndex: Int = 0 - fileprivate var nextPageIndex: Int = 0 - fileprivate var timer: Timer? - fileprivate var timeInterval: TimeInterval = 0.0 - fileprivate var transitionInProgress: Bool = false - fileprivate var shouldHidePageControl: Bool = false + private var currentPageIndex: Int = 0 + private var nextPageIndex: Int = 0 + private var timer: Timer? + + private var timeInterval: TimeInterval = 0.0 + private var shouldHidePageControl: Bool = false + private var navigationDirection: UIPageViewController.NavigationDirection = .forward + + private var transitionInProgress: Bool = false // MARK: - Computed properties @@ -34,8 +37,10 @@ open class DLAutoSlidePageViewController: UIPageViewController { options: [UIPageViewController.OptionsKey.interPageSpacing: configuration.interPageSpacing, UIPageViewController.OptionsKey.spineLocation: configuration.spineLocation]) self.pages = pages + self.timeInterval = configuration.timeInterval self.shouldHidePageControl = configuration.hidePageControl + self.navigationDirection = configuration.navigationDirection setupPageView() setupPageTimer(with: timeInterval) @@ -77,30 +82,30 @@ open class DLAutoSlidePageViewController: UIPageViewController { // MARK: - Private - fileprivate func setupObservers() { + private func setupObservers() { let notificationCenter = NotificationCenter.default notificationCenter.addObserver(self, selector: #selector(movedToForeground), name: UIApplication.willEnterForegroundNotification, object: nil) } - fileprivate func setupPageView() { + private func setupPageView() { guard let firstPage = pages.first else { return } currentPageIndex = 0 - setViewControllers([firstPage], direction: .forward, animated: true, completion: nil) + setViewControllers([firstPage], direction: navigationDirection, animated: true, completion: nil) } - fileprivate func setupPageControl(with configuration: AutoSlideConfiguration) { + private func setupPageControl(with configuration: AutoSlideConfiguration) { pageControl?.currentPageIndicatorTintColor = configuration.currentPageIndicatorTintColor pageControl?.pageIndicatorTintColor = configuration.pageIndicatorTintColor pageControl?.backgroundColor = configuration.pageControlBackgroundColor } - fileprivate func viewControllerAtIndex(_ index: Int) -> UIViewController { + private func viewControllerAtIndex(_ index: Int) -> UIViewController { guard index < pages.count else { return UIViewController() } currentPageIndex = index return pages[index] } - fileprivate func setupPageTimer(with timeInterval: TimeInterval) { + private func setupPageTimer(with timeInterval: TimeInterval) { guard timeInterval != 0.0 else { return } timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, @@ -109,35 +114,33 @@ open class DLAutoSlidePageViewController: UIPageViewController { repeats: true) } - fileprivate func stopTimer() { + private func stopTimer() { guard let _ = timer else { return } timer?.invalidate() timer = nil } - fileprivate func restartTimer() { + private func restartTimer() { stopTimer() setupPageTimer(with: timeInterval) } // MARK: - Selectors - @objc fileprivate func movedToForeground() { + @objc private func movedToForeground() { transitionInProgress = false restartTimer() } - @objc fileprivate func changePage() { - if currentPageIndex < pages.count - 1 { - currentPageIndex += 1 - } else { - currentPageIndex = 0 - } + @objc private func changePage() { + currentPageIndex = AutoSlideHelper.pageIndex(for: currentPageIndex, + totalPageCount: pages.count, + direction: navigationDirection) guard let viewController = viewControllerAtIndex(currentPageIndex) as UIViewController? else { return } if !transitionInProgress { transitionInProgress = true - setViewControllers([viewController], direction: .forward, animated: true, completion: { finished in - self.transitionInProgress = !finished + setViewControllers([viewController], direction: navigationDirection, animated: true, completion: { finished in + self.transitionInProgress = false }) } } diff --git a/Sources/DefaultAutoSlideConfiguration.swift b/Sources/DefaultAutoSlideConfiguration.swift index d573e03..f75bee8 100644 --- a/Sources/DefaultAutoSlideConfiguration.swift +++ b/Sources/DefaultAutoSlideConfiguration.swift @@ -18,6 +18,7 @@ final public class DefaultAutoSlideConfiguration: AutoSlideConfiguration { public var timeInterval: TimeInterval = 3.0 public var transitionStyle: UIPageViewController.TransitionStyle = .scroll public var navigationOrientation: UIPageViewController.NavigationOrientation = .horizontal + public var navigationDirection: UIPageViewController.NavigationDirection = .forward public var interPageSpacing: Float = 0.0 public var spineLocation: UIPageViewController.SpineLocation = .none public var hidePageControl: Bool = false