├── .gitignore ├── LoadMoreExample.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── johncodeos.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── johncodeos.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── LoadMoreExample ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── 1024.png │ │ ├── 120.png │ │ ├── 152.png │ │ ├── 167.png │ │ ├── 180.png │ │ ├── 20.png │ │ ├── 29.png │ │ ├── 40.png │ │ ├── 58.png │ │ ├── 60.png │ │ ├── 76.png │ │ ├── 80.png │ │ ├── 87.png │ │ └── Contents.json │ ├── Contents.json │ ├── collectionview.imageset │ │ ├── Contents.json │ │ ├── collectionview.png │ │ ├── collectionview@2x.png │ │ └── collectionview@3x.png │ ├── primaryColor.colorset │ │ └── Contents.json │ ├── secondaryColor.colorset │ │ └── Contents.json │ └── tableview.imageset │ │ ├── Contents.json │ │ ├── tableview.png │ │ ├── tableview@2x.png │ │ └── tableview@3x.png ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── CollectionView │ ├── CollectionView.swift │ ├── CollectionViewItemCell │ │ ├── CollectionViewItemCell.swift │ │ └── CollectionViewItemCell.xib │ └── LoadingReusableView │ │ ├── LoadingReusableView.swift │ │ └── LoadingReusableView.xib ├── Info.plist ├── MainViewController.swift ├── Supporting Files │ ├── AppDelegate.swift │ ├── CustomLayout.swift │ └── SceneDelegate.swift └── TableView │ ├── LoadingCell │ ├── LoadingCell.swift │ └── LoadingCell.xib │ ├── TableView.swift │ └── TableViewItemCell │ ├── TableViewItemCell.swift │ └── TableViewItemCell.xib └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | *.xcuserdata 20 | *.generated.swift 21 | 22 | ## Other 23 | *.moved-aside 24 | *.xccheckout 25 | *.xcscmblueprint 26 | .DS_Store 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | *.ipa 31 | *.dSYM.zip 32 | *.dSYM 33 | 34 | ## Playgrounds 35 | timeline.xctimeline 36 | playground.xcworkspace 37 | 38 | # Swift Package Manager 39 | # 40 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 41 | # Packages/ 42 | # Package.pins 43 | # Package.resolved 44 | .build/ 45 | 46 | # CocoaPods 47 | # 48 | # We recommend against adding the Pods directory to your .gitignore. However 49 | # you should judge for yourself, the pros and cons are mentioned at: 50 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 51 | # 52 | Pods/ 53 | # 54 | # Add this line if you want to avoid checking in source code from the Xcode workspace 55 | # *.xcworkspace 56 | 57 | # Carthage 58 | # 59 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 60 | # Carthage/Checkouts 61 | 62 | Carthage/Build 63 | 64 | # fastlane 65 | # 66 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 67 | # screenshots whenever they are needed. 68 | # For more information about the recommended setup visit: 69 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 70 | 71 | fastlane/report.xml 72 | fastlane/Preview.html 73 | fastlane/screenshots/**/*.png 74 | fastlane/test_output 75 | 76 | # Code Injection 77 | # 78 | # After new code Injection tools there's a generated folder /iOSInjectionProject 79 | # https://github.com/johnno1962/injectionforxcode 80 | 81 | iOSInjectionProject/.DS_Store 82 | -------------------------------------------------------------------------------- /LoadMoreExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | C2070721234F682800CACE2C /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2070720234F682800CACE2C /* AppDelegate.swift */; }; 11 | C2070723234F682800CACE2C /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2070722234F682800CACE2C /* SceneDelegate.swift */; }; 12 | C2070725234F682800CACE2C /* MainViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2070724234F682800CACE2C /* MainViewController.swift */; }; 13 | C2070728234F682800CACE2C /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C2070726234F682800CACE2C /* Main.storyboard */; }; 14 | C207072A234F682A00CACE2C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C2070729234F682A00CACE2C /* Assets.xcassets */; }; 15 | C207072D234F682A00CACE2C /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C207072B234F682A00CACE2C /* LaunchScreen.storyboard */; }; 16 | C207073C234F7CC600CACE2C /* TableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C207073B234F7CC600CACE2C /* TableView.swift */; }; 17 | C21352BA2354CAED0091FC61 /* TableViewItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C21352B82354CAED0091FC61 /* TableViewItemCell.swift */; }; 18 | C21352BB2354CAED0091FC61 /* TableViewItemCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C21352B92354CAED0091FC61 /* TableViewItemCell.xib */; }; 19 | C21352C12354CC8C0091FC61 /* CollectionViewItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C21352BF2354CC8C0091FC61 /* CollectionViewItemCell.swift */; }; 20 | C21352C22354CC8C0091FC61 /* CollectionViewItemCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C21352C02354CC8C0091FC61 /* CollectionViewItemCell.xib */; }; 21 | C21352C92354D2D80091FC61 /* LoadingReusableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C21352C72354D2D80091FC61 /* LoadingReusableView.swift */; }; 22 | C21352CA2354D2D80091FC61 /* LoadingReusableView.xib in Resources */ = {isa = PBXBuildFile; fileRef = C21352C82354D2D80091FC61 /* LoadingReusableView.xib */; }; 23 | C21352CC2354D6480091FC61 /* CustomLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = C21352CB2354D6480091FC61 /* CustomLayout.swift */; }; 24 | C2BCCA49235278E600AAC36E /* LoadingCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2BCCA47235278E600AAC36E /* LoadingCell.swift */; }; 25 | C2BCCA4A235278E600AAC36E /* LoadingCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = C2BCCA48235278E600AAC36E /* LoadingCell.xib */; }; 26 | C2DDE688234FC3DF005FFBD1 /* CollectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C2DDE687234FC3DF005FFBD1 /* CollectionView.swift */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | C207071D234F682800CACE2C /* LoadMoreExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = LoadMoreExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | C2070720234F682800CACE2C /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 32 | C2070722234F682800CACE2C /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 33 | C2070724234F682800CACE2C /* MainViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewController.swift; sourceTree = ""; }; 34 | C2070727234F682800CACE2C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 35 | C2070729234F682A00CACE2C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 36 | C207072C234F682A00CACE2C /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 37 | C207072E234F682A00CACE2C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 38 | C207073B234F7CC600CACE2C /* TableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableView.swift; sourceTree = ""; }; 39 | C21352B82354CAED0091FC61 /* TableViewItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TableViewItemCell.swift; sourceTree = ""; }; 40 | C21352B92354CAED0091FC61 /* TableViewItemCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TableViewItemCell.xib; sourceTree = ""; }; 41 | C21352BF2354CC8C0091FC61 /* CollectionViewItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionViewItemCell.swift; sourceTree = ""; }; 42 | C21352C02354CC8C0091FC61 /* CollectionViewItemCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = CollectionViewItemCell.xib; sourceTree = ""; }; 43 | C21352C72354D2D80091FC61 /* LoadingReusableView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingReusableView.swift; sourceTree = ""; }; 44 | C21352C82354D2D80091FC61 /* LoadingReusableView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoadingReusableView.xib; sourceTree = ""; }; 45 | C21352CB2354D6480091FC61 /* CustomLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomLayout.swift; sourceTree = ""; }; 46 | C2BCCA47235278E600AAC36E /* LoadingCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoadingCell.swift; sourceTree = ""; }; 47 | C2BCCA48235278E600AAC36E /* LoadingCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LoadingCell.xib; sourceTree = ""; }; 48 | C2DDE687234FC3DF005FFBD1 /* CollectionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CollectionView.swift; sourceTree = ""; }; 49 | /* End PBXFileReference section */ 50 | 51 | /* Begin PBXFrameworksBuildPhase section */ 52 | C207071A234F682800CACE2C /* Frameworks */ = { 53 | isa = PBXFrameworksBuildPhase; 54 | buildActionMask = 2147483647; 55 | files = ( 56 | ); 57 | runOnlyForDeploymentPostprocessing = 0; 58 | }; 59 | /* End PBXFrameworksBuildPhase section */ 60 | 61 | /* Begin PBXGroup section */ 62 | C2070714234F682800CACE2C = { 63 | isa = PBXGroup; 64 | children = ( 65 | C207071F234F682800CACE2C /* LoadMoreExample */, 66 | C207071E234F682800CACE2C /* Products */, 67 | ); 68 | sourceTree = ""; 69 | }; 70 | C207071E234F682800CACE2C /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | C207071D234F682800CACE2C /* LoadMoreExample.app */, 74 | ); 75 | name = Products; 76 | sourceTree = ""; 77 | }; 78 | C207071F234F682800CACE2C /* LoadMoreExample */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | C21352CD2354D6970091FC61 /* Supporting Files */, 82 | C2EA1F2E235604EC00A8729D /* CollectionView */, 83 | C2EA1F2F2356051D00A8729D /* TableView */, 84 | C2070724234F682800CACE2C /* MainViewController.swift */, 85 | C2070726234F682800CACE2C /* Main.storyboard */, 86 | C2070729234F682A00CACE2C /* Assets.xcassets */, 87 | C207072B234F682A00CACE2C /* LaunchScreen.storyboard */, 88 | C207072E234F682A00CACE2C /* Info.plist */, 89 | ); 90 | path = LoadMoreExample; 91 | sourceTree = ""; 92 | }; 93 | C21352BC2354CAF00091FC61 /* TableViewItemCell */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | C21352B82354CAED0091FC61 /* TableViewItemCell.swift */, 97 | C21352B92354CAED0091FC61 /* TableViewItemCell.xib */, 98 | ); 99 | path = TableViewItemCell; 100 | sourceTree = ""; 101 | }; 102 | C21352BD2354CC690091FC61 /* CollectionViewItemCell */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | C21352BF2354CC8C0091FC61 /* CollectionViewItemCell.swift */, 106 | C21352C02354CC8C0091FC61 /* CollectionViewItemCell.xib */, 107 | ); 108 | path = CollectionViewItemCell; 109 | sourceTree = ""; 110 | }; 111 | C21352BE2354CC710091FC61 /* LoadingReusableView */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | C21352C72354D2D80091FC61 /* LoadingReusableView.swift */, 115 | C21352C82354D2D80091FC61 /* LoadingReusableView.xib */, 116 | ); 117 | path = LoadingReusableView; 118 | sourceTree = ""; 119 | }; 120 | C21352CD2354D6970091FC61 /* Supporting Files */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | C2070720234F682800CACE2C /* AppDelegate.swift */, 124 | C2070722234F682800CACE2C /* SceneDelegate.swift */, 125 | C21352CB2354D6480091FC61 /* CustomLayout.swift */, 126 | ); 127 | path = "Supporting Files"; 128 | sourceTree = ""; 129 | }; 130 | C2BCCA4B235278EF00AAC36E /* LoadingCell */ = { 131 | isa = PBXGroup; 132 | children = ( 133 | C2BCCA47235278E600AAC36E /* LoadingCell.swift */, 134 | C2BCCA48235278E600AAC36E /* LoadingCell.xib */, 135 | ); 136 | path = LoadingCell; 137 | sourceTree = ""; 138 | }; 139 | C2EA1F2E235604EC00A8729D /* CollectionView */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | C21352BE2354CC710091FC61 /* LoadingReusableView */, 143 | C21352BD2354CC690091FC61 /* CollectionViewItemCell */, 144 | C2DDE687234FC3DF005FFBD1 /* CollectionView.swift */, 145 | ); 146 | path = CollectionView; 147 | sourceTree = ""; 148 | }; 149 | C2EA1F2F2356051D00A8729D /* TableView */ = { 150 | isa = PBXGroup; 151 | children = ( 152 | C21352BC2354CAF00091FC61 /* TableViewItemCell */, 153 | C2BCCA4B235278EF00AAC36E /* LoadingCell */, 154 | C207073B234F7CC600CACE2C /* TableView.swift */, 155 | ); 156 | path = TableView; 157 | sourceTree = ""; 158 | }; 159 | /* End PBXGroup section */ 160 | 161 | /* Begin PBXNativeTarget section */ 162 | C207071C234F682800CACE2C /* LoadMoreExample */ = { 163 | isa = PBXNativeTarget; 164 | buildConfigurationList = C2070731234F682A00CACE2C /* Build configuration list for PBXNativeTarget "LoadMoreExample" */; 165 | buildPhases = ( 166 | C2070719234F682800CACE2C /* Sources */, 167 | C207071A234F682800CACE2C /* Frameworks */, 168 | C207071B234F682800CACE2C /* Resources */, 169 | ); 170 | buildRules = ( 171 | ); 172 | dependencies = ( 173 | ); 174 | name = LoadMoreExample; 175 | productName = LoadMoreExample; 176 | productReference = C207071D234F682800CACE2C /* LoadMoreExample.app */; 177 | productType = "com.apple.product-type.application"; 178 | }; 179 | /* End PBXNativeTarget section */ 180 | 181 | /* Begin PBXProject section */ 182 | C2070715234F682800CACE2C /* Project object */ = { 183 | isa = PBXProject; 184 | attributes = { 185 | LastSwiftUpdateCheck = 1120; 186 | LastUpgradeCheck = 1120; 187 | ORGANIZATIONNAME = "John Codeos"; 188 | TargetAttributes = { 189 | C207071C234F682800CACE2C = { 190 | CreatedOnToolsVersion = 11.2; 191 | }; 192 | }; 193 | }; 194 | buildConfigurationList = C2070718234F682800CACE2C /* Build configuration list for PBXProject "LoadMoreExample" */; 195 | compatibilityVersion = "Xcode 9.3"; 196 | developmentRegion = en; 197 | hasScannedForEncodings = 0; 198 | knownRegions = ( 199 | en, 200 | Base, 201 | ); 202 | mainGroup = C2070714234F682800CACE2C; 203 | productRefGroup = C207071E234F682800CACE2C /* Products */; 204 | projectDirPath = ""; 205 | projectRoot = ""; 206 | targets = ( 207 | C207071C234F682800CACE2C /* LoadMoreExample */, 208 | ); 209 | }; 210 | /* End PBXProject section */ 211 | 212 | /* Begin PBXResourcesBuildPhase section */ 213 | C207071B234F682800CACE2C /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | C21352CA2354D2D80091FC61 /* LoadingReusableView.xib in Resources */, 218 | C207072D234F682A00CACE2C /* LaunchScreen.storyboard in Resources */, 219 | C21352BB2354CAED0091FC61 /* TableViewItemCell.xib in Resources */, 220 | C21352C22354CC8C0091FC61 /* CollectionViewItemCell.xib in Resources */, 221 | C207072A234F682A00CACE2C /* Assets.xcassets in Resources */, 222 | C2BCCA4A235278E600AAC36E /* LoadingCell.xib in Resources */, 223 | C2070728234F682800CACE2C /* Main.storyboard in Resources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXResourcesBuildPhase section */ 228 | 229 | /* Begin PBXSourcesBuildPhase section */ 230 | C2070719234F682800CACE2C /* Sources */ = { 231 | isa = PBXSourcesBuildPhase; 232 | buildActionMask = 2147483647; 233 | files = ( 234 | C21352C12354CC8C0091FC61 /* CollectionViewItemCell.swift in Sources */, 235 | C2DDE688234FC3DF005FFBD1 /* CollectionView.swift in Sources */, 236 | C21352C92354D2D80091FC61 /* LoadingReusableView.swift in Sources */, 237 | C21352CC2354D6480091FC61 /* CustomLayout.swift in Sources */, 238 | C207073C234F7CC600CACE2C /* TableView.swift in Sources */, 239 | C21352BA2354CAED0091FC61 /* TableViewItemCell.swift in Sources */, 240 | C2070725234F682800CACE2C /* MainViewController.swift in Sources */, 241 | C2BCCA49235278E600AAC36E /* LoadingCell.swift in Sources */, 242 | C2070721234F682800CACE2C /* AppDelegate.swift in Sources */, 243 | C2070723234F682800CACE2C /* SceneDelegate.swift in Sources */, 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | /* End PBXSourcesBuildPhase section */ 248 | 249 | /* Begin PBXVariantGroup section */ 250 | C2070726234F682800CACE2C /* Main.storyboard */ = { 251 | isa = PBXVariantGroup; 252 | children = ( 253 | C2070727234F682800CACE2C /* Base */, 254 | ); 255 | name = Main.storyboard; 256 | sourceTree = ""; 257 | }; 258 | C207072B234F682A00CACE2C /* LaunchScreen.storyboard */ = { 259 | isa = PBXVariantGroup; 260 | children = ( 261 | C207072C234F682A00CACE2C /* Base */, 262 | ); 263 | name = LaunchScreen.storyboard; 264 | sourceTree = ""; 265 | }; 266 | /* End PBXVariantGroup section */ 267 | 268 | /* Begin XCBuildConfiguration section */ 269 | C207072F234F682A00CACE2C /* Debug */ = { 270 | isa = XCBuildConfiguration; 271 | buildSettings = { 272 | ALWAYS_SEARCH_USER_PATHS = NO; 273 | CLANG_ANALYZER_NONNULL = YES; 274 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 275 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 276 | CLANG_CXX_LIBRARY = "libc++"; 277 | CLANG_ENABLE_MODULES = YES; 278 | CLANG_ENABLE_OBJC_ARC = YES; 279 | CLANG_ENABLE_OBJC_WEAK = YES; 280 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 281 | CLANG_WARN_BOOL_CONVERSION = YES; 282 | CLANG_WARN_COMMA = YES; 283 | CLANG_WARN_CONSTANT_CONVERSION = YES; 284 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 285 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 286 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 287 | CLANG_WARN_EMPTY_BODY = YES; 288 | CLANG_WARN_ENUM_CONVERSION = YES; 289 | CLANG_WARN_INFINITE_RECURSION = YES; 290 | CLANG_WARN_INT_CONVERSION = YES; 291 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 292 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 293 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 294 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 295 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 296 | CLANG_WARN_STRICT_PROTOTYPES = YES; 297 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 298 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 299 | CLANG_WARN_UNREACHABLE_CODE = YES; 300 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 301 | COPY_PHASE_STRIP = NO; 302 | DEBUG_INFORMATION_FORMAT = dwarf; 303 | ENABLE_STRICT_OBJC_MSGSEND = YES; 304 | ENABLE_TESTABILITY = YES; 305 | GCC_C_LANGUAGE_STANDARD = gnu11; 306 | GCC_DYNAMIC_NO_PIC = NO; 307 | GCC_NO_COMMON_BLOCKS = YES; 308 | GCC_OPTIMIZATION_LEVEL = 0; 309 | GCC_PREPROCESSOR_DEFINITIONS = ( 310 | "DEBUG=1", 311 | "$(inherited)", 312 | ); 313 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 314 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 315 | GCC_WARN_UNDECLARED_SELECTOR = YES; 316 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 317 | GCC_WARN_UNUSED_FUNCTION = YES; 318 | GCC_WARN_UNUSED_VARIABLE = YES; 319 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 320 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 321 | MTL_FAST_MATH = YES; 322 | ONLY_ACTIVE_ARCH = YES; 323 | SDKROOT = iphoneos; 324 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 325 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 326 | }; 327 | name = Debug; 328 | }; 329 | C2070730234F682A00CACE2C /* Release */ = { 330 | isa = XCBuildConfiguration; 331 | buildSettings = { 332 | ALWAYS_SEARCH_USER_PATHS = NO; 333 | CLANG_ANALYZER_NONNULL = YES; 334 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 335 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 336 | CLANG_CXX_LIBRARY = "libc++"; 337 | CLANG_ENABLE_MODULES = YES; 338 | CLANG_ENABLE_OBJC_ARC = YES; 339 | CLANG_ENABLE_OBJC_WEAK = YES; 340 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 341 | CLANG_WARN_BOOL_CONVERSION = YES; 342 | CLANG_WARN_COMMA = YES; 343 | CLANG_WARN_CONSTANT_CONVERSION = YES; 344 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 345 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 346 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 347 | CLANG_WARN_EMPTY_BODY = YES; 348 | CLANG_WARN_ENUM_CONVERSION = YES; 349 | CLANG_WARN_INFINITE_RECURSION = YES; 350 | CLANG_WARN_INT_CONVERSION = YES; 351 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 352 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 353 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 354 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 355 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 356 | CLANG_WARN_STRICT_PROTOTYPES = YES; 357 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 358 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 359 | CLANG_WARN_UNREACHABLE_CODE = YES; 360 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 361 | COPY_PHASE_STRIP = NO; 362 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 363 | ENABLE_NS_ASSERTIONS = NO; 364 | ENABLE_STRICT_OBJC_MSGSEND = YES; 365 | GCC_C_LANGUAGE_STANDARD = gnu11; 366 | GCC_NO_COMMON_BLOCKS = YES; 367 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 368 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 369 | GCC_WARN_UNDECLARED_SELECTOR = YES; 370 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 371 | GCC_WARN_UNUSED_FUNCTION = YES; 372 | GCC_WARN_UNUSED_VARIABLE = YES; 373 | IPHONEOS_DEPLOYMENT_TARGET = 13.2; 374 | MTL_ENABLE_DEBUG_INFO = NO; 375 | MTL_FAST_MATH = YES; 376 | SDKROOT = iphoneos; 377 | SWIFT_COMPILATION_MODE = wholemodule; 378 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 379 | VALIDATE_PRODUCT = YES; 380 | }; 381 | name = Release; 382 | }; 383 | C2070732234F682A00CACE2C /* Debug */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 387 | CODE_SIGN_STYLE = Automatic; 388 | DEVELOPMENT_TEAM = 6P8Q9Q6J62; 389 | INFOPLIST_FILE = LoadMoreExample/Info.plist; 390 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 391 | LD_RUNPATH_SEARCH_PATHS = ( 392 | "$(inherited)", 393 | "@executable_path/Frameworks", 394 | ); 395 | PRODUCT_BUNDLE_IDENTIFIER = com.example.LoadMoreExample; 396 | PRODUCT_NAME = "$(TARGET_NAME)"; 397 | SWIFT_VERSION = 5.0; 398 | TARGETED_DEVICE_FAMILY = "1,2"; 399 | }; 400 | name = Debug; 401 | }; 402 | C2070733234F682A00CACE2C /* Release */ = { 403 | isa = XCBuildConfiguration; 404 | buildSettings = { 405 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 406 | CODE_SIGN_STYLE = Automatic; 407 | DEVELOPMENT_TEAM = 6P8Q9Q6J62; 408 | INFOPLIST_FILE = LoadMoreExample/Info.plist; 409 | IPHONEOS_DEPLOYMENT_TARGET = 13.0; 410 | LD_RUNPATH_SEARCH_PATHS = ( 411 | "$(inherited)", 412 | "@executable_path/Frameworks", 413 | ); 414 | PRODUCT_BUNDLE_IDENTIFIER = com.example.LoadMoreExample; 415 | PRODUCT_NAME = "$(TARGET_NAME)"; 416 | SWIFT_VERSION = 5.0; 417 | TARGETED_DEVICE_FAMILY = "1,2"; 418 | }; 419 | name = Release; 420 | }; 421 | /* End XCBuildConfiguration section */ 422 | 423 | /* Begin XCConfigurationList section */ 424 | C2070718234F682800CACE2C /* Build configuration list for PBXProject "LoadMoreExample" */ = { 425 | isa = XCConfigurationList; 426 | buildConfigurations = ( 427 | C207072F234F682A00CACE2C /* Debug */, 428 | C2070730234F682A00CACE2C /* Release */, 429 | ); 430 | defaultConfigurationIsVisible = 0; 431 | defaultConfigurationName = Release; 432 | }; 433 | C2070731234F682A00CACE2C /* Build configuration list for PBXNativeTarget "LoadMoreExample" */ = { 434 | isa = XCConfigurationList; 435 | buildConfigurations = ( 436 | C2070732234F682A00CACE2C /* Debug */, 437 | C2070733234F682A00CACE2C /* Release */, 438 | ); 439 | defaultConfigurationIsVisible = 0; 440 | defaultConfigurationName = Release; 441 | }; 442 | /* End XCConfigurationList section */ 443 | }; 444 | rootObject = C2070715234F682800CACE2C /* Project object */; 445 | } 446 | -------------------------------------------------------------------------------- /LoadMoreExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LoadMoreExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /LoadMoreExample.xcodeproj/project.xcworkspace/xcuserdata/johncodeos.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample.xcodeproj/project.xcworkspace/xcuserdata/johncodeos.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /LoadMoreExample.xcodeproj/xcuserdata/johncodeos.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /LoadMoreExample.xcodeproj/xcuserdata/johncodeos.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | LoadMoreExample.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "40.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "60.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "58.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "87.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "80.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "120.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "120.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "180.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "20.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "40.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "29.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "58.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "40.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "80.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "76.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "152.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "167.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "1024.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/collectionview.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "collectionview.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "collectionview@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "collectionview@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/collectionview.imageset/collectionview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/collectionview.imageset/collectionview.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/collectionview.imageset/collectionview@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/collectionview.imageset/collectionview@2x.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/collectionview.imageset/collectionview@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/collectionview.imageset/collectionview@3x.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/primaryColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.294", 9 | "green" : "0.133", 10 | "red" : "0.737" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/secondaryColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "color" : { 5 | "color-space" : "srgb", 6 | "components" : { 7 | "alpha" : "1.000", 8 | "blue" : "0.251", 9 | "green" : "0.110", 10 | "red" : "0.620" 11 | } 12 | }, 13 | "idiom" : "universal" 14 | } 15 | ], 16 | "info" : { 17 | "author" : "xcode", 18 | "version" : 1 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/tableview.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "tableview.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "tableview@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "tableview@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/tableview.imageset/tableview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/tableview.imageset/tableview.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/tableview.imageset/tableview@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/tableview.imageset/tableview@2x.png -------------------------------------------------------------------------------- /LoadMoreExample/Assets.xcassets/tableview.imageset/tableview@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johncodeos-blog/LoadMoreiOSExample/6ccc521adab5383835b3b4b987ef0e30479aa8df/LoadMoreExample/Assets.xcassets/tableview.imageset/tableview@3x.png -------------------------------------------------------------------------------- /LoadMoreExample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /LoadMoreExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 37 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | -------------------------------------------------------------------------------- /LoadMoreExample/CollectionView/CollectionView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionView.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CollectionViewController: UIViewController { 12 | @IBOutlet var collectionView: UICollectionView! 13 | 14 | var itemsArray = [UIColor]() 15 | 16 | var loadingView: LoadingReusableView? 17 | 18 | var isLoading = false 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | self.collectionView.delegate = self 23 | self.collectionView.dataSource = self 24 | 25 | // Register Item Cell 26 | let itemCellNib = UINib(nibName: "CollectionViewItemCell", bundle: nil) 27 | self.collectionView.register(itemCellNib, forCellWithReuseIdentifier: "collectionviewitemcellid") 28 | 29 | // Register Loading Reuseable View 30 | let loadingReusableNib = UINib(nibName: "LoadingReusableView", bundle: nil) 31 | collectionView.register(loadingReusableNib, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "loadingresuableviewid") 32 | 33 | loadData() 34 | } 35 | 36 | func loadData() { 37 | isLoading = false 38 | collectionView.collectionViewLayout.invalidateLayout() 39 | for _ in 0...40 { 40 | // Add random color in the array 41 | itemsArray.append(getRandomColor()) 42 | } 43 | self.collectionView.reloadData() 44 | } 45 | 46 | func getRandomColor() -> UIColor { 47 | // Generate between 0 to 1 48 | let red = CGFloat(drand48()) 49 | let green = CGFloat(drand48()) 50 | let blue = CGFloat(drand48()) 51 | 52 | return UIColor(red: red, green: green, blue: blue, alpha: 1.0) 53 | } 54 | } 55 | 56 | extension CollectionViewController: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { 57 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 58 | return itemsArray.count 59 | } 60 | 61 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 62 | let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionviewitemcellid", for: indexPath) as! CollectionViewItemCell 63 | cell.imageView.backgroundColor = self.itemsArray[indexPath.row] 64 | return cell 65 | } 66 | 67 | func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) { 68 | if indexPath.row == itemsArray.count - 10, !self.isLoading { 69 | loadMoreData() 70 | } 71 | } 72 | 73 | func loadMoreData() { 74 | if !self.isLoading { 75 | self.isLoading = true 76 | let start = itemsArray.count 77 | let end = start + 16 78 | DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(1)) { // Remove the 1-second delay if you want to load the data without waiting 79 | for _ in start...end { 80 | self.itemsArray.append(self.getRandomColor()) 81 | } 82 | DispatchQueue.main.async { 83 | self.collectionView.reloadData() 84 | self.isLoading = false 85 | } 86 | } 87 | } 88 | } 89 | 90 | func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize { 91 | if self.isLoading { 92 | return CGSize.zero 93 | } else { 94 | return CGSize(width: collectionView.bounds.size.width, height: 55) 95 | } 96 | } 97 | 98 | func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { 99 | if kind == UICollectionView.elementKindSectionFooter { 100 | let aFooterView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "loadingresuableviewid", for: indexPath) as! LoadingReusableView 101 | loadingView = aFooterView 102 | loadingView?.backgroundColor = UIColor.clear 103 | return aFooterView 104 | } 105 | return UICollectionReusableView() 106 | } 107 | 108 | func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath) { 109 | if elementKind == UICollectionView.elementKindSectionFooter { 110 | self.loadingView?.activityIndicator.startAnimating() 111 | } 112 | } 113 | 114 | func collectionView(_ collectionView: UICollectionView, didEndDisplayingSupplementaryView view: UICollectionReusableView, forElementOfKind elementKind: String, at indexPath: IndexPath) { 115 | if elementKind == UICollectionView.elementKindSectionFooter { 116 | self.loadingView?.activityIndicator.stopAnimating() 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /LoadMoreExample/CollectionView/CollectionViewItemCell/CollectionViewItemCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionViewCell.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class CollectionViewItemCell: UICollectionViewCell { 12 | 13 | @IBOutlet weak var imageView: UIImageView! 14 | 15 | override func awakeFromNib() { 16 | super.awakeFromNib() 17 | 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /LoadMoreExample/CollectionView/CollectionViewItemCell/CollectionViewItemCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /LoadMoreExample/CollectionView/LoadingReusableView/LoadingReusableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CollectionViewLoadingReusableView.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LoadingReusableView: UICollectionReusableView { 12 | 13 | @IBOutlet weak var activityIndicator: UIActivityIndicatorView! 14 | 15 | override func awakeFromNib() { 16 | super.awakeFromNib() 17 | activityIndicator.color = UIColor.white 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LoadMoreExample/CollectionView/LoadingReusableView/LoadingReusableView.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /LoadMoreExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | UIViewControllerBasedStatusBarAppearance 64 | 65 | UIStatusBarStyle 66 | UIStatusBarStyleLightContent 67 | 68 | 69 | -------------------------------------------------------------------------------- /LoadMoreExample/MainViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainViewController.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MainViewController: UIViewController { 12 | override func viewDidLoad() { 13 | super.viewDidLoad() 14 | // Fix navigation bar color in iOS 15 and above 15 | if #available(iOS 15, *) { 16 | let appearance = UINavigationBarAppearance() 17 | appearance.configureWithOpaqueBackground() 18 | appearance.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white] 19 | appearance.backgroundColor = UIColor(named: "primaryColor") 20 | navigationController?.navigationBar.standardAppearance = appearance 21 | navigationController?.navigationBar.scrollEdgeAppearance = navigationController?.navigationBar.standardAppearance 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /LoadMoreExample/Supporting Files/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 16 | // Override point for customization after application launch. 17 | return true 18 | } 19 | 20 | // MARK: UISceneSession Lifecycle 21 | 22 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 23 | // Called when a new scene session is being created. 24 | // Use this method to select a configuration to create the new scene with. 25 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 26 | } 27 | 28 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 29 | // Called when the user discards a scene session. 30 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 31 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 32 | } 33 | 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /LoadMoreExample/Supporting Files/CustomLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomLayout.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | import UIKit 9 | 10 | 11 | class CustomLayout: UICollectionViewFlowLayout { 12 | 13 | @IBInspectable var numberOfItemsPerRow: Int = 0 { 14 | didSet { 15 | invalidateLayout() 16 | } 17 | } 18 | 19 | override func prepare() { 20 | super.prepare() 21 | 22 | if let collectionView = self.collectionView { 23 | var newItemSize = itemSize 24 | 25 | // Always use an item count of at least 1 and convert it to a float to use in size calculations 26 | let itemsPerRow = CGFloat(max(numberOfItemsPerRow, 1)) 27 | 28 | // Calculate the sum of the spacing between cells 29 | let totalSpacing = minimumInteritemSpacing * (itemsPerRow - 1.0) 30 | 31 | // Calculate how wide items should be 32 | newItemSize.width = (collectionView.bounds.size.width - sectionInset.left - sectionInset.right - totalSpacing) / itemsPerRow 33 | 34 | // Use the aspect ratio of the current item size to determine how tall the items should be 35 | if itemSize.height > 0 { 36 | let itemAspectRatio = itemSize.width / itemSize.height 37 | newItemSize.height = newItemSize.width / itemAspectRatio 38 | } 39 | 40 | // Set the new item size 41 | itemSize = newItemSize 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LoadMoreExample/Supporting Files/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 16 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 17 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 18 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 19 | guard let _ = (scene as? UIWindowScene) else { return } 20 | } 21 | 22 | func sceneDidDisconnect(_ scene: UIScene) { 23 | // Called as the scene is being released by the system. 24 | // This occurs shortly after the scene enters the background, or when its session is discarded. 25 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 26 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 27 | } 28 | 29 | func sceneDidBecomeActive(_ scene: UIScene) { 30 | // Called when the scene has moved from an inactive state to an active state. 31 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 32 | } 33 | 34 | func sceneWillResignActive(_ scene: UIScene) { 35 | // Called when the scene will move from an active state to an inactive state. 36 | // This may occur due to temporary interruptions (ex. an incoming phone call). 37 | } 38 | 39 | func sceneWillEnterForeground(_ scene: UIScene) { 40 | // Called as the scene transitions from the background to the foreground. 41 | // Use this method to undo the changes made on entering the background. 42 | } 43 | 44 | func sceneDidEnterBackground(_ scene: UIScene) { 45 | // Called as the scene transitions from the foreground to the background. 46 | // Use this method to save data, release shared resources, and store enough scene-specific state information 47 | // to restore the scene back to its current state. 48 | } 49 | 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /LoadMoreExample/TableView/LoadingCell/LoadingCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LoadingCell.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class LoadingCell: UITableViewCell { 12 | 13 | @IBOutlet weak var activityIndicator: UIActivityIndicatorView! 14 | 15 | override func awakeFromNib() { 16 | super.awakeFromNib() 17 | backgroundColor = UIColor.clear 18 | activityIndicator.color = UIColor.white 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /LoadMoreExample/TableView/LoadingCell/LoadingCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /LoadMoreExample/TableView/TableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableView.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TableViewController: UIViewController { 12 | @IBOutlet var tableView: UITableView! 13 | 14 | var itemsArray = [String]() 15 | 16 | var isLoading = false 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | // Register Item Cell 21 | let itemCellNib = UINib(nibName: "TableViewItemCell", bundle: nil) 22 | self.tableView.register(itemCellNib, forCellReuseIdentifier: "tableviewitemcellid") 23 | 24 | // Register Loading Cell 25 | let loadingCellNib = UINib(nibName: "LoadingCell", bundle: nil) 26 | self.tableView.register(loadingCellNib, forCellReuseIdentifier: "loadingcellid") 27 | 28 | loadData() 29 | } 30 | 31 | func loadData() { 32 | self.isLoading = false 33 | for i in 0...40 { 34 | itemsArray.append("Item \(i)") 35 | } 36 | self.tableView.reloadData() 37 | } 38 | 39 | func loadMoreData() { 40 | if !self.isLoading { 41 | self.isLoading = true 42 | let start = itemsArray.count 43 | let end = start + 16 44 | DispatchQueue.global().asyncAfter(deadline: .now() + .seconds(1)) { // Remove the 1-second delay if you want to load the data without waiting 45 | for i in start...end { 46 | self.itemsArray.append("Item \(i)") 47 | } 48 | DispatchQueue.main.async { 49 | self.tableView.reloadData() 50 | self.isLoading = false 51 | } 52 | } 53 | } 54 | } 55 | } 56 | 57 | extension TableViewController: UITableViewDelegate, UITableViewDataSource { 58 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 59 | if section == 0 { 60 | return itemsArray.count 61 | } else if section == 1 { 62 | return 1 63 | } else { 64 | return 0 65 | } 66 | } 67 | 68 | func numberOfSections(in tableView: UITableView) -> Int { 69 | return 2 70 | } 71 | 72 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 73 | if indexPath.section == 0 { 74 | let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewitemcellid", for: indexPath) as! TableViewItemCell 75 | cell.itemLabel.text = itemsArray[indexPath.row] 76 | return cell 77 | } else { 78 | let cell = tableView.dequeueReusableCell(withIdentifier: "loadingcellid", for: indexPath) as! LoadingCell 79 | cell.activityIndicator.startAnimating() 80 | return cell 81 | } 82 | } 83 | 84 | func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 85 | if indexPath.section == 0 { 86 | return 44 // Item Cell height 87 | } else { 88 | return 55 // Loading Cell height 89 | } 90 | } 91 | 92 | func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { 93 | if indexPath.row == itemsArray.count - 10, !isLoading { 94 | loadMoreData() 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /LoadMoreExample/TableView/TableViewItemCell/TableViewItemCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TableViewCell.swift 3 | // LoadMoreExample 4 | // 5 | // Created by John Codeos on 10/14/2019. 6 | // Copyright © 2019 John Codeos. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TableViewItemCell: UITableViewCell { 12 | 13 | @IBOutlet weak var itemLabel: UILabel! 14 | 15 | override func awakeFromNib() { 16 | super.awakeFromNib() 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /LoadMoreExample/TableView/TableViewItemCell/TableViewItemCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![logo](https://i.imgur.com/Dv73hCk.png) 2 | # LoadMoreiOSExample 3 | How to add Load More / Infinite Scrolling in iOS using Swift 4 | 5 | https://johncodeos.com/how-to-add-load-more-infinite-scrolling-in-ios-using-swift/ 6 | --------------------------------------------------------------------------------