├── 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 | --------------------------------------------------------------------------------