Skip to content

Commit

Permalink
New modifier to change content loading policy
Browse files Browse the repository at this point in the history
  • Loading branch information
Fernando Moya de Rivas committed Jul 5, 2020
1 parent a0cab66 commit 298378f
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 9 deletions.
4 changes: 4 additions & 0 deletions Example/SwiftUIPagerExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
6BC5EE0024866D9500E1E78C /* SizeViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC5EDF924866D9500E1E78C /* SizeViewModifier.swift */; };
6BC5EE0124866D9500E1E78C /* Pager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC5EDFA24866D9500E1E78C /* Pager.swift */; };
6BC5EE0224866D9500E1E78C /* Pager+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BC5EDFB24866D9500E1E78C /* Pager+Helper.swift */; };
6BCF139224B2677B00AADE74 /* ContentLoadingPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF139124B2677B00AADE74 /* ContentLoadingPolicy.swift */; };
6BEA731324ACF8D7007EA8DC /* PositionAlignment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BEA730F24ACF8D7007EA8DC /* PositionAlignment.swift */; };
6BEA731424ACF8D7007EA8DC /* SwipeDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BEA731024ACF8D7007EA8DC /* SwipeDirection.swift */; };
6BEA731524ACF8D7007EA8DC /* SwipeInteractionArea.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BEA731124ACF8D7007EA8DC /* SwipeInteractionArea.swift */; };
Expand Down Expand Up @@ -62,6 +63,7 @@
6BC5EDF924866D9500E1E78C /* SizeViewModifier.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SizeViewModifier.swift; sourceTree = "<group>"; };
6BC5EDFA24866D9500E1E78C /* Pager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Pager.swift; path = ../../Sources/SwiftUIPager/Pager.swift; sourceTree = "<group>"; };
6BC5EDFB24866D9500E1E78C /* Pager+Helper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Pager+Helper.swift"; path = "../../Sources/SwiftUIPager/Pager+Helper.swift"; sourceTree = "<group>"; };
6BCF139124B2677B00AADE74 /* ContentLoadingPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContentLoadingPolicy.swift; path = ../../Sources/SwiftUIPager/PageConfiguration/ContentLoadingPolicy.swift; sourceTree = "<group>"; };
6BEA730F24ACF8D7007EA8DC /* PositionAlignment.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = PositionAlignment.swift; path = ../../Sources/SwiftUIPager/PageConfiguration/PositionAlignment.swift; sourceTree = "<group>"; };
6BEA731024ACF8D7007EA8DC /* SwipeDirection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwipeDirection.swift; path = ../../Sources/SwiftUIPager/PageConfiguration/SwipeDirection.swift; sourceTree = "<group>"; };
6BEA731124ACF8D7007EA8DC /* SwipeInteractionArea.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SwipeInteractionArea.swift; path = ../../Sources/SwiftUIPager/PageConfiguration/SwipeInteractionArea.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -157,6 +159,7 @@
6BEA730E24ACF8BB007EA8DC /* PageConfiguration */ = {
isa = PBXGroup;
children = (
6BCF139124B2677B00AADE74 /* ContentLoadingPolicy.swift */,
6BEA731224ACF8D7007EA8DC /* GesturePriority.swift */,
6BEA730F24ACF8D7007EA8DC /* PositionAlignment.swift */,
6BEA731024ACF8D7007EA8DC /* SwipeDirection.swift */,
Expand Down Expand Up @@ -256,6 +259,7 @@
6B22DC81247E5C9A00EF95C5 /* NestedExampleView.swift in Sources */,
17D9E0F823D4CF6700C5AE93 /* ContentView.swift in Sources */,
6BC5EDFC24866D9500E1E78C /* Pager+Buildable.swift in Sources */,
6BCF139224B2677B00AADE74 /* ContentLoadingPolicy.swift in Sources */,
6BEA731524ACF8D7007EA8DC /* SwipeInteractionArea.swift in Sources */,
6BC5EE0124866D9500E1E78C /* Pager.swift in Sources */,
);
Expand Down
27 changes: 27 additions & 0 deletions Sources/SwiftUIPager/PageConfiguration/ContentLoadingPolicy.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// File.swift
//
//
// Created by Fernando Moya de Rivas on 05/07/2020.
//

import Foundation

/// Policy to follow when loading content
public enum ContentLoadingPolicy: Equatable {

/// Content is loaded on demand by applying a recycling the ratio.
///
/// - Parameter recyclingRatio: Manages the number of items that should be displayed in the screen.
///
/// A ratio of `5`, for instance, will load enough items in memory to fill five times the size of `Pager`.
/// - Note: `recyclingRatio` must be greather than `0`.
case lazy(recyclingRatio: UInt)

/// Choose `eager` to load all items at once
case eager

/// Default policy, a.k.a, `lazy(recyclingRatio: 5)`
static var `default`: ContentLoadingPolicy = .lazy(recyclingRatio: 5)
}

5 changes: 4 additions & 1 deletion Sources/SwiftUIPager/PageConfiguration/GesturePriority.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ public enum GesturePriority {
case simultaneous

/// Refers to `gesture` modifier
case `default`
case normal

/// Default value, a.k.a, `normal`
static let `default`: GesturePriority = .normal
}

@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
Expand Down
10 changes: 10 additions & 0 deletions Sources/SwiftUIPager/Pager+Buildable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ import SwiftUI
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Pager: Buildable {

/// Sets the policy followed to load `Pager` content.
///
/// - Parameter value: policy to load the content.
///
/// Choose `lazy` to load pages on demand so that the right amount of memory is used. Choose `eager` if
/// `Pager` won't hold many items or if memory isn't an issue.
public func contentLoadingPolicy(_ value: ContentLoadingPolicy) -> Self {
mutating(keyPath: \.contentLoadingPolicy, value: value)
}

/// Sets `Pager` to loop the items in a never-ending scroll.
///
/// - Parameter value: `true` if `Pager` should loop the pages. `false`, otherwise.
Expand Down
19 changes: 17 additions & 2 deletions Sources/SwiftUIPager/Pager+Helper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ import SwiftUI
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension Pager {

/// Manages the number of items that should be displayed in the screen.
var recyclingRatio: Int {
switch contentLoadingPolicy {
case .eager:
return numberOfPages
case .lazy(let ratio):
return max(1, Int(ratio))
}
}

/// Work around to avoid @State keeps wrong value
var page: Int {
return min(pageIndex, numberOfPages - 1)
Expand Down Expand Up @@ -106,6 +116,7 @@ extension Pager {

/// Maximum number in memory at the same time. Always an even number.
var maximumNumberOfPages: Int {
guard contentLoadingPolicy != .eager else { return numberOfPages }
guard pageDistance != 0, numberOfPages > 0 else { return 0 }
let side = isHorizontal ? size.width : size.height
var number = Int((CGFloat(recyclingRatio) * side / pageDistance).rounded(.up))
Expand Down Expand Up @@ -139,14 +150,18 @@ extension Pager {

/// Lower bound of the data displaed
var lowerPageDisplayed: Int {
guard isInifinitePager else { return max(0, page - maximumNumberOfPages / 2) }
guard isInifinitePager else {
return contentLoadingPolicy == .eager ? 0 : max(0, page - maximumNumberOfPages / 2)
}
guard numberOfPages > 0 else { return 0 }
return ((page - maximumNumberOfPages / 2) + numberOfPages) % numberOfPages
}

/// Upper bound of the data displaed
var upperPageDisplayed: Int {
guard isInifinitePager else { return min(numberOfPages - 1, page + maximumNumberOfPages / 2) }
guard isInifinitePager else {
return contentLoadingPolicy == .eager ? numberOfPages - 1 : min(numberOfPages - 1, page + maximumNumberOfPages / 2)
}
guard numberOfPages > 0 else { return 0 }
return (Int((Float(maximumNumberOfPages) / 2).rounded(.up)) + page) % numberOfPages
}
Expand Down
6 changes: 2 additions & 4 deletions Sources/SwiftUIPager/Pager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ public struct Pager<Element, ID, PageView>: View where PageView: View, Element:

/*** Constants ***/

/// Manages the number of items that should be displayed in the screen.
/// A ratio of 5, for instance, would mean the items held in memory are enough
/// to cover 5 times the size of the pager
let recyclingRatio = 5
/// Policy to be applied when loading content
var contentLoadingPolicy: ContentLoadingPolicy = .default

/// Angle of rotation when should rotate
let rotationDegrees: Double = 20
Expand Down
2 changes: 1 addition & 1 deletion SwiftUIPager.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "SwiftUIPager"
s.version = "1.7.0"
s.version = "1.8.0-beta.1"
s.summary = "Native pager for SwiftUI. Easily to use, easy to customize."

s.description = <<-DESC
Expand Down
12 changes: 12 additions & 0 deletions SwiftUIPager.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@
6BBC3D772488DC0B004194BD /* Pager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BDE442223DE12470022A2F7 /* Pager.swift */; };
6BBC3D782488DC0E004194BD /* Pager+Buildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BDE442323DE12470022A2F7 /* Pager+Buildable.swift */; };
6BBC3D792488DC11004194BD /* Pager+Helper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BDE442823DE12480022A2F7 /* Pager+Helper.swift */; };
6BCF138C24B2674E00AADE74 /* ContentLoadingPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF138B24B2674800AADE74 /* ContentLoadingPolicy.swift */; };
6BCF138D24B2674F00AADE74 /* ContentLoadingPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF138B24B2674800AADE74 /* ContentLoadingPolicy.swift */; };
6BCF138E24B2674F00AADE74 /* ContentLoadingPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF138B24B2674800AADE74 /* ContentLoadingPolicy.swift */; };
6BCF138F24B2675000AADE74 /* ContentLoadingPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF138B24B2674800AADE74 /* ContentLoadingPolicy.swift */; };
6BCF139024B2675000AADE74 /* ContentLoadingPolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BCF138B24B2674800AADE74 /* ContentLoadingPolicy.swift */; };
6BDE441C23DE10C10022A2F7 /* SwiftUIPager.h in Headers */ = {isa = PBXBuildFile; fileRef = 6BDE441A23DE10C10022A2F7 /* SwiftUIPager.h */; settings = {ATTRIBUTES = (Public, ); }; };
6BDE442923DE12480022A2F7 /* Pager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BDE442223DE12470022A2F7 /* Pager.swift */; };
6BDE442A23DE12480022A2F7 /* Pager+Buildable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6BDE442323DE12470022A2F7 /* Pager+Buildable.swift */; };
Expand Down Expand Up @@ -101,6 +106,7 @@
6B2C3069248D747700E528F9 /* Info-Catalyst.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-Catalyst.plist"; sourceTree = "<group>"; };
6B3F9C052488E6FE00AF5E74 /* Info-tvOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-tvOS.plist"; sourceTree = "<group>"; };
6BBC3D6B2488DBE8004194BD /* SwiftUIPager.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftUIPager.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6BCF138B24B2674800AADE74 /* ContentLoadingPolicy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ContentLoadingPolicy.swift; path = Sources/SwiftUIPager/PageConfiguration/ContentLoadingPolicy.swift; sourceTree = SOURCE_ROOT; };
6BDE441723DE10C10022A2F7 /* SwiftUIPager.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftUIPager.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6BDE441A23DE10C10022A2F7 /* SwiftUIPager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftUIPager.h; sourceTree = "<group>"; };
6BDE441B23DE10C10022A2F7 /* Info-iOS.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-iOS.plist"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -226,6 +232,7 @@
6BEA730D24ACF7FF007EA8DC /* PageConfiguration */ = {
isa = PBXGroup;
children = (
6BCF138B24B2674800AADE74 /* ContentLoadingPolicy.swift */,
6BEA731A24ACF9B0007EA8DC /* GesturePriority.swift */,
6BEA731924ACF9B0007EA8DC /* PositionAlignment.swift */,
6BEA731724ACF9AF007EA8DC /* SwipeDirection.swift */,
Expand Down Expand Up @@ -497,6 +504,7 @@
6BEA732C24ACFA08007EA8DC /* SwipeInteractionArea.swift in Sources */,
172F4D5623DF830600FD2F15 /* Pager+Buildable.swift in Sources */,
172F4D5723DF830600FD2F15 /* View+Helper.swift in Sources */,
6BCF138E24B2674F00AADE74 /* ContentLoadingPolicy.swift in Sources */,
172F4D5823DF830600FD2F15 /* Buildable.swift in Sources */,
172F4D5923DF830600FD2F15 /* Pager.swift in Sources */,
6BEA732724ACFA03007EA8DC /* SwipeDirection.swift in Sources */,
Expand All @@ -514,6 +522,7 @@
6BEA732D24ACFA08007EA8DC /* SwipeInteractionArea.swift in Sources */,
172F4D8423DF8B4400FD2F15 /* Pager.swift in Sources */,
172F4D8223DF8B3F00FD2F15 /* SizeViewModifier.swift in Sources */,
6BCF138F24B2675000AADE74 /* ContentLoadingPolicy.swift in Sources */,
172F4D8023DF8B3800FD2F15 /* View+Helper.swift in Sources */,
172F4D8523DF8B4800FD2F15 /* Pager+Buildable.swift in Sources */,
6BEA732824ACFA04007EA8DC /* SwipeDirection.swift in Sources */,
Expand All @@ -531,6 +540,7 @@
6BEA732B24ACFA07007EA8DC /* SwipeInteractionArea.swift in Sources */,
6B2C305A248D740800E528F9 /* Pager+Buildable.swift in Sources */,
6B2C305B248D740800E528F9 /* View+Helper.swift in Sources */,
6BCF138D24B2674F00AADE74 /* ContentLoadingPolicy.swift in Sources */,
6B2C305C248D740800E528F9 /* Buildable.swift in Sources */,
6B2C305E248D740800E528F9 /* Pager.swift in Sources */,
6BEA732624ACFA03007EA8DC /* SwipeDirection.swift in Sources */,
Expand All @@ -548,6 +558,7 @@
6BEA732E24ACFA09007EA8DC /* SwipeInteractionArea.swift in Sources */,
6BBC3D772488DC0B004194BD /* Pager.swift in Sources */,
6BBC3D782488DC0E004194BD /* Pager+Buildable.swift in Sources */,
6BCF139024B2675000AADE74 /* ContentLoadingPolicy.swift in Sources */,
6BBC3D742488DC01004194BD /* View+Helper.swift in Sources */,
6BBC3D762488DC07004194BD /* SizeViewModifier.swift in Sources */,
6BEA732924ACFA04007EA8DC /* SwipeDirection.swift in Sources */,
Expand All @@ -565,6 +576,7 @@
6BEA732A24ACFA07007EA8DC /* SwipeInteractionArea.swift in Sources */,
6BDE442A23DE12480022A2F7 /* Pager+Buildable.swift in Sources */,
6BDE442B23DE12480022A2F7 /* View+Helper.swift in Sources */,
6BCF138C24B2674E00AADE74 /* ContentLoadingPolicy.swift in Sources */,
6BDE442C23DE12480022A2F7 /* Buildable.swift in Sources */,
6BDE442923DE12480022A2F7 /* Pager.swift in Sources */,
6BEA732524ACFA02007EA8DC /* SwipeDirection.swift in Sources */,
Expand Down
24 changes: 23 additions & 1 deletion Tests/SwiftUIPagerTests/Pager+Buildable_Tests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,25 @@ final class Pager_Buildable_Tests: XCTestCase {
XCTAssertEqual(pager.swipeInteractionArea, .page)
XCTAssertEqual(pager.minimumDistance, 15)
XCTAssertEqual(pager.gesturePriority, .default)
XCTAssertEqual(pager.contentLoadingPolicy, .default)
}

func test_GivenPager_WhenContentLoadingPolicyLazy0_ThenRecyclingRatioIs1() {
var pager = givenPager
pager = pager.contentLoadingPolicy(.lazy(recyclingRatio: 0))
XCTAssertEqual(pager.recyclingRatio, 1)
}

func test_GivenPager_WhenContentLoadingPolicyLazy10_ThenRecyclingRatioIs10() {
var pager = givenPager
pager = pager.contentLoadingPolicy(.lazy(recyclingRatio: 10))
XCTAssertEqual(pager.recyclingRatio, 10)
}

func test_GivenPager_WhenContentLoadingPolicyEager_ThenRecyclingRatioIsIntMax() {
var pager = givenPager
pager = pager.contentLoadingPolicy(.eager)
XCTAssertEqual(pager.recyclingRatio, pager.numberOfPages)
}

func test_GivenPager_WhenPagingPrioritySimultaneous_ThenSimultaneous() {
Expand Down Expand Up @@ -312,6 +331,9 @@ final class Pager_Buildable_Tests: XCTestCase {
("test_GivenPager_WhenLoopPages_ThenIsInfinitePagerTrue", test_GivenPager_WhenLoopPages_ThenIsInfinitePagerTrue),
("test_GivenPager_WhenPreferredItemSize_ThenNotNil", test_GivenPager_WhenPreferredItemSize_ThenNotNil),
("test_GivenPager_WhenPagingPrioritySimultaneous_ThenSimultaneous", test_GivenPager_WhenPagingPrioritySimultaneous_ThenSimultaneous),
("test_GivenPager_WhenPagingPriorityHigh_ThenHigh", test_GivenPager_WhenPagingPriorityHigh_ThenHigh)
("test_GivenPager_WhenPagingPriorityHigh_ThenHigh", test_GivenPager_WhenPagingPriorityHigh_ThenHigh),
("test_GivenPager_WhenContentLoadingPolicyLazy0_ThenRecyclingRatioIs1", test_GivenPager_WhenContentLoadingPolicyLazy0_ThenRecyclingRatioIs1),
("test_GivenPager_WhenContentLoadingPolicyLazy10_ThenRecyclingRatioIs10", test_GivenPager_WhenContentLoadingPolicyLazy10_ThenRecyclingRatioIs10),
("test_GivenPager_WhenContentLoadingPolicyEager_ThenRecyclingRatioIsIntMax", test_GivenPager_WhenContentLoadingPolicyEager_ThenRecyclingRatioIsIntMax)
]
}

0 comments on commit 298378f

Please sign in to comment.