├── demo.gif
├── InfinitePagingSample
├── InfinitePagingSample
│ ├── Assets.xcassets
│ │ ├── Contents.json
│ │ └── AppIcon.appiconset
│ │ │ └── Contents.json
│ ├── Page.swift
│ ├── InfinitePagingSampleApp.swift
│ └── ContentView.swift
├── Package.swift
└── InfinitePagingSample.xcodeproj
│ ├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ └── project.pbxproj
├── .gitignore
├── Sources
└── InfinitePaging
│ ├── PageDirection.swift
│ ├── PageAlignment.swift
│ ├── InfinitePagingView.swift
│ └── InfinitePagingViewModifier.swift
├── Package.swift
├── LICENSE
└── README.md
/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Kyome22/InfinitePaging/HEAD/demo.gif
--------------------------------------------------------------------------------
/InfinitePagingSample/InfinitePagingSample/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Mac
2 | .DS_Store
3 |
4 | # Xcode
5 | xcuserdata/
6 | *.xcuserstate
7 |
8 | # Swift Package Manager
9 | Packages.resolved
10 | .swiftpm/
11 | .build/
12 |
--------------------------------------------------------------------------------
/InfinitePagingSample/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.9
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "",
6 | products: [],
7 | targets: []
8 | )
9 |
--------------------------------------------------------------------------------
/InfinitePagingSample/InfinitePagingSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Sources/InfinitePaging/PageDirection.swift:
--------------------------------------------------------------------------------
1 | /*
2 | PageDirection.swift
3 | InfinitePaging
4 |
5 | Created by Takuto Nakamura on 2023/10/22.
6 | */
7 |
8 | public enum PageDirection: String, CaseIterable {
9 | case backward
10 | case forward
11 | }
12 |
--------------------------------------------------------------------------------
/InfinitePagingSample/InfinitePagingSample/Page.swift:
--------------------------------------------------------------------------------
1 | /*
2 | Page.swift
3 | InfinitePagingSample
4 |
5 | Created by Takuto Nakamura on 2023/10/22.
6 | */
7 |
8 | import Foundation
9 | import InfinitePaging
10 |
11 | struct Page: Pageable {
12 | var id = UUID()
13 | var number: Int
14 | }
15 |
--------------------------------------------------------------------------------
/InfinitePagingSample/InfinitePagingSample/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/InfinitePagingSample/InfinitePagingSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/InfinitePagingSample/InfinitePagingSample/InfinitePagingSampleApp.swift:
--------------------------------------------------------------------------------
1 | /*
2 | InfinitePagingSampleApp.swift
3 | InfinitePagingSample
4 |
5 | Created by Takuto Nakamura on 2023/10/22.
6 | */
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct InfinitePagingSampleApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 6.0
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "InfinitePaging",
7 | platforms: [
8 | .iOS(.v17),
9 | ],
10 | products: [
11 | .library(
12 | name: "InfinitePaging",
13 | targets: ["InfinitePaging"]
14 | ),
15 | ],
16 | targets: [
17 | .target(
18 | name: "InfinitePaging",
19 | swiftSettings: [.enableUpcomingFeature("ExistentialAny")]
20 | ),
21 | ]
22 | )
23 |
--------------------------------------------------------------------------------
/Sources/InfinitePaging/PageAlignment.swift:
--------------------------------------------------------------------------------
1 | /*
2 | PageAlignment.swift
3 | InfinitePaging
4 |
5 | Created by Takuto Nakamura on 2023/11/07.
6 | */
7 |
8 | import SwiftUI
9 |
10 | public enum PageAlignment: String, CaseIterable {
11 | case horizontal
12 | case vertical
13 |
14 | func scalar(_ size: CGSize) -> CGFloat {
15 | switch self {
16 | case .horizontal:
17 | size.width
18 | case .vertical:
19 | size.height
20 | }
21 | }
22 |
23 | func offset(_ value: CGFloat) -> CGSize {
24 | switch self {
25 | case .horizontal:
26 | CGSize(width: value, height: 0)
27 | case .vertical:
28 | CGSize(width: 0, height: value)
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Takuto NAKAMURA (Kyome)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # InfinitePaging
2 |
3 | This provides infinite carousel-like paging view in SwiftUI.
4 |
5 |
6 |
7 | ## Requirements
8 |
9 | - Development with Xcode 16.2+
10 | - Written in Swift 6.0
11 | - Compatible with iOS 17.0+
12 |
13 | ## Usage
14 |
15 | 1. Define a structure conforming to Pageable.
16 |
17 | ```swift
18 | import Foundation
19 | import InfinitePaging
20 |
21 | struct Page: Pageable {
22 | var id = UUID()
23 | var number: Int
24 | }
25 | ```
26 |
27 | 2. Use InfinitePagingView
28 |
29 | ```swift
30 | import SwiftUI
31 | import InfinitePaging
32 |
33 | struct ContentView: View {
34 | // Prepare three elements to display at first.
35 | @State var pages: [Page] = [
36 | Page(number: -1),
37 | Page(number: 0),
38 | Page(number: 1)
39 | ]
40 |
41 | var body: some View {
42 | InfinitePagingView(
43 | objects: $pages,
44 | pageAlignment: .horizontal,
45 | pagingHandler: { paging($0) },
46 | content: { pageView($0) }
47 | )
48 | }
49 |
50 | // Define the View that makes up one page.
51 | private func pageView(_ page: Page) -> some View {
52 | Text(String(page.number))
53 | .font(.largeTitle)
54 | .fontWeight(.bold)
55 | .frame(maxWidth: .infinity, maxHeight: .infinity)
56 | .background(Color.gray)
57 | .clipShape(RoundedRectangle(cornerRadius: 32))
58 | .padding()
59 | }
60 |
61 | // Shifts the array element by one when a paging request comes.
62 | private func paging(_ pageDirection: PageDirection) {
63 | switch pageDirection {
64 | case .backward:
65 | if let number = pages.first?.number {
66 | pages.insert(Page(number: number - 1), at: 0)
67 | pages.removeLast()
68 | }
69 | case .forward:
70 | if let number = pages.last?.number {
71 | pages.append(Page(number: number + 1))
72 | pages.removeFirst()
73 | }
74 | }
75 | }
76 | }
77 | ```
78 |
79 | ## Privacy Manifest
80 |
81 | This library does not collect or track user information, so it does not include a PrivacyInfo.xcprivacy file.
82 |
--------------------------------------------------------------------------------
/InfinitePagingSample/InfinitePagingSample/ContentView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | ContentView.swift
3 | InfinitePagingSample
4 |
5 | Created by Takuto Nakamura on 2023/10/22.
6 | */
7 |
8 | import SwiftUI
9 | import InfinitePaging
10 |
11 | struct ContentView: View {
12 | // Prepare three elements to display at first.
13 | @State var pages: [Page] = [
14 | Page(number: -1),
15 | Page(number: 0),
16 | Page(number: 1)
17 | ]
18 | @State var pageAlignment: PageAlignment = .horizontal
19 |
20 | var body: some View {
21 | VStack {
22 | InfinitePagingView(
23 | objects: $pages,
24 | minimumDistance: 10,
25 | pageAlignment: pageAlignment,
26 | pagingHandler: { paging($0) },
27 | content: { pageView($0) }
28 | )
29 | Picker("Alignment", selection: $pageAlignment) {
30 | ForEach(PageAlignment.allCases) { alignment in
31 | Text(verbatim: alignment.label)
32 | .tag(alignment)
33 | }
34 | }
35 | }
36 | }
37 |
38 | // Define the View that makes up one page.
39 | private func pageView(_ page: Page) -> some View {
40 | Text(String(page.number))
41 | .font(.largeTitle)
42 | .fontWeight(.bold)
43 | .frame(maxWidth: .infinity, maxHeight: .infinity)
44 | .background(Color.gray)
45 | .clipShape(RoundedRectangle(cornerRadius: 32))
46 | .padding()
47 | }
48 |
49 | // Shifts the array element by one when a paging request comes.
50 | private func paging(_ pageDirection: PageDirection) {
51 | switch pageDirection {
52 | case .backward:
53 | if let number = pages.first?.number {
54 | pages.insert(Page(number: number - 1), at: 0)
55 | pages.removeLast()
56 | }
57 | case .forward:
58 | if let number = pages.last?.number {
59 | pages.append(Page(number: number + 1))
60 | pages.removeFirst()
61 | }
62 | }
63 | }
64 | }
65 |
66 | extension PageAlignment: @retroactive Identifiable {
67 | public var id: String { rawValue }
68 | var label: String { rawValue.localizedCapitalized }
69 | }
70 |
71 | #Preview {
72 | ContentView()
73 | }
74 |
--------------------------------------------------------------------------------
/Sources/InfinitePaging/InfinitePagingView.swift:
--------------------------------------------------------------------------------
1 | /*
2 | InfinitePagingView.swift
3 | InfinitePaging
4 |
5 | Created by Takuto Nakamura on 2023/10/22.
6 | */
7 |
8 | import SwiftUI
9 |
10 | public protocol Pageable: Equatable & Identifiable {}
11 |
12 | public struct InfinitePagingView: View {
13 | @Binding var objects: [T]
14 | private let minimumDistance: CGFloat
15 | private let pageAlignment: PageAlignment
16 | private let pagingHandler: (PageDirection) -> Void
17 | private let content: (T) -> Content
18 |
19 | public init(
20 | objects: Binding<[T]>,
21 | minimumDistance: CGFloat = 0,
22 | pageAlignment: PageAlignment,
23 | pagingHandler: @escaping (PageDirection) -> Void,
24 | @ViewBuilder content: @escaping (T) -> Content
25 | ) {
26 | assert(objects.wrappedValue.count == 3, "objects count must be 3.")
27 | _objects = objects
28 | self.minimumDistance = minimumDistance
29 | self.pageAlignment = pageAlignment
30 | self.pagingHandler = pagingHandler
31 | self.content = content
32 | }
33 |
34 | public var body: some View {
35 | GeometryReader { proxy in
36 | Group {
37 | switch pageAlignment {
38 | case .horizontal:
39 | horizontalView(size: proxy.size)
40 | case .vertical:
41 | verticalView(size: proxy.size)
42 | }
43 | }
44 | .modifier(
45 | InfinitePagingViewModifier(
46 | objects: $objects,
47 | pageSize: Binding(
48 | get: { pageAlignment.scalar(proxy.size) },
49 | set: { _ in }
50 | ),
51 | minimumDistance: minimumDistance,
52 | pageAlignment: pageAlignment,
53 | pagingHandler: pagingHandler
54 | )
55 | )
56 | }
57 | .clipped()
58 | .id(pageAlignment)
59 | }
60 |
61 | private func horizontalView(size: CGSize) -> some View {
62 | HStack(alignment: .center, spacing: 0) {
63 | ForEach(objects) { object in
64 | content(object)
65 | .frame(width: size.width, height: size.height)
66 | }
67 | }
68 | }
69 |
70 | private func verticalView(size: CGSize) -> some View {
71 | VStack(alignment: .center, spacing: 0) {
72 | ForEach(objects) { object in
73 | content(object)
74 | .frame(width: size.width, height: size.height)
75 | }
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/Sources/InfinitePaging/InfinitePagingViewModifier.swift:
--------------------------------------------------------------------------------
1 | /*
2 | InfinitePagingViewModifier.swift
3 | InfinitePaging
4 |
5 | Created by Takuto Nakamura on 2023/10/22.
6 | */
7 |
8 | import SwiftUI
9 |
10 | struct InfinitePagingViewModifier: ViewModifier {
11 | @Binding var objects: [T]
12 | @Binding var pageSize: CGFloat
13 | @State var pagingOffset: CGFloat
14 | @State var draggingOffset: CGFloat
15 | private let minimumDistance: CGFloat
16 | private let pageAlignment: PageAlignment
17 | private let pagingHandler: (PageDirection) -> Void
18 |
19 | var dragGesture: some Gesture {
20 | DragGesture(minimumDistance: minimumDistance)
21 | .onChanged { value in
22 | draggingOffset = pageAlignment.scalar(value.translation)
23 | }
24 | .onEnded { value in
25 | let oldIndex = Int(floor(0.5 - (pagingOffset / pageSize)))
26 | pagingOffset += pageAlignment.scalar(value.translation)
27 | draggingOffset = 0
28 | let predicatedOffset = pageAlignment.scalar(value.predictedEndTranslation)
29 | let newIndex = Int(max(0, min(2, round(1 - predicatedOffset / pageSize))))
30 | withAnimation(.smooth(duration: 0.1)) {
31 | pagingOffset = -pageSize * CGFloat(newIndex)
32 | } completion: {
33 | if newIndex == oldIndex { return }
34 | if newIndex == 0 {
35 | pagingHandler(.backward)
36 | }
37 | if newIndex == 2 {
38 | pagingHandler(.forward)
39 | }
40 | }
41 | }
42 | }
43 |
44 | init(
45 | objects: Binding<[T]>,
46 | pageSize: Binding,
47 | minimumDistance: CGFloat,
48 | pageAlignment: PageAlignment,
49 | pagingHandler: @escaping (PageDirection) -> Void
50 | ) {
51 | _objects = objects
52 | _pageSize = pageSize
53 | _pagingOffset = State(initialValue: -pageSize.wrappedValue)
54 | _draggingOffset = State(initialValue: 0)
55 | self.minimumDistance = minimumDistance
56 | self.pageAlignment = pageAlignment
57 | self.pagingHandler = pagingHandler
58 | }
59 |
60 | func body(content: Content) -> some View {
61 | content
62 | .offset(pageAlignment.offset(pagingOffset + draggingOffset))
63 | .simultaneousGesture(dragGesture)
64 | .onChange(of: objects) { _, _ in
65 | pagingOffset = -pageSize
66 | }
67 | .onChange(of: pageSize) { _, _ in
68 | pagingOffset = -pageSize
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/InfinitePagingSample/InfinitePagingSample.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 77;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 1C9449E02B71F07A009A3C30 /* InfinitePaging in Frameworks */ = {isa = PBXBuildFile; productRef = 1C9449DF2B71F07A009A3C30 /* InfinitePaging */; };
11 | 1CE66B8C2AE4F70F00AC612D /* InfinitePagingSampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CE66B8B2AE4F70F00AC612D /* InfinitePagingSampleApp.swift */; };
12 | 1CE66B8E2AE4F70F00AC612D /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CE66B8D2AE4F70F00AC612D /* ContentView.swift */; };
13 | 1CE66B902AE4F71000AC612D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1CE66B8F2AE4F71000AC612D /* Assets.xcassets */; };
14 | 1CE66B9D2AE4F7CB00AC612D /* Page.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CE66B9C2AE4F7CB00AC612D /* Page.swift */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXFileReference section */
18 | 1C9449DD2B71F06D009A3C30 /* InfinitePaging */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = InfinitePaging; path = ..; sourceTree = ""; };
19 | 1CE66B882AE4F70F00AC612D /* InfinitePagingSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = InfinitePagingSample.app; sourceTree = BUILT_PRODUCTS_DIR; };
20 | 1CE66B8B2AE4F70F00AC612D /* InfinitePagingSampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfinitePagingSampleApp.swift; sourceTree = ""; };
21 | 1CE66B8D2AE4F70F00AC612D /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
22 | 1CE66B8F2AE4F71000AC612D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
23 | 1CE66B9C2AE4F7CB00AC612D /* Page.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Page.swift; sourceTree = ""; };
24 | /* End PBXFileReference section */
25 |
26 | /* Begin PBXFrameworksBuildPhase section */
27 | 1CE66B852AE4F70F00AC612D /* Frameworks */ = {
28 | isa = PBXFrameworksBuildPhase;
29 | buildActionMask = 2147483647;
30 | files = (
31 | 1C9449E02B71F07A009A3C30 /* InfinitePaging in Frameworks */,
32 | );
33 | runOnlyForDeploymentPostprocessing = 0;
34 | };
35 | /* End PBXFrameworksBuildPhase section */
36 |
37 | /* Begin PBXGroup section */
38 | 1C9449DE2B71F07A009A3C30 /* Frameworks */ = {
39 | isa = PBXGroup;
40 | children = (
41 | );
42 | name = Frameworks;
43 | sourceTree = "";
44 | };
45 | 1CE66B7F2AE4F70F00AC612D = {
46 | isa = PBXGroup;
47 | children = (
48 | 1C9449DD2B71F06D009A3C30 /* InfinitePaging */,
49 | 1CE66B8A2AE4F70F00AC612D /* InfinitePagingSample */,
50 | 1CE66B892AE4F70F00AC612D /* Products */,
51 | 1C9449DE2B71F07A009A3C30 /* Frameworks */,
52 | );
53 | sourceTree = "";
54 | };
55 | 1CE66B892AE4F70F00AC612D /* Products */ = {
56 | isa = PBXGroup;
57 | children = (
58 | 1CE66B882AE4F70F00AC612D /* InfinitePagingSample.app */,
59 | );
60 | name = Products;
61 | sourceTree = "";
62 | };
63 | 1CE66B8A2AE4F70F00AC612D /* InfinitePagingSample */ = {
64 | isa = PBXGroup;
65 | children = (
66 | 1CE66B8B2AE4F70F00AC612D /* InfinitePagingSampleApp.swift */,
67 | 1CE66B8D2AE4F70F00AC612D /* ContentView.swift */,
68 | 1CE66B9C2AE4F7CB00AC612D /* Page.swift */,
69 | 1CE66B8F2AE4F71000AC612D /* Assets.xcassets */,
70 | );
71 | path = InfinitePagingSample;
72 | sourceTree = "";
73 | };
74 | /* End PBXGroup section */
75 |
76 | /* Begin PBXNativeTarget section */
77 | 1CE66B872AE4F70F00AC612D /* InfinitePagingSample */ = {
78 | isa = PBXNativeTarget;
79 | buildConfigurationList = 1CE66B962AE4F71000AC612D /* Build configuration list for PBXNativeTarget "InfinitePagingSample" */;
80 | buildPhases = (
81 | 1CE66B842AE4F70F00AC612D /* Sources */,
82 | 1CE66B852AE4F70F00AC612D /* Frameworks */,
83 | 1CE66B862AE4F70F00AC612D /* Resources */,
84 | );
85 | buildRules = (
86 | );
87 | dependencies = (
88 | );
89 | name = InfinitePagingSample;
90 | packageProductDependencies = (
91 | 1C9449DF2B71F07A009A3C30 /* InfinitePaging */,
92 | );
93 | productName = InfinitePagingSample;
94 | productReference = 1CE66B882AE4F70F00AC612D /* InfinitePagingSample.app */;
95 | productType = "com.apple.product-type.application";
96 | };
97 | /* End PBXNativeTarget section */
98 |
99 | /* Begin PBXProject section */
100 | 1CE66B802AE4F70F00AC612D /* Project object */ = {
101 | isa = PBXProject;
102 | attributes = {
103 | BuildIndependentTargetsInParallel = 1;
104 | LastSwiftUpdateCheck = 1500;
105 | LastUpgradeCheck = 1500;
106 | TargetAttributes = {
107 | 1CE66B872AE4F70F00AC612D = {
108 | CreatedOnToolsVersion = 15.0.1;
109 | };
110 | };
111 | };
112 | buildConfigurationList = 1CE66B832AE4F70F00AC612D /* Build configuration list for PBXProject "InfinitePagingSample" */;
113 | developmentRegion = en;
114 | hasScannedForEncodings = 0;
115 | knownRegions = (
116 | en,
117 | Base,
118 | );
119 | mainGroup = 1CE66B7F2AE4F70F00AC612D;
120 | packageReferences = (
121 | );
122 | preferredProjectObjectVersion = 77;
123 | productRefGroup = 1CE66B892AE4F70F00AC612D /* Products */;
124 | projectDirPath = "";
125 | projectRoot = "";
126 | targets = (
127 | 1CE66B872AE4F70F00AC612D /* InfinitePagingSample */,
128 | );
129 | };
130 | /* End PBXProject section */
131 |
132 | /* Begin PBXResourcesBuildPhase section */
133 | 1CE66B862AE4F70F00AC612D /* Resources */ = {
134 | isa = PBXResourcesBuildPhase;
135 | buildActionMask = 2147483647;
136 | files = (
137 | 1CE66B902AE4F71000AC612D /* Assets.xcassets in Resources */,
138 | );
139 | runOnlyForDeploymentPostprocessing = 0;
140 | };
141 | /* End PBXResourcesBuildPhase section */
142 |
143 | /* Begin PBXSourcesBuildPhase section */
144 | 1CE66B842AE4F70F00AC612D /* Sources */ = {
145 | isa = PBXSourcesBuildPhase;
146 | buildActionMask = 2147483647;
147 | files = (
148 | 1CE66B8E2AE4F70F00AC612D /* ContentView.swift in Sources */,
149 | 1CE66B8C2AE4F70F00AC612D /* InfinitePagingSampleApp.swift in Sources */,
150 | 1CE66B9D2AE4F7CB00AC612D /* Page.swift in Sources */,
151 | );
152 | runOnlyForDeploymentPostprocessing = 0;
153 | };
154 | /* End PBXSourcesBuildPhase section */
155 |
156 | /* Begin XCBuildConfiguration section */
157 | 1CE66B942AE4F71000AC612D /* Debug */ = {
158 | isa = XCBuildConfiguration;
159 | buildSettings = {
160 | ALWAYS_SEARCH_USER_PATHS = NO;
161 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
162 | CLANG_ANALYZER_NONNULL = YES;
163 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
164 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
165 | CLANG_ENABLE_MODULES = YES;
166 | CLANG_ENABLE_OBJC_ARC = YES;
167 | CLANG_ENABLE_OBJC_WEAK = YES;
168 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
169 | CLANG_WARN_BOOL_CONVERSION = YES;
170 | CLANG_WARN_COMMA = YES;
171 | CLANG_WARN_CONSTANT_CONVERSION = YES;
172 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
173 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
174 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
175 | CLANG_WARN_EMPTY_BODY = YES;
176 | CLANG_WARN_ENUM_CONVERSION = YES;
177 | CLANG_WARN_INFINITE_RECURSION = YES;
178 | CLANG_WARN_INT_CONVERSION = YES;
179 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
180 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
181 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
182 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
183 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
184 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
185 | CLANG_WARN_STRICT_PROTOTYPES = YES;
186 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
187 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
188 | CLANG_WARN_UNREACHABLE_CODE = YES;
189 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
190 | COPY_PHASE_STRIP = NO;
191 | DEBUG_INFORMATION_FORMAT = dwarf;
192 | ENABLE_STRICT_OBJC_MSGSEND = YES;
193 | ENABLE_TESTABILITY = YES;
194 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
195 | GCC_C_LANGUAGE_STANDARD = gnu17;
196 | GCC_DYNAMIC_NO_PIC = NO;
197 | GCC_NO_COMMON_BLOCKS = YES;
198 | GCC_OPTIMIZATION_LEVEL = 0;
199 | GCC_PREPROCESSOR_DEFINITIONS = (
200 | "DEBUG=1",
201 | "$(inherited)",
202 | );
203 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
204 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
205 | GCC_WARN_UNDECLARED_SELECTOR = YES;
206 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
207 | GCC_WARN_UNUSED_FUNCTION = YES;
208 | GCC_WARN_UNUSED_VARIABLE = YES;
209 | IPHONEOS_DEPLOYMENT_TARGET = 17.6;
210 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
211 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
212 | MTL_FAST_MATH = YES;
213 | ONLY_ACTIVE_ARCH = YES;
214 | SDKROOT = iphoneos;
215 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
216 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
217 | };
218 | name = Debug;
219 | };
220 | 1CE66B952AE4F71000AC612D /* Release */ = {
221 | isa = XCBuildConfiguration;
222 | buildSettings = {
223 | ALWAYS_SEARCH_USER_PATHS = NO;
224 | ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
225 | CLANG_ANALYZER_NONNULL = YES;
226 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
227 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
228 | CLANG_ENABLE_MODULES = YES;
229 | CLANG_ENABLE_OBJC_ARC = YES;
230 | CLANG_ENABLE_OBJC_WEAK = YES;
231 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
232 | CLANG_WARN_BOOL_CONVERSION = YES;
233 | CLANG_WARN_COMMA = YES;
234 | CLANG_WARN_CONSTANT_CONVERSION = YES;
235 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
236 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
237 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
238 | CLANG_WARN_EMPTY_BODY = YES;
239 | CLANG_WARN_ENUM_CONVERSION = YES;
240 | CLANG_WARN_INFINITE_RECURSION = YES;
241 | CLANG_WARN_INT_CONVERSION = YES;
242 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
243 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
244 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
245 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
246 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
247 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
248 | CLANG_WARN_STRICT_PROTOTYPES = YES;
249 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
250 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
251 | CLANG_WARN_UNREACHABLE_CODE = YES;
252 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
253 | COPY_PHASE_STRIP = NO;
254 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
255 | ENABLE_NS_ASSERTIONS = NO;
256 | ENABLE_STRICT_OBJC_MSGSEND = YES;
257 | ENABLE_USER_SCRIPT_SANDBOXING = YES;
258 | GCC_C_LANGUAGE_STANDARD = gnu17;
259 | GCC_NO_COMMON_BLOCKS = YES;
260 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
261 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
262 | GCC_WARN_UNDECLARED_SELECTOR = YES;
263 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
264 | GCC_WARN_UNUSED_FUNCTION = YES;
265 | GCC_WARN_UNUSED_VARIABLE = YES;
266 | IPHONEOS_DEPLOYMENT_TARGET = 17.6;
267 | LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
268 | MTL_ENABLE_DEBUG_INFO = NO;
269 | MTL_FAST_MATH = YES;
270 | SDKROOT = iphoneos;
271 | SWIFT_COMPILATION_MODE = wholemodule;
272 | VALIDATE_PRODUCT = YES;
273 | };
274 | name = Release;
275 | };
276 | 1CE66B972AE4F71000AC612D /* Debug */ = {
277 | isa = XCBuildConfiguration;
278 | buildSettings = {
279 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
280 | CODE_SIGN_STYLE = Automatic;
281 | CURRENT_PROJECT_VERSION = 1;
282 | DEVELOPMENT_TEAM = VJ5N2X84K8;
283 | ENABLE_PREVIEWS = YES;
284 | GENERATE_INFOPLIST_FILE = YES;
285 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
286 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
287 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
288 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
289 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
290 | LD_RUNPATH_SEARCH_PATHS = (
291 | "$(inherited)",
292 | "@executable_path/Frameworks",
293 | );
294 | MARKETING_VERSION = 1.0;
295 | PRODUCT_BUNDLE_IDENTIFIER = com.kyome.InfinitePagingSample;
296 | PRODUCT_NAME = "$(TARGET_NAME)";
297 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
298 | SUPPORTS_MACCATALYST = NO;
299 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
300 | SWIFT_EMIT_LOC_STRINGS = YES;
301 | SWIFT_VERSION = 6.0;
302 | TARGETED_DEVICE_FAMILY = "1,2";
303 | };
304 | name = Debug;
305 | };
306 | 1CE66B982AE4F71000AC612D /* Release */ = {
307 | isa = XCBuildConfiguration;
308 | buildSettings = {
309 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
310 | CODE_SIGN_STYLE = Automatic;
311 | CURRENT_PROJECT_VERSION = 1;
312 | DEVELOPMENT_TEAM = VJ5N2X84K8;
313 | ENABLE_PREVIEWS = YES;
314 | GENERATE_INFOPLIST_FILE = YES;
315 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
316 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
317 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
318 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
319 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
320 | LD_RUNPATH_SEARCH_PATHS = (
321 | "$(inherited)",
322 | "@executable_path/Frameworks",
323 | );
324 | MARKETING_VERSION = 1.0;
325 | PRODUCT_BUNDLE_IDENTIFIER = com.kyome.InfinitePagingSample;
326 | PRODUCT_NAME = "$(TARGET_NAME)";
327 | SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
328 | SUPPORTS_MACCATALYST = NO;
329 | SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
330 | SWIFT_EMIT_LOC_STRINGS = YES;
331 | SWIFT_VERSION = 6.0;
332 | TARGETED_DEVICE_FAMILY = "1,2";
333 | };
334 | name = Release;
335 | };
336 | /* End XCBuildConfiguration section */
337 |
338 | /* Begin XCConfigurationList section */
339 | 1CE66B832AE4F70F00AC612D /* Build configuration list for PBXProject "InfinitePagingSample" */ = {
340 | isa = XCConfigurationList;
341 | buildConfigurations = (
342 | 1CE66B942AE4F71000AC612D /* Debug */,
343 | 1CE66B952AE4F71000AC612D /* Release */,
344 | );
345 | defaultConfigurationIsVisible = 0;
346 | defaultConfigurationName = Release;
347 | };
348 | 1CE66B962AE4F71000AC612D /* Build configuration list for PBXNativeTarget "InfinitePagingSample" */ = {
349 | isa = XCConfigurationList;
350 | buildConfigurations = (
351 | 1CE66B972AE4F71000AC612D /* Debug */,
352 | 1CE66B982AE4F71000AC612D /* Release */,
353 | );
354 | defaultConfigurationIsVisible = 0;
355 | defaultConfigurationName = Release;
356 | };
357 | /* End XCConfigurationList section */
358 |
359 | /* Begin XCSwiftPackageProductDependency section */
360 | 1C9449DF2B71F07A009A3C30 /* InfinitePaging */ = {
361 | isa = XCSwiftPackageProductDependency;
362 | productName = InfinitePaging;
363 | };
364 | /* End XCSwiftPackageProductDependency section */
365 | };
366 | rootObject = 1CE66B802AE4F70F00AC612D /* Project object */;
367 | }
368 |
--------------------------------------------------------------------------------