├── .gitignore ├── Demo ├── Demo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Demo.xcworkspace │ └── contents.xcworkspacedata ├── Demo │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift ├── DemoTests │ ├── DemoTests.swift │ └── Info.plist ├── DemoUITests │ ├── DemoUITests.swift │ └── Info.plist ├── Podfile ├── Podfile.lock └── Pods │ ├── Local Podspecs │ └── StatefulTableView.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ └── project.pbxproj │ └── Target Support Files │ ├── Pods-Demo │ ├── Info.plist │ ├── Pods-Demo-acknowledgements.markdown │ ├── Pods-Demo-acknowledgements.plist │ ├── Pods-Demo-dummy.m │ ├── Pods-Demo-frameworks.sh │ ├── Pods-Demo-resources.sh │ ├── Pods-Demo-umbrella.h │ ├── Pods-Demo.debug.xcconfig │ ├── Pods-Demo.modulemap │ └── Pods-Demo.release.xcconfig │ └── StatefulTableView │ ├── Info.plist │ ├── StatefulTableView-dummy.m │ ├── StatefulTableView-prefix.pch │ ├── StatefulTableView-umbrella.h │ ├── StatefulTableView.modulemap │ └── StatefulTableView.xcconfig ├── LICENSE ├── README.md ├── Sources ├── CGRect+Extensions.swift ├── StatefulTableDelegate.swift └── StatefulTableView.swift └── StatefulTableView.podspec /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.gitignore.io/api/swift 2 | 3 | ### Swift ### 4 | # Xcode 5 | # 6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 7 | 8 | ## Build generated 9 | build/ 10 | DerivedData/ 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata/ 22 | 23 | ## Other 24 | *.moved-aside 25 | *.xcuserstate 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | Demo/Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2CBFD961A70C9B1577F0286B /* Pods_Demo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E18E2637AAF070943DDCB0A9 /* Pods_Demo.framework */; }; 11 | 8C78531E50789A0105B4072D /* Pods_DemoTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA9251D21C9D91E90A5327F2 /* Pods_DemoTests.framework */; }; 12 | 906D171C1CE4BF99001B30EF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 906D171B1CE4BF99001B30EF /* AppDelegate.swift */; }; 13 | 906D171E1CE4BF99001B30EF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 906D171D1CE4BF99001B30EF /* ViewController.swift */; }; 14 | 906D17211CE4BF99001B30EF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 906D171F1CE4BF99001B30EF /* Main.storyboard */; }; 15 | 906D17231CE4BF99001B30EF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 906D17221CE4BF99001B30EF /* Assets.xcassets */; }; 16 | 906D17261CE4BF99001B30EF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 906D17241CE4BF99001B30EF /* LaunchScreen.storyboard */; }; 17 | 906D17311CE4BF99001B30EF /* DemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 906D17301CE4BF99001B30EF /* DemoTests.swift */; }; 18 | 906D173C1CE4BF99001B30EF /* DemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 906D173B1CE4BF99001B30EF /* DemoUITests.swift */; }; 19 | D884A08032E51E35936B1A02 /* Pods_DemoUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 49C819E087348795B5CBB37E /* Pods_DemoUITests.framework */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 906D172D1CE4BF99001B30EF /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 906D17101CE4BF99001B30EF /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 906D17171CE4BF99001B30EF; 28 | remoteInfo = Demo; 29 | }; 30 | 906D17381CE4BF99001B30EF /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 906D17101CE4BF99001B30EF /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 906D17171CE4BF99001B30EF; 35 | remoteInfo = Demo; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 0A563EA3A78DC7437869051D /* Pods-DemoTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DemoTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-DemoTests/Pods-DemoTests.debug.xcconfig"; sourceTree = ""; }; 41 | 1EAF6CDFC38F75E74127F13C /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig"; sourceTree = ""; }; 42 | 210E8BF35549B671ABAA71B0 /* Pods-DemoTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DemoTests.release.xcconfig"; path = "Pods/Target Support Files/Pods-DemoTests/Pods-DemoTests.release.xcconfig"; sourceTree = ""; }; 43 | 49C819E087348795B5CBB37E /* Pods_DemoUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DemoUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 6CC9EC0297CBB38896C7B7E1 /* Pods-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Demo.release.xcconfig"; path = "Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig"; sourceTree = ""; }; 45 | 906D17181CE4BF99001B30EF /* Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Demo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 906D171B1CE4BF99001B30EF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 47 | 906D171D1CE4BF99001B30EF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 48 | 906D17201CE4BF99001B30EF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 49 | 906D17221CE4BF99001B30EF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 50 | 906D17251CE4BF99001B30EF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 51 | 906D17271CE4BF99001B30EF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 52 | 906D172C1CE4BF99001B30EF /* DemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 906D17301CE4BF99001B30EF /* DemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoTests.swift; sourceTree = ""; }; 54 | 906D17321CE4BF99001B30EF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 55 | 906D17371CE4BF99001B30EF /* DemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 906D173B1CE4BF99001B30EF /* DemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DemoUITests.swift; sourceTree = ""; }; 57 | 906D173D1CE4BF99001B30EF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58 | AA9251D21C9D91E90A5327F2 /* Pods_DemoTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DemoTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 59 | CC164385BCFA6CC7DDC9D1F9 /* Pods-DemoUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DemoUITests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-DemoUITests/Pods-DemoUITests.debug.xcconfig"; sourceTree = ""; }; 60 | E179559F3B224B0B84374FAE /* Pods-DemoUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DemoUITests.release.xcconfig"; path = "Pods/Target Support Files/Pods-DemoUITests/Pods-DemoUITests.release.xcconfig"; sourceTree = ""; }; 61 | E18E2637AAF070943DDCB0A9 /* Pods_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 62 | /* End PBXFileReference section */ 63 | 64 | /* Begin PBXFrameworksBuildPhase section */ 65 | 906D17151CE4BF99001B30EF /* Frameworks */ = { 66 | isa = PBXFrameworksBuildPhase; 67 | buildActionMask = 2147483647; 68 | files = ( 69 | 2CBFD961A70C9B1577F0286B /* Pods_Demo.framework in Frameworks */, 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | 906D17291CE4BF99001B30EF /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | 8C78531E50789A0105B4072D /* Pods_DemoTests.framework in Frameworks */, 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | 906D17341CE4BF99001B30EF /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | D884A08032E51E35936B1A02 /* Pods_DemoUITests.framework in Frameworks */, 86 | ); 87 | runOnlyForDeploymentPostprocessing = 0; 88 | }; 89 | /* End PBXFrameworksBuildPhase section */ 90 | 91 | /* Begin PBXGroup section */ 92 | 906D170F1CE4BF99001B30EF = { 93 | isa = PBXGroup; 94 | children = ( 95 | 906D171A1CE4BF99001B30EF /* Demo */, 96 | 906D172F1CE4BF99001B30EF /* DemoTests */, 97 | 906D173A1CE4BF99001B30EF /* DemoUITests */, 98 | 906D17191CE4BF99001B30EF /* Products */, 99 | 99D9B40D95A3F5108647351E /* Pods */, 100 | C545F881EFF8BB3EAD6954EA /* Frameworks */, 101 | ); 102 | sourceTree = ""; 103 | }; 104 | 906D17191CE4BF99001B30EF /* Products */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 906D17181CE4BF99001B30EF /* Demo.app */, 108 | 906D172C1CE4BF99001B30EF /* DemoTests.xctest */, 109 | 906D17371CE4BF99001B30EF /* DemoUITests.xctest */, 110 | ); 111 | name = Products; 112 | sourceTree = ""; 113 | }; 114 | 906D171A1CE4BF99001B30EF /* Demo */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 906D171B1CE4BF99001B30EF /* AppDelegate.swift */, 118 | 906D171D1CE4BF99001B30EF /* ViewController.swift */, 119 | 906D171F1CE4BF99001B30EF /* Main.storyboard */, 120 | 906D17221CE4BF99001B30EF /* Assets.xcassets */, 121 | 906D17241CE4BF99001B30EF /* LaunchScreen.storyboard */, 122 | 906D17271CE4BF99001B30EF /* Info.plist */, 123 | ); 124 | path = Demo; 125 | sourceTree = ""; 126 | }; 127 | 906D172F1CE4BF99001B30EF /* DemoTests */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 906D17301CE4BF99001B30EF /* DemoTests.swift */, 131 | 906D17321CE4BF99001B30EF /* Info.plist */, 132 | ); 133 | path = DemoTests; 134 | sourceTree = ""; 135 | }; 136 | 906D173A1CE4BF99001B30EF /* DemoUITests */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 906D173B1CE4BF99001B30EF /* DemoUITests.swift */, 140 | 906D173D1CE4BF99001B30EF /* Info.plist */, 141 | ); 142 | path = DemoUITests; 143 | sourceTree = ""; 144 | }; 145 | 99D9B40D95A3F5108647351E /* Pods */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 1EAF6CDFC38F75E74127F13C /* Pods-Demo.debug.xcconfig */, 149 | 6CC9EC0297CBB38896C7B7E1 /* Pods-Demo.release.xcconfig */, 150 | 0A563EA3A78DC7437869051D /* Pods-DemoTests.debug.xcconfig */, 151 | 210E8BF35549B671ABAA71B0 /* Pods-DemoTests.release.xcconfig */, 152 | CC164385BCFA6CC7DDC9D1F9 /* Pods-DemoUITests.debug.xcconfig */, 153 | E179559F3B224B0B84374FAE /* Pods-DemoUITests.release.xcconfig */, 154 | ); 155 | name = Pods; 156 | sourceTree = ""; 157 | }; 158 | C545F881EFF8BB3EAD6954EA /* Frameworks */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | E18E2637AAF070943DDCB0A9 /* Pods_Demo.framework */, 162 | AA9251D21C9D91E90A5327F2 /* Pods_DemoTests.framework */, 163 | 49C819E087348795B5CBB37E /* Pods_DemoUITests.framework */, 164 | ); 165 | name = Frameworks; 166 | sourceTree = ""; 167 | }; 168 | /* End PBXGroup section */ 169 | 170 | /* Begin PBXNativeTarget section */ 171 | 906D17171CE4BF99001B30EF /* Demo */ = { 172 | isa = PBXNativeTarget; 173 | buildConfigurationList = 906D17401CE4BF99001B30EF /* Build configuration list for PBXNativeTarget "Demo" */; 174 | buildPhases = ( 175 | FEB65081904F90F064C377A1 /* 📦 Check Pods Manifest.lock */, 176 | 906D17141CE4BF99001B30EF /* Sources */, 177 | 906D17151CE4BF99001B30EF /* Frameworks */, 178 | 906D17161CE4BF99001B30EF /* Resources */, 179 | 86804F2319AE8F80CD8FFAF9 /* 📦 Embed Pods Frameworks */, 180 | 5F6248DCDFF53F5D059D2D5E /* 📦 Copy Pods Resources */, 181 | ); 182 | buildRules = ( 183 | ); 184 | dependencies = ( 185 | ); 186 | name = Demo; 187 | productName = Demo; 188 | productReference = 906D17181CE4BF99001B30EF /* Demo.app */; 189 | productType = "com.apple.product-type.application"; 190 | }; 191 | 906D172B1CE4BF99001B30EF /* DemoTests */ = { 192 | isa = PBXNativeTarget; 193 | buildConfigurationList = 906D17431CE4BF99001B30EF /* Build configuration list for PBXNativeTarget "DemoTests" */; 194 | buildPhases = ( 195 | 22ADE59AA9009ED6D5DB509B /* 📦 Check Pods Manifest.lock */, 196 | 906D17281CE4BF99001B30EF /* Sources */, 197 | 906D17291CE4BF99001B30EF /* Frameworks */, 198 | 906D172A1CE4BF99001B30EF /* Resources */, 199 | 389F862436469705440E9EC9 /* 📦 Embed Pods Frameworks */, 200 | 6A4D202622A93480BA8D8468 /* 📦 Copy Pods Resources */, 201 | ); 202 | buildRules = ( 203 | ); 204 | dependencies = ( 205 | 906D172E1CE4BF99001B30EF /* PBXTargetDependency */, 206 | ); 207 | name = DemoTests; 208 | productName = DemoTests; 209 | productReference = 906D172C1CE4BF99001B30EF /* DemoTests.xctest */; 210 | productType = "com.apple.product-type.bundle.unit-test"; 211 | }; 212 | 906D17361CE4BF99001B30EF /* DemoUITests */ = { 213 | isa = PBXNativeTarget; 214 | buildConfigurationList = 906D17461CE4BF99001B30EF /* Build configuration list for PBXNativeTarget "DemoUITests" */; 215 | buildPhases = ( 216 | D6D4202278DCFD55DD82F020 /* 📦 Check Pods Manifest.lock */, 217 | 906D17331CE4BF99001B30EF /* Sources */, 218 | 906D17341CE4BF99001B30EF /* Frameworks */, 219 | 906D17351CE4BF99001B30EF /* Resources */, 220 | 6A9D1057246E8E96D8E1F3BD /* 📦 Copy Pods Resources */, 221 | ); 222 | buildRules = ( 223 | ); 224 | dependencies = ( 225 | 906D17391CE4BF99001B30EF /* PBXTargetDependency */, 226 | ); 227 | name = DemoUITests; 228 | productName = DemoUITests; 229 | productReference = 906D17371CE4BF99001B30EF /* DemoUITests.xctest */; 230 | productType = "com.apple.product-type.bundle.ui-testing"; 231 | }; 232 | /* End PBXNativeTarget section */ 233 | 234 | /* Begin PBXProject section */ 235 | 906D17101CE4BF99001B30EF /* Project object */ = { 236 | isa = PBXProject; 237 | attributes = { 238 | LastSwiftUpdateCheck = 0730; 239 | LastUpgradeCheck = 0730; 240 | ORGANIZATIONNAME = timominous; 241 | TargetAttributes = { 242 | 906D17171CE4BF99001B30EF = { 243 | CreatedOnToolsVersion = 7.3; 244 | }; 245 | 906D172B1CE4BF99001B30EF = { 246 | CreatedOnToolsVersion = 7.3; 247 | TestTargetID = 906D17171CE4BF99001B30EF; 248 | }; 249 | 906D17361CE4BF99001B30EF = { 250 | CreatedOnToolsVersion = 7.3; 251 | TestTargetID = 906D17171CE4BF99001B30EF; 252 | }; 253 | }; 254 | }; 255 | buildConfigurationList = 906D17131CE4BF99001B30EF /* Build configuration list for PBXProject "Demo" */; 256 | compatibilityVersion = "Xcode 3.2"; 257 | developmentRegion = English; 258 | hasScannedForEncodings = 0; 259 | knownRegions = ( 260 | en, 261 | Base, 262 | ); 263 | mainGroup = 906D170F1CE4BF99001B30EF; 264 | productRefGroup = 906D17191CE4BF99001B30EF /* Products */; 265 | projectDirPath = ""; 266 | projectRoot = ""; 267 | targets = ( 268 | 906D17171CE4BF99001B30EF /* Demo */, 269 | 906D172B1CE4BF99001B30EF /* DemoTests */, 270 | 906D17361CE4BF99001B30EF /* DemoUITests */, 271 | ); 272 | }; 273 | /* End PBXProject section */ 274 | 275 | /* Begin PBXResourcesBuildPhase section */ 276 | 906D17161CE4BF99001B30EF /* Resources */ = { 277 | isa = PBXResourcesBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | 906D17261CE4BF99001B30EF /* LaunchScreen.storyboard in Resources */, 281 | 906D17231CE4BF99001B30EF /* Assets.xcassets in Resources */, 282 | 906D17211CE4BF99001B30EF /* Main.storyboard in Resources */, 283 | ); 284 | runOnlyForDeploymentPostprocessing = 0; 285 | }; 286 | 906D172A1CE4BF99001B30EF /* Resources */ = { 287 | isa = PBXResourcesBuildPhase; 288 | buildActionMask = 2147483647; 289 | files = ( 290 | ); 291 | runOnlyForDeploymentPostprocessing = 0; 292 | }; 293 | 906D17351CE4BF99001B30EF /* Resources */ = { 294 | isa = PBXResourcesBuildPhase; 295 | buildActionMask = 2147483647; 296 | files = ( 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | }; 300 | /* End PBXResourcesBuildPhase section */ 301 | 302 | /* Begin PBXShellScriptBuildPhase section */ 303 | 22ADE59AA9009ED6D5DB509B /* 📦 Check Pods Manifest.lock */ = { 304 | isa = PBXShellScriptBuildPhase; 305 | buildActionMask = 2147483647; 306 | files = ( 307 | ); 308 | inputPaths = ( 309 | ); 310 | name = "📦 Check Pods Manifest.lock"; 311 | outputPaths = ( 312 | ); 313 | runOnlyForDeploymentPostprocessing = 0; 314 | shellPath = /bin/sh; 315 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 316 | showEnvVarsInLog = 0; 317 | }; 318 | 389F862436469705440E9EC9 /* 📦 Embed Pods Frameworks */ = { 319 | isa = PBXShellScriptBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | ); 323 | inputPaths = ( 324 | ); 325 | name = "📦 Embed Pods Frameworks"; 326 | outputPaths = ( 327 | ); 328 | runOnlyForDeploymentPostprocessing = 0; 329 | shellPath = /bin/sh; 330 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DemoTests/Pods-DemoTests-frameworks.sh\"\n"; 331 | showEnvVarsInLog = 0; 332 | }; 333 | 5F6248DCDFF53F5D059D2D5E /* 📦 Copy Pods Resources */ = { 334 | isa = PBXShellScriptBuildPhase; 335 | buildActionMask = 2147483647; 336 | files = ( 337 | ); 338 | inputPaths = ( 339 | ); 340 | name = "📦 Copy Pods Resources"; 341 | outputPaths = ( 342 | ); 343 | runOnlyForDeploymentPostprocessing = 0; 344 | shellPath = /bin/sh; 345 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Demo/Pods-Demo-resources.sh\"\n"; 346 | showEnvVarsInLog = 0; 347 | }; 348 | 6A4D202622A93480BA8D8468 /* 📦 Copy Pods Resources */ = { 349 | isa = PBXShellScriptBuildPhase; 350 | buildActionMask = 2147483647; 351 | files = ( 352 | ); 353 | inputPaths = ( 354 | ); 355 | name = "📦 Copy Pods Resources"; 356 | outputPaths = ( 357 | ); 358 | runOnlyForDeploymentPostprocessing = 0; 359 | shellPath = /bin/sh; 360 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DemoTests/Pods-DemoTests-resources.sh\"\n"; 361 | showEnvVarsInLog = 0; 362 | }; 363 | 6A9D1057246E8E96D8E1F3BD /* 📦 Copy Pods Resources */ = { 364 | isa = PBXShellScriptBuildPhase; 365 | buildActionMask = 2147483647; 366 | files = ( 367 | ); 368 | inputPaths = ( 369 | ); 370 | name = "📦 Copy Pods Resources"; 371 | outputPaths = ( 372 | ); 373 | runOnlyForDeploymentPostprocessing = 0; 374 | shellPath = /bin/sh; 375 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-DemoUITests/Pods-DemoUITests-resources.sh\"\n"; 376 | showEnvVarsInLog = 0; 377 | }; 378 | 86804F2319AE8F80CD8FFAF9 /* 📦 Embed Pods Frameworks */ = { 379 | isa = PBXShellScriptBuildPhase; 380 | buildActionMask = 2147483647; 381 | files = ( 382 | ); 383 | inputPaths = ( 384 | ); 385 | name = "📦 Embed Pods Frameworks"; 386 | outputPaths = ( 387 | ); 388 | runOnlyForDeploymentPostprocessing = 0; 389 | shellPath = /bin/sh; 390 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh\"\n"; 391 | showEnvVarsInLog = 0; 392 | }; 393 | D6D4202278DCFD55DD82F020 /* 📦 Check Pods Manifest.lock */ = { 394 | isa = PBXShellScriptBuildPhase; 395 | buildActionMask = 2147483647; 396 | files = ( 397 | ); 398 | inputPaths = ( 399 | ); 400 | name = "📦 Check Pods Manifest.lock"; 401 | outputPaths = ( 402 | ); 403 | runOnlyForDeploymentPostprocessing = 0; 404 | shellPath = /bin/sh; 405 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 406 | showEnvVarsInLog = 0; 407 | }; 408 | FEB65081904F90F064C377A1 /* 📦 Check Pods Manifest.lock */ = { 409 | isa = PBXShellScriptBuildPhase; 410 | buildActionMask = 2147483647; 411 | files = ( 412 | ); 413 | inputPaths = ( 414 | ); 415 | name = "📦 Check Pods Manifest.lock"; 416 | outputPaths = ( 417 | ); 418 | runOnlyForDeploymentPostprocessing = 0; 419 | shellPath = /bin/sh; 420 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 421 | showEnvVarsInLog = 0; 422 | }; 423 | /* End PBXShellScriptBuildPhase section */ 424 | 425 | /* Begin PBXSourcesBuildPhase section */ 426 | 906D17141CE4BF99001B30EF /* Sources */ = { 427 | isa = PBXSourcesBuildPhase; 428 | buildActionMask = 2147483647; 429 | files = ( 430 | 906D171E1CE4BF99001B30EF /* ViewController.swift in Sources */, 431 | 906D171C1CE4BF99001B30EF /* AppDelegate.swift in Sources */, 432 | ); 433 | runOnlyForDeploymentPostprocessing = 0; 434 | }; 435 | 906D17281CE4BF99001B30EF /* Sources */ = { 436 | isa = PBXSourcesBuildPhase; 437 | buildActionMask = 2147483647; 438 | files = ( 439 | 906D17311CE4BF99001B30EF /* DemoTests.swift in Sources */, 440 | ); 441 | runOnlyForDeploymentPostprocessing = 0; 442 | }; 443 | 906D17331CE4BF99001B30EF /* Sources */ = { 444 | isa = PBXSourcesBuildPhase; 445 | buildActionMask = 2147483647; 446 | files = ( 447 | 906D173C1CE4BF99001B30EF /* DemoUITests.swift in Sources */, 448 | ); 449 | runOnlyForDeploymentPostprocessing = 0; 450 | }; 451 | /* End PBXSourcesBuildPhase section */ 452 | 453 | /* Begin PBXTargetDependency section */ 454 | 906D172E1CE4BF99001B30EF /* PBXTargetDependency */ = { 455 | isa = PBXTargetDependency; 456 | target = 906D17171CE4BF99001B30EF /* Demo */; 457 | targetProxy = 906D172D1CE4BF99001B30EF /* PBXContainerItemProxy */; 458 | }; 459 | 906D17391CE4BF99001B30EF /* PBXTargetDependency */ = { 460 | isa = PBXTargetDependency; 461 | target = 906D17171CE4BF99001B30EF /* Demo */; 462 | targetProxy = 906D17381CE4BF99001B30EF /* PBXContainerItemProxy */; 463 | }; 464 | /* End PBXTargetDependency section */ 465 | 466 | /* Begin PBXVariantGroup section */ 467 | 906D171F1CE4BF99001B30EF /* Main.storyboard */ = { 468 | isa = PBXVariantGroup; 469 | children = ( 470 | 906D17201CE4BF99001B30EF /* Base */, 471 | ); 472 | name = Main.storyboard; 473 | sourceTree = ""; 474 | }; 475 | 906D17241CE4BF99001B30EF /* LaunchScreen.storyboard */ = { 476 | isa = PBXVariantGroup; 477 | children = ( 478 | 906D17251CE4BF99001B30EF /* Base */, 479 | ); 480 | name = LaunchScreen.storyboard; 481 | sourceTree = ""; 482 | }; 483 | /* End PBXVariantGroup section */ 484 | 485 | /* Begin XCBuildConfiguration section */ 486 | 906D173E1CE4BF99001B30EF /* Debug */ = { 487 | isa = XCBuildConfiguration; 488 | buildSettings = { 489 | ALWAYS_SEARCH_USER_PATHS = NO; 490 | CLANG_ANALYZER_NONNULL = YES; 491 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 492 | CLANG_CXX_LIBRARY = "libc++"; 493 | CLANG_ENABLE_MODULES = YES; 494 | CLANG_ENABLE_OBJC_ARC = YES; 495 | CLANG_WARN_BOOL_CONVERSION = YES; 496 | CLANG_WARN_CONSTANT_CONVERSION = YES; 497 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 498 | CLANG_WARN_EMPTY_BODY = YES; 499 | CLANG_WARN_ENUM_CONVERSION = YES; 500 | CLANG_WARN_INT_CONVERSION = YES; 501 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 502 | CLANG_WARN_UNREACHABLE_CODE = YES; 503 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 504 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 505 | COPY_PHASE_STRIP = NO; 506 | DEBUG_INFORMATION_FORMAT = dwarf; 507 | ENABLE_STRICT_OBJC_MSGSEND = YES; 508 | ENABLE_TESTABILITY = YES; 509 | GCC_C_LANGUAGE_STANDARD = gnu99; 510 | GCC_DYNAMIC_NO_PIC = NO; 511 | GCC_NO_COMMON_BLOCKS = YES; 512 | GCC_OPTIMIZATION_LEVEL = 0; 513 | GCC_PREPROCESSOR_DEFINITIONS = ( 514 | "DEBUG=1", 515 | "$(inherited)", 516 | ); 517 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 518 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 519 | GCC_WARN_UNDECLARED_SELECTOR = YES; 520 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 521 | GCC_WARN_UNUSED_FUNCTION = YES; 522 | GCC_WARN_UNUSED_VARIABLE = YES; 523 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 524 | MTL_ENABLE_DEBUG_INFO = YES; 525 | ONLY_ACTIVE_ARCH = YES; 526 | SDKROOT = iphoneos; 527 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 528 | TARGETED_DEVICE_FAMILY = "1,2"; 529 | }; 530 | name = Debug; 531 | }; 532 | 906D173F1CE4BF99001B30EF /* Release */ = { 533 | isa = XCBuildConfiguration; 534 | buildSettings = { 535 | ALWAYS_SEARCH_USER_PATHS = NO; 536 | CLANG_ANALYZER_NONNULL = YES; 537 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 538 | CLANG_CXX_LIBRARY = "libc++"; 539 | CLANG_ENABLE_MODULES = YES; 540 | CLANG_ENABLE_OBJC_ARC = YES; 541 | CLANG_WARN_BOOL_CONVERSION = YES; 542 | CLANG_WARN_CONSTANT_CONVERSION = YES; 543 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 544 | CLANG_WARN_EMPTY_BODY = YES; 545 | CLANG_WARN_ENUM_CONVERSION = YES; 546 | CLANG_WARN_INT_CONVERSION = YES; 547 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 548 | CLANG_WARN_UNREACHABLE_CODE = YES; 549 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 550 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 551 | COPY_PHASE_STRIP = NO; 552 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 553 | ENABLE_NS_ASSERTIONS = NO; 554 | ENABLE_STRICT_OBJC_MSGSEND = YES; 555 | GCC_C_LANGUAGE_STANDARD = gnu99; 556 | GCC_NO_COMMON_BLOCKS = YES; 557 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 558 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 559 | GCC_WARN_UNDECLARED_SELECTOR = YES; 560 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 561 | GCC_WARN_UNUSED_FUNCTION = YES; 562 | GCC_WARN_UNUSED_VARIABLE = YES; 563 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 564 | MTL_ENABLE_DEBUG_INFO = NO; 565 | SDKROOT = iphoneos; 566 | TARGETED_DEVICE_FAMILY = "1,2"; 567 | VALIDATE_PRODUCT = YES; 568 | }; 569 | name = Release; 570 | }; 571 | 906D17411CE4BF99001B30EF /* Debug */ = { 572 | isa = XCBuildConfiguration; 573 | baseConfigurationReference = 1EAF6CDFC38F75E74127F13C /* Pods-Demo.debug.xcconfig */; 574 | buildSettings = { 575 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 576 | INFOPLIST_FILE = Demo/Info.plist; 577 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 578 | PRODUCT_BUNDLE_IDENTIFIER = com.timomnious.Demo; 579 | PRODUCT_NAME = "$(TARGET_NAME)"; 580 | }; 581 | name = Debug; 582 | }; 583 | 906D17421CE4BF99001B30EF /* Release */ = { 584 | isa = XCBuildConfiguration; 585 | baseConfigurationReference = 6CC9EC0297CBB38896C7B7E1 /* Pods-Demo.release.xcconfig */; 586 | buildSettings = { 587 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 588 | INFOPLIST_FILE = Demo/Info.plist; 589 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 590 | PRODUCT_BUNDLE_IDENTIFIER = com.timomnious.Demo; 591 | PRODUCT_NAME = "$(TARGET_NAME)"; 592 | }; 593 | name = Release; 594 | }; 595 | 906D17441CE4BF99001B30EF /* Debug */ = { 596 | isa = XCBuildConfiguration; 597 | baseConfigurationReference = 0A563EA3A78DC7437869051D /* Pods-DemoTests.debug.xcconfig */; 598 | buildSettings = { 599 | BUNDLE_LOADER = "$(TEST_HOST)"; 600 | INFOPLIST_FILE = DemoTests/Info.plist; 601 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 602 | PRODUCT_BUNDLE_IDENTIFIER = com.timomnious.DemoTests; 603 | PRODUCT_NAME = "$(TARGET_NAME)"; 604 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo"; 605 | }; 606 | name = Debug; 607 | }; 608 | 906D17451CE4BF99001B30EF /* Release */ = { 609 | isa = XCBuildConfiguration; 610 | baseConfigurationReference = 210E8BF35549B671ABAA71B0 /* Pods-DemoTests.release.xcconfig */; 611 | buildSettings = { 612 | BUNDLE_LOADER = "$(TEST_HOST)"; 613 | INFOPLIST_FILE = DemoTests/Info.plist; 614 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 615 | PRODUCT_BUNDLE_IDENTIFIER = com.timomnious.DemoTests; 616 | PRODUCT_NAME = "$(TARGET_NAME)"; 617 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Demo.app/Demo"; 618 | }; 619 | name = Release; 620 | }; 621 | 906D17471CE4BF99001B30EF /* Debug */ = { 622 | isa = XCBuildConfiguration; 623 | baseConfigurationReference = CC164385BCFA6CC7DDC9D1F9 /* Pods-DemoUITests.debug.xcconfig */; 624 | buildSettings = { 625 | INFOPLIST_FILE = DemoUITests/Info.plist; 626 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 627 | PRODUCT_BUNDLE_IDENTIFIER = com.timomnious.DemoUITests; 628 | PRODUCT_NAME = "$(TARGET_NAME)"; 629 | TEST_TARGET_NAME = Demo; 630 | }; 631 | name = Debug; 632 | }; 633 | 906D17481CE4BF99001B30EF /* Release */ = { 634 | isa = XCBuildConfiguration; 635 | baseConfigurationReference = E179559F3B224B0B84374FAE /* Pods-DemoUITests.release.xcconfig */; 636 | buildSettings = { 637 | INFOPLIST_FILE = DemoUITests/Info.plist; 638 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 639 | PRODUCT_BUNDLE_IDENTIFIER = com.timomnious.DemoUITests; 640 | PRODUCT_NAME = "$(TARGET_NAME)"; 641 | TEST_TARGET_NAME = Demo; 642 | }; 643 | name = Release; 644 | }; 645 | /* End XCBuildConfiguration section */ 646 | 647 | /* Begin XCConfigurationList section */ 648 | 906D17131CE4BF99001B30EF /* Build configuration list for PBXProject "Demo" */ = { 649 | isa = XCConfigurationList; 650 | buildConfigurations = ( 651 | 906D173E1CE4BF99001B30EF /* Debug */, 652 | 906D173F1CE4BF99001B30EF /* Release */, 653 | ); 654 | defaultConfigurationIsVisible = 0; 655 | defaultConfigurationName = Release; 656 | }; 657 | 906D17401CE4BF99001B30EF /* Build configuration list for PBXNativeTarget "Demo" */ = { 658 | isa = XCConfigurationList; 659 | buildConfigurations = ( 660 | 906D17411CE4BF99001B30EF /* Debug */, 661 | 906D17421CE4BF99001B30EF /* Release */, 662 | ); 663 | defaultConfigurationIsVisible = 0; 664 | defaultConfigurationName = Release; 665 | }; 666 | 906D17431CE4BF99001B30EF /* Build configuration list for PBXNativeTarget "DemoTests" */ = { 667 | isa = XCConfigurationList; 668 | buildConfigurations = ( 669 | 906D17441CE4BF99001B30EF /* Debug */, 670 | 906D17451CE4BF99001B30EF /* Release */, 671 | ); 672 | defaultConfigurationIsVisible = 0; 673 | defaultConfigurationName = Release; 674 | }; 675 | 906D17461CE4BF99001B30EF /* Build configuration list for PBXNativeTarget "DemoUITests" */ = { 676 | isa = XCConfigurationList; 677 | buildConfigurations = ( 678 | 906D17471CE4BF99001B30EF /* Debug */, 679 | 906D17481CE4BF99001B30EF /* Release */, 680 | ); 681 | defaultConfigurationIsVisible = 0; 682 | defaultConfigurationName = Release; 683 | }; 684 | /* End XCConfigurationList section */ 685 | }; 686 | rootObject = 906D17101CE4BF99001B30EF /* Project object */; 687 | } 688 | -------------------------------------------------------------------------------- /Demo/Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Demo.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demo/Demo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Demo 4 | // 5 | // Created by Tim on 12/05/2016. 6 | // Copyright © 2016 timominous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 17 | return true 18 | } 19 | 20 | func applicationWillResignActive(application: UIApplication) { 21 | } 22 | 23 | func applicationDidEnterBackground(application: UIApplication) { 24 | } 25 | 26 | func applicationWillEnterForeground(application: UIApplication) { 27 | } 28 | 29 | func applicationDidBecomeActive(application: UIApplication) { 30 | } 31 | 32 | func applicationWillTerminate(application: UIApplication) { 33 | } 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /Demo/Demo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Demo/Demo/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 | 27 | 28 | -------------------------------------------------------------------------------- /Demo/Demo/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 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Demo/Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /Demo/Demo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Demo 4 | // 5 | // Created by Tim on 12/05/2016. 6 | // Copyright © 2016 timominous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import StatefulTableView 11 | 12 | class ViewController: UIViewController { 13 | 14 | @IBOutlet weak var statefulTableView: StatefulTableView! 15 | 16 | var items = 0 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | statefulTableView.canPullToRefresh = true 21 | statefulTableView.canLoadMore = true 22 | 23 | statefulTableView.statefulDelegate = self 24 | statefulTableView.dataSource = self 25 | statefulTableView.delegate = self 26 | statefulTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "identifier") 27 | } 28 | 29 | override func viewDidAppear(animated: Bool) { 30 | super.viewDidAppear(animated) 31 | statefulTableView.triggerInitialLoad() 32 | } 33 | 34 | override func didReceiveMemoryWarning() { 35 | super.didReceiveMemoryWarning() 36 | } 37 | 38 | } 39 | 40 | extension ViewController: StatefulTableDelegate { 41 | func statefulTableViewWillBeginLoadingFromRefresh(tvc: StatefulTableView, handler: InitialLoadCompletionHandler) { 42 | items = Int(arc4random_uniform(15)) 43 | let empty = items == 0 44 | 45 | let time = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * NSEC_PER_SEC)) 46 | dispatch_after(time, dispatch_get_main_queue()) { 47 | let error = NSError(domain: "test", code: 1, userInfo: [NSLocalizedDescriptionKey: "Unknown error"]) 48 | tvc.reloadData() 49 | handler(tableIsEmpty: empty, errorOrNil: error) 50 | } 51 | } 52 | 53 | func statefulTableViewWillBeginInitialLoad(tvc: StatefulTableView, handler: InitialLoadCompletionHandler) { 54 | items = Int(arc4random_uniform(15)) 55 | let empty = items == 0 56 | 57 | let time = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * NSEC_PER_SEC)) 58 | dispatch_after(time, dispatch_get_main_queue()) { 59 | let error = NSError(domain: "test", code: 1, userInfo: [NSLocalizedDescriptionKey: "Unknown error"]) 60 | tvc.reloadData() 61 | handler(tableIsEmpty: empty, errorOrNil: error) 62 | } 63 | } 64 | 65 | func statefulTableViewWillBeginLoadingMore(tvc: StatefulTableView, handler: LoadMoreCompletionHandler) { 66 | // items += Int(arc4random_uniform(20)) 67 | // let loadMore = items < 50 68 | let loadMore = false 69 | 70 | let time = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * NSEC_PER_SEC)) 71 | dispatch_after(time, dispatch_get_main_queue()) { 72 | let error = NSError(domain: "test", code: 1, userInfo: [NSLocalizedDescriptionKey: "Unknown error"]) 73 | tvc.reloadData() 74 | handler(canLoadMore: true, errorOrNil: error, showErrorView: !loadMore) 75 | } 76 | } 77 | 78 | func statefulTableViewViewForInitialLoad(tvc: StatefulTableView) -> UIView? { 79 | // let view = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 100))) 80 | // view.backgroundColor = .blueColor() 81 | // return view 82 | return nil 83 | } 84 | 85 | func statefulTableViewView(tvc: StatefulTableView, forInitialLoadError: NSError?) -> UIView? { 86 | // let view = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 100))) 87 | // view.backgroundColor = .redColor() 88 | // return view 89 | return nil 90 | } 91 | 92 | func statefulTableViewView(tvc: StatefulTableView, forLoadMoreError: NSError?) -> UIView? { 93 | let view = UIView(frame: CGRect(origin: .zero, size: CGSize(width: 100, height: 100))) 94 | view.backgroundColor = .greenColor() 95 | return view 96 | // return nil 97 | } 98 | } 99 | 100 | extension ViewController: UITableViewDataSource { 101 | func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 102 | return items 103 | } 104 | 105 | func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 106 | return tableView.dequeueReusableCellWithIdentifier("identifier", forIndexPath: indexPath) 107 | } 108 | } 109 | 110 | extension ViewController: UITableViewDelegate { 111 | func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) { 112 | cell.textLabel?.text = "Cell \(indexPath.row)" 113 | } 114 | 115 | func scrollViewDidScroll(scrollView: UIScrollView) { 116 | statefulTableView.scrollViewDidScroll(scrollView) 117 | } 118 | } 119 | 120 | -------------------------------------------------------------------------------- /Demo/DemoTests/DemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DemoTests.swift 3 | // DemoTests 4 | // 5 | // Created by Tim on 12/05/2016. 6 | // Copyright © 2016 timominous. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import Demo 11 | 12 | class DemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Demo/DemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Demo/DemoUITests/DemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DemoUITests.swift 3 | // DemoUITests 4 | // 5 | // Created by Tim on 12/05/2016. 6 | // Copyright © 2016 timominous. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class DemoUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /Demo/DemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Demo/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | use_frameworks! 3 | 4 | target 'Demo' do 5 | 6 | pod 'StatefulTableView', :path => '../' 7 | 8 | end 9 | 10 | target 'DemoTests' do 11 | 12 | end 13 | 14 | target 'DemoUITests' do 15 | 16 | end 17 | 18 | -------------------------------------------------------------------------------- /Demo/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - StatefulTableView (0.0.7) 3 | 4 | DEPENDENCIES: 5 | - StatefulTableView (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | StatefulTableView: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | StatefulTableView: 4aee2f4b31384b56187908e55b6f57ef787fe97f 13 | 14 | PODFILE CHECKSUM: e6944d74483536f64ec788f95fbe36a46c8b7346 15 | 16 | COCOAPODS: 1.0.0 17 | -------------------------------------------------------------------------------- /Demo/Pods/Local Podspecs/StatefulTableView.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "StatefulTableView", 3 | "version": "0.0.7", 4 | "license": { 5 | "type": "MIT", 6 | "file": "LICENSE" 7 | }, 8 | "homepage": "http://github.com/timominous/StatefulTableView", 9 | "description": "Custom UITableView container class that supports pull-to-refresh, load-more, initial load, and empty states. Swift port of SKStatefulTableViewController", 10 | "summary": "Custom UITableView container class that supports pull-to-refresh, load-more, initial load, and empty states.", 11 | "authors": { 12 | "timominous": "timominous@gmail.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/timominous/StatefulTableView.git", 16 | "tag": "0.0.7" 17 | }, 18 | "platforms": { 19 | "ios": "8.0" 20 | }, 21 | "source_files": "Sources/*.swift", 22 | "requires_arc": true 23 | } 24 | -------------------------------------------------------------------------------- /Demo/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - StatefulTableView (0.0.7) 3 | 4 | DEPENDENCIES: 5 | - StatefulTableView (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | StatefulTableView: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | StatefulTableView: 4aee2f4b31384b56187908e55b6f57ef787fe97f 13 | 14 | PODFILE CHECKSUM: e6944d74483536f64ec788f95fbe36a46c8b7346 15 | 16 | COCOAPODS: 1.0.0 17 | -------------------------------------------------------------------------------- /Demo/Pods/Pods.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0E36B00605783AE35801FA8BC2696DA6 /* StatefulTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66E0F451469F15360D21A33B3D797686 /* StatefulTableView.swift */; }; 11 | 4C012D74EEB3B8E39B3EB083663682D1 /* Pods-DemoTests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B1569C6DCF82AA7CF84D8B811006EB33 /* Pods-DemoTests-dummy.m */; }; 12 | 610807D5B787A45F792AE0C1F3058C40 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEC22C73C1608DFA5D5D78BDCB218219 /* Foundation.framework */; }; 13 | 63144331CDA950C7800E5CF3A24218FC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEC22C73C1608DFA5D5D78BDCB218219 /* Foundation.framework */; }; 14 | 67BB3846BB9447C6156AB9543A08CE3B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEC22C73C1608DFA5D5D78BDCB218219 /* Foundation.framework */; }; 15 | 87928445D78EF72661BDF753433ABDB4 /* CGRect+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2371CE7C4DF3BB66019C46C0C464874F /* CGRect+Extensions.swift */; }; 16 | 8E5B93E620BFFFD3237EAC4F40F0EC8A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = CEC22C73C1608DFA5D5D78BDCB218219 /* Foundation.framework */; }; 17 | B78692852BEC38605BAEFA7BA06EE70C /* Pods-Demo-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = EE429CDECFF71C9B17B7581C29E09289 /* Pods-Demo-dummy.m */; }; 18 | BB8C27D3E07B8DC70F9F639BB5D28AFB /* Pods-DemoUITests-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0CEC47EDB22CABC7FC768BE2FDC1F67F /* Pods-DemoUITests-dummy.m */; }; 19 | C72A9B187CFD607B707A3404779F18F1 /* Pods-Demo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0A3FE8CA3DA43E2F10B028673F8ECA69 /* Pods-Demo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20 | C840C63721979B78DB8B6FAE70C4D4C2 /* Pods-DemoTests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 36C2719E1B3FB525DB5CBD9D1A2B829D /* Pods-DemoTests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | E5A5EEF58648374957BAE1B094F635E8 /* StatefulTableView-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = BB085B26DF5668529C5A82D189954D93 /* StatefulTableView-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 22 | E7172898F84D90362818805E8345BD85 /* StatefulTableView-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 5F9CF8DFA1EC8BE2C78588018241C7B1 /* StatefulTableView-dummy.m */; }; 23 | EC7F8733FF00448ED303F7B23EC0CDB0 /* StatefulTableDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 072A5BA0BB37C1C638496D3ECDB2B9B6 /* StatefulTableDelegate.swift */; }; 24 | EFC35CF09F980A3A57BC142B91FA922B /* Pods-DemoUITests-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CF945E41BAA9B8CD56288EE504797E2F /* Pods-DemoUITests-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXContainerItemProxy section */ 28 | 18D85051B53FCE6FC22BA9C2CF5306FD /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 31 | proxyType = 1; 32 | remoteGlobalIDString = 3214511D1F9F00A60F9DEB19C260F2E6; 33 | remoteInfo = StatefulTableView; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXFileReference section */ 38 | 00C4AAB18A3BE1C869CD3AF547E3A3A6 /* Pods-DemoUITests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DemoUITests-resources.sh"; sourceTree = ""; }; 39 | 072A5BA0BB37C1C638496D3ECDB2B9B6 /* StatefulTableDelegate.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StatefulTableDelegate.swift; sourceTree = ""; }; 40 | 0A3FE8CA3DA43E2F10B028673F8ECA69 /* Pods-Demo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Demo-umbrella.h"; sourceTree = ""; }; 41 | 0CEC47EDB22CABC7FC768BE2FDC1F67F /* Pods-DemoUITests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-DemoUITests-dummy.m"; sourceTree = ""; }; 42 | 1DE0CED7B7ADB6D7FA8A2262C29A3AA3 /* Pods-DemoTests-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DemoTests-resources.sh"; sourceTree = ""; }; 43 | 1DF3F60EBCC277BC5E7370D1D3646D5F /* Pods-DemoUITests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DemoUITests-frameworks.sh"; sourceTree = ""; }; 44 | 23452F029D36A3CAD8679DCB236D55FD /* Pods-DemoTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DemoTests.release.xcconfig"; sourceTree = ""; }; 45 | 2371CE7C4DF3BB66019C46C0C464874F /* CGRect+Extensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = "CGRect+Extensions.swift"; sourceTree = ""; }; 46 | 275B590F6238E05F9891EA6EBD3DA279 /* Pods-Demo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-Demo.modulemap"; sourceTree = ""; }; 47 | 2924EA9BBAE30808335B493A129B031D /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 48 | 2D40D87A4E8ED69B0CB65F92F9963743 /* Pods-DemoUITests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-DemoUITests-acknowledgements.markdown"; sourceTree = ""; }; 49 | 2F3F7702BE7C307C5C057AFB0C32E858 /* Pods_DemoUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DemoUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 36C2719E1B3FB525DB5CBD9D1A2B829D /* Pods-DemoTests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-DemoTests-umbrella.h"; sourceTree = ""; }; 51 | 3725C8454A52223A8C1118E2779986C3 /* Pods-Demo-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Demo-acknowledgements.markdown"; sourceTree = ""; }; 52 | 3B412D224F2BBF29E39898AD2DD3BB37 /* Pods_DemoTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DemoTests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 404E5B1C8D78FFF68D183DAA0BE5852D /* Pods-DemoTests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-DemoTests.modulemap"; sourceTree = ""; }; 54 | 414DD768A9F987AB6357C878B93FBD60 /* Pods-DemoTests-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DemoTests-frameworks.sh"; sourceTree = ""; }; 55 | 43DA6EB65A515B09514580F4AE3199EE /* Pods-Demo-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Demo-resources.sh"; sourceTree = ""; }; 56 | 449152E5920E5F6A192DE5E9EBEF752E /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 477EB4BA59F5F90F179B503D933CC2C8 /* Pods-DemoTests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-DemoTests-acknowledgements.plist"; sourceTree = ""; }; 58 | 5F9CF8DFA1EC8BE2C78588018241C7B1 /* StatefulTableView-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "StatefulTableView-dummy.m"; sourceTree = ""; }; 59 | 66E0F451469F15360D21A33B3D797686 /* StatefulTableView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = StatefulTableView.swift; sourceTree = ""; }; 60 | 73E00041EFF493EC7874D5568045C518 /* Pods-Demo-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Demo-acknowledgements.plist"; sourceTree = ""; }; 61 | 7AAFBDEF67D6CCF650CBEC8EAE2262F8 /* StatefulTableView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = StatefulTableView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 62 | 7C9EB40DED8019B446FED95A34D662F5 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 63 | 811B9D28A9DD26F441992FA2CEF4D2F8 /* Pods-Demo-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Demo-frameworks.sh"; sourceTree = ""; }; 64 | 857ED152383374E1A48906A22162E08F /* Pods_Demo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Demo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | 8723937E63A08BA7C079E319EEF55233 /* Pods-DemoTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DemoTests.debug.xcconfig"; sourceTree = ""; }; 66 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; 67 | A6015D2D5CA7CEF78BA84D7D44C04FAE /* Pods-DemoUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DemoUITests.debug.xcconfig"; sourceTree = ""; }; 68 | A671FE86FDF46B9B96363CCD555EF468 /* StatefulTableView.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = StatefulTableView.xcconfig; sourceTree = ""; }; 69 | ABE8D144B0D86287A665FAA581D438B5 /* Pods-DemoTests-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-DemoTests-acknowledgements.markdown"; sourceTree = ""; }; 70 | B1569C6DCF82AA7CF84D8B811006EB33 /* Pods-DemoTests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-DemoTests-dummy.m"; sourceTree = ""; }; 71 | B2965FDD73768E96B7AA9AA94792F051 /* Pods-Demo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Demo.debug.xcconfig"; sourceTree = ""; }; 72 | BB085B26DF5668529C5A82D189954D93 /* StatefulTableView-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StatefulTableView-umbrella.h"; sourceTree = ""; }; 73 | BE72B85B034BD5F0B586EF2ACA21698F /* Pods-DemoUITests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-DemoUITests.modulemap"; sourceTree = ""; }; 74 | C68BCEBA269DA3436883DEDA35184BDC /* Pods-DemoUITests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-DemoUITests-acknowledgements.plist"; sourceTree = ""; }; 75 | CA80BAE59278C00FE0C0CF82F7F8D512 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 76 | CEC22C73C1608DFA5D5D78BDCB218219 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 77 | CF945E41BAA9B8CD56288EE504797E2F /* Pods-DemoUITests-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-DemoUITests-umbrella.h"; sourceTree = ""; }; 78 | D13AA07D45D9B98CA6C538095CCA7B6B /* StatefulTableView-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "StatefulTableView-prefix.pch"; sourceTree = ""; }; 79 | D5BB793669D989DF955F53AE43448A23 /* Pods-Demo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Demo.release.xcconfig"; sourceTree = ""; }; 80 | DD3E16589C2E8084D4C4F6914B34DE47 /* StatefulTableView.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = StatefulTableView.modulemap; sourceTree = ""; }; 81 | EE429CDECFF71C9B17B7581C29E09289 /* Pods-Demo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-Demo-dummy.m"; sourceTree = ""; }; 82 | F0E1AEB035E705E526843792E79F16D0 /* Pods-DemoUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DemoUITests.release.xcconfig"; sourceTree = ""; }; 83 | /* End PBXFileReference section */ 84 | 85 | /* Begin PBXFrameworksBuildPhase section */ 86 | 090B3306332580AC7F31489E475F5552 /* Frameworks */ = { 87 | isa = PBXFrameworksBuildPhase; 88 | buildActionMask = 2147483647; 89 | files = ( 90 | 8E5B93E620BFFFD3237EAC4F40F0EC8A /* Foundation.framework in Frameworks */, 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | 83FF2E05D68CBCC529D00B09EF9B0BF7 /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | 67BB3846BB9447C6156AB9543A08CE3B /* Foundation.framework in Frameworks */, 99 | ); 100 | runOnlyForDeploymentPostprocessing = 0; 101 | }; 102 | 87760712E3D448FD54E3EA985F26BB1E /* Frameworks */ = { 103 | isa = PBXFrameworksBuildPhase; 104 | buildActionMask = 2147483647; 105 | files = ( 106 | 610807D5B787A45F792AE0C1F3058C40 /* Foundation.framework in Frameworks */, 107 | ); 108 | runOnlyForDeploymentPostprocessing = 0; 109 | }; 110 | 97B8EA7B11FE6C68994E40DF9BB037A2 /* Frameworks */ = { 111 | isa = PBXFrameworksBuildPhase; 112 | buildActionMask = 2147483647; 113 | files = ( 114 | 63144331CDA950C7800E5CF3A24218FC /* Foundation.framework in Frameworks */, 115 | ); 116 | runOnlyForDeploymentPostprocessing = 0; 117 | }; 118 | /* End PBXFrameworksBuildPhase section */ 119 | 120 | /* Begin PBXGroup section */ 121 | 363659F9FB2D216820FA7470F853EA05 /* Development Pods */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 708565B2C346FE9FCFBCE4FCCD3702EF /* StatefulTableView */, 125 | ); 126 | name = "Development Pods"; 127 | sourceTree = ""; 128 | }; 129 | 3A7CE78D01A05AF4985FFE471D8BA17B /* Support Files */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | CA80BAE59278C00FE0C0CF82F7F8D512 /* Info.plist */, 133 | DD3E16589C2E8084D4C4F6914B34DE47 /* StatefulTableView.modulemap */, 134 | A671FE86FDF46B9B96363CCD555EF468 /* StatefulTableView.xcconfig */, 135 | 5F9CF8DFA1EC8BE2C78588018241C7B1 /* StatefulTableView-dummy.m */, 136 | D13AA07D45D9B98CA6C538095CCA7B6B /* StatefulTableView-prefix.pch */, 137 | BB085B26DF5668529C5A82D189954D93 /* StatefulTableView-umbrella.h */, 138 | ); 139 | name = "Support Files"; 140 | path = "Demo/Pods/Target Support Files/StatefulTableView"; 141 | sourceTree = ""; 142 | }; 143 | 3DCAB2B7CDE207B3958B6CB957FCC758 /* iOS */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | CEC22C73C1608DFA5D5D78BDCB218219 /* Foundation.framework */, 147 | ); 148 | name = iOS; 149 | sourceTree = ""; 150 | }; 151 | 52414E976F9D7C57E90815FA8039AC2D /* Products */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | 857ED152383374E1A48906A22162E08F /* Pods_Demo.framework */, 155 | 3B412D224F2BBF29E39898AD2DD3BB37 /* Pods_DemoTests.framework */, 156 | 2F3F7702BE7C307C5C057AFB0C32E858 /* Pods_DemoUITests.framework */, 157 | 7AAFBDEF67D6CCF650CBEC8EAE2262F8 /* StatefulTableView.framework */, 158 | ); 159 | name = Products; 160 | sourceTree = ""; 161 | }; 162 | 708565B2C346FE9FCFBCE4FCCD3702EF /* StatefulTableView */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | A530C6B414AFA4102E8C21613562A07B /* Sources */, 166 | 3A7CE78D01A05AF4985FFE471D8BA17B /* Support Files */, 167 | ); 168 | name = StatefulTableView; 169 | path = ../..; 170 | sourceTree = ""; 171 | }; 172 | 76A1E3B812C2E79DF0A4B0E391521FFD /* Targets Support Files */ = { 173 | isa = PBXGroup; 174 | children = ( 175 | 9D7934768530B40EE7605AA8CEB70AE9 /* Pods-Demo */, 176 | F5578AA98E6F044FDD2161A8873FC666 /* Pods-DemoTests */, 177 | 8E39F333BE337CEE42D22206D5866962 /* Pods-DemoUITests */, 178 | ); 179 | name = "Targets Support Files"; 180 | sourceTree = ""; 181 | }; 182 | 7DB346D0F39D3F0E887471402A8071AB = { 183 | isa = PBXGroup; 184 | children = ( 185 | 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 186 | 363659F9FB2D216820FA7470F853EA05 /* Development Pods */, 187 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */, 188 | 52414E976F9D7C57E90815FA8039AC2D /* Products */, 189 | 76A1E3B812C2E79DF0A4B0E391521FFD /* Targets Support Files */, 190 | ); 191 | sourceTree = ""; 192 | }; 193 | 8E39F333BE337CEE42D22206D5866962 /* Pods-DemoUITests */ = { 194 | isa = PBXGroup; 195 | children = ( 196 | 2924EA9BBAE30808335B493A129B031D /* Info.plist */, 197 | BE72B85B034BD5F0B586EF2ACA21698F /* Pods-DemoUITests.modulemap */, 198 | 2D40D87A4E8ED69B0CB65F92F9963743 /* Pods-DemoUITests-acknowledgements.markdown */, 199 | C68BCEBA269DA3436883DEDA35184BDC /* Pods-DemoUITests-acknowledgements.plist */, 200 | 0CEC47EDB22CABC7FC768BE2FDC1F67F /* Pods-DemoUITests-dummy.m */, 201 | 1DF3F60EBCC277BC5E7370D1D3646D5F /* Pods-DemoUITests-frameworks.sh */, 202 | 00C4AAB18A3BE1C869CD3AF547E3A3A6 /* Pods-DemoUITests-resources.sh */, 203 | CF945E41BAA9B8CD56288EE504797E2F /* Pods-DemoUITests-umbrella.h */, 204 | A6015D2D5CA7CEF78BA84D7D44C04FAE /* Pods-DemoUITests.debug.xcconfig */, 205 | F0E1AEB035E705E526843792E79F16D0 /* Pods-DemoUITests.release.xcconfig */, 206 | ); 207 | name = "Pods-DemoUITests"; 208 | path = "Target Support Files/Pods-DemoUITests"; 209 | sourceTree = ""; 210 | }; 211 | 9D7934768530B40EE7605AA8CEB70AE9 /* Pods-Demo */ = { 212 | isa = PBXGroup; 213 | children = ( 214 | 449152E5920E5F6A192DE5E9EBEF752E /* Info.plist */, 215 | 275B590F6238E05F9891EA6EBD3DA279 /* Pods-Demo.modulemap */, 216 | 3725C8454A52223A8C1118E2779986C3 /* Pods-Demo-acknowledgements.markdown */, 217 | 73E00041EFF493EC7874D5568045C518 /* Pods-Demo-acknowledgements.plist */, 218 | EE429CDECFF71C9B17B7581C29E09289 /* Pods-Demo-dummy.m */, 219 | 811B9D28A9DD26F441992FA2CEF4D2F8 /* Pods-Demo-frameworks.sh */, 220 | 43DA6EB65A515B09514580F4AE3199EE /* Pods-Demo-resources.sh */, 221 | 0A3FE8CA3DA43E2F10B028673F8ECA69 /* Pods-Demo-umbrella.h */, 222 | B2965FDD73768E96B7AA9AA94792F051 /* Pods-Demo.debug.xcconfig */, 223 | D5BB793669D989DF955F53AE43448A23 /* Pods-Demo.release.xcconfig */, 224 | ); 225 | name = "Pods-Demo"; 226 | path = "Target Support Files/Pods-Demo"; 227 | sourceTree = ""; 228 | }; 229 | A530C6B414AFA4102E8C21613562A07B /* Sources */ = { 230 | isa = PBXGroup; 231 | children = ( 232 | 2371CE7C4DF3BB66019C46C0C464874F /* CGRect+Extensions.swift */, 233 | 072A5BA0BB37C1C638496D3ECDB2B9B6 /* StatefulTableDelegate.swift */, 234 | 66E0F451469F15360D21A33B3D797686 /* StatefulTableView.swift */, 235 | ); 236 | path = Sources; 237 | sourceTree = ""; 238 | }; 239 | BC3CA7F9E30CC8F7E2DD044DD34432FC /* Frameworks */ = { 240 | isa = PBXGroup; 241 | children = ( 242 | 3DCAB2B7CDE207B3958B6CB957FCC758 /* iOS */, 243 | ); 244 | name = Frameworks; 245 | sourceTree = ""; 246 | }; 247 | F5578AA98E6F044FDD2161A8873FC666 /* Pods-DemoTests */ = { 248 | isa = PBXGroup; 249 | children = ( 250 | 7C9EB40DED8019B446FED95A34D662F5 /* Info.plist */, 251 | 404E5B1C8D78FFF68D183DAA0BE5852D /* Pods-DemoTests.modulemap */, 252 | ABE8D144B0D86287A665FAA581D438B5 /* Pods-DemoTests-acknowledgements.markdown */, 253 | 477EB4BA59F5F90F179B503D933CC2C8 /* Pods-DemoTests-acknowledgements.plist */, 254 | B1569C6DCF82AA7CF84D8B811006EB33 /* Pods-DemoTests-dummy.m */, 255 | 414DD768A9F987AB6357C878B93FBD60 /* Pods-DemoTests-frameworks.sh */, 256 | 1DE0CED7B7ADB6D7FA8A2262C29A3AA3 /* Pods-DemoTests-resources.sh */, 257 | 36C2719E1B3FB525DB5CBD9D1A2B829D /* Pods-DemoTests-umbrella.h */, 258 | 8723937E63A08BA7C079E319EEF55233 /* Pods-DemoTests.debug.xcconfig */, 259 | 23452F029D36A3CAD8679DCB236D55FD /* Pods-DemoTests.release.xcconfig */, 260 | ); 261 | name = "Pods-DemoTests"; 262 | path = "Target Support Files/Pods-DemoTests"; 263 | sourceTree = ""; 264 | }; 265 | /* End PBXGroup section */ 266 | 267 | /* Begin PBXHeadersBuildPhase section */ 268 | 207FD4D94C6FEAC3ED48EA552AF0B764 /* Headers */ = { 269 | isa = PBXHeadersBuildPhase; 270 | buildActionMask = 2147483647; 271 | files = ( 272 | E5A5EEF58648374957BAE1B094F635E8 /* StatefulTableView-umbrella.h in Headers */, 273 | ); 274 | runOnlyForDeploymentPostprocessing = 0; 275 | }; 276 | 89FA341EF281172849A89266E093D913 /* Headers */ = { 277 | isa = PBXHeadersBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | C72A9B187CFD607B707A3404779F18F1 /* Pods-Demo-umbrella.h in Headers */, 281 | ); 282 | runOnlyForDeploymentPostprocessing = 0; 283 | }; 284 | C38DC4DF0D32DA799E00BD06F215E191 /* Headers */ = { 285 | isa = PBXHeadersBuildPhase; 286 | buildActionMask = 2147483647; 287 | files = ( 288 | EFC35CF09F980A3A57BC142B91FA922B /* Pods-DemoUITests-umbrella.h in Headers */, 289 | ); 290 | runOnlyForDeploymentPostprocessing = 0; 291 | }; 292 | E42608AF8B4137FA47FFE13BF2155E7C /* Headers */ = { 293 | isa = PBXHeadersBuildPhase; 294 | buildActionMask = 2147483647; 295 | files = ( 296 | C840C63721979B78DB8B6FAE70C4D4C2 /* Pods-DemoTests-umbrella.h in Headers */, 297 | ); 298 | runOnlyForDeploymentPostprocessing = 0; 299 | }; 300 | /* End PBXHeadersBuildPhase section */ 301 | 302 | /* Begin PBXNativeTarget section */ 303 | 3214511D1F9F00A60F9DEB19C260F2E6 /* StatefulTableView */ = { 304 | isa = PBXNativeTarget; 305 | buildConfigurationList = B6A94B253EE97A011AD54B563369556D /* Build configuration list for PBXNativeTarget "StatefulTableView" */; 306 | buildPhases = ( 307 | BA3C8656FBE003BB4BD04CCE7F814E66 /* Sources */, 308 | 87760712E3D448FD54E3EA985F26BB1E /* Frameworks */, 309 | 207FD4D94C6FEAC3ED48EA552AF0B764 /* Headers */, 310 | ); 311 | buildRules = ( 312 | ); 313 | dependencies = ( 314 | ); 315 | name = StatefulTableView; 316 | productName = StatefulTableView; 317 | productReference = 7AAFBDEF67D6CCF650CBEC8EAE2262F8 /* StatefulTableView.framework */; 318 | productType = "com.apple.product-type.framework"; 319 | }; 320 | 3B92E1438BE19D20B9C5A4FA07A18BE9 /* Pods-Demo */ = { 321 | isa = PBXNativeTarget; 322 | buildConfigurationList = 51EC227A5307E3367E6751995B945C22 /* Build configuration list for PBXNativeTarget "Pods-Demo" */; 323 | buildPhases = ( 324 | D93FC75A318E786DF26B352394AA3F6A /* Sources */, 325 | 090B3306332580AC7F31489E475F5552 /* Frameworks */, 326 | 89FA341EF281172849A89266E093D913 /* Headers */, 327 | ); 328 | buildRules = ( 329 | ); 330 | dependencies = ( 331 | 44E298421443E9697B89C45BE575755B /* PBXTargetDependency */, 332 | ); 333 | name = "Pods-Demo"; 334 | productName = "Pods-Demo"; 335 | productReference = 857ED152383374E1A48906A22162E08F /* Pods_Demo.framework */; 336 | productType = "com.apple.product-type.framework"; 337 | }; 338 | 453074D35513325004193CCE83D6A334 /* Pods-DemoUITests */ = { 339 | isa = PBXNativeTarget; 340 | buildConfigurationList = 2352CB33E448FAF32C50E1D72B893D85 /* Build configuration list for PBXNativeTarget "Pods-DemoUITests" */; 341 | buildPhases = ( 342 | 369D347409EAAE33219C9F9B8BA3D8B4 /* Sources */, 343 | 97B8EA7B11FE6C68994E40DF9BB037A2 /* Frameworks */, 344 | C38DC4DF0D32DA799E00BD06F215E191 /* Headers */, 345 | ); 346 | buildRules = ( 347 | ); 348 | dependencies = ( 349 | ); 350 | name = "Pods-DemoUITests"; 351 | productName = "Pods-DemoUITests"; 352 | productReference = 2F3F7702BE7C307C5C057AFB0C32E858 /* Pods_DemoUITests.framework */; 353 | productType = "com.apple.product-type.framework"; 354 | }; 355 | D548370457DEA9E612AB613DECEC925E /* Pods-DemoTests */ = { 356 | isa = PBXNativeTarget; 357 | buildConfigurationList = 129101A10255AE6EF678510690CB0DC8 /* Build configuration list for PBXNativeTarget "Pods-DemoTests" */; 358 | buildPhases = ( 359 | 26AE9AEA8E27FEBBA340FEA7A0ADB024 /* Sources */, 360 | 83FF2E05D68CBCC529D00B09EF9B0BF7 /* Frameworks */, 361 | E42608AF8B4137FA47FFE13BF2155E7C /* Headers */, 362 | ); 363 | buildRules = ( 364 | ); 365 | dependencies = ( 366 | ); 367 | name = "Pods-DemoTests"; 368 | productName = "Pods-DemoTests"; 369 | productReference = 3B412D224F2BBF29E39898AD2DD3BB37 /* Pods_DemoTests.framework */; 370 | productType = "com.apple.product-type.framework"; 371 | }; 372 | /* End PBXNativeTarget section */ 373 | 374 | /* Begin PBXProject section */ 375 | D41D8CD98F00B204E9800998ECF8427E /* Project object */ = { 376 | isa = PBXProject; 377 | attributes = { 378 | LastSwiftUpdateCheck = 0730; 379 | LastUpgradeCheck = 0700; 380 | }; 381 | buildConfigurationList = 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */; 382 | compatibilityVersion = "Xcode 3.2"; 383 | developmentRegion = English; 384 | hasScannedForEncodings = 0; 385 | knownRegions = ( 386 | en, 387 | ); 388 | mainGroup = 7DB346D0F39D3F0E887471402A8071AB; 389 | productRefGroup = 52414E976F9D7C57E90815FA8039AC2D /* Products */; 390 | projectDirPath = ""; 391 | projectRoot = ""; 392 | targets = ( 393 | 3B92E1438BE19D20B9C5A4FA07A18BE9 /* Pods-Demo */, 394 | D548370457DEA9E612AB613DECEC925E /* Pods-DemoTests */, 395 | 453074D35513325004193CCE83D6A334 /* Pods-DemoUITests */, 396 | 3214511D1F9F00A60F9DEB19C260F2E6 /* StatefulTableView */, 397 | ); 398 | }; 399 | /* End PBXProject section */ 400 | 401 | /* Begin PBXSourcesBuildPhase section */ 402 | 26AE9AEA8E27FEBBA340FEA7A0ADB024 /* Sources */ = { 403 | isa = PBXSourcesBuildPhase; 404 | buildActionMask = 2147483647; 405 | files = ( 406 | 4C012D74EEB3B8E39B3EB083663682D1 /* Pods-DemoTests-dummy.m in Sources */, 407 | ); 408 | runOnlyForDeploymentPostprocessing = 0; 409 | }; 410 | 369D347409EAAE33219C9F9B8BA3D8B4 /* Sources */ = { 411 | isa = PBXSourcesBuildPhase; 412 | buildActionMask = 2147483647; 413 | files = ( 414 | BB8C27D3E07B8DC70F9F639BB5D28AFB /* Pods-DemoUITests-dummy.m in Sources */, 415 | ); 416 | runOnlyForDeploymentPostprocessing = 0; 417 | }; 418 | BA3C8656FBE003BB4BD04CCE7F814E66 /* Sources */ = { 419 | isa = PBXSourcesBuildPhase; 420 | buildActionMask = 2147483647; 421 | files = ( 422 | 87928445D78EF72661BDF753433ABDB4 /* CGRect+Extensions.swift in Sources */, 423 | EC7F8733FF00448ED303F7B23EC0CDB0 /* StatefulTableDelegate.swift in Sources */, 424 | E7172898F84D90362818805E8345BD85 /* StatefulTableView-dummy.m in Sources */, 425 | 0E36B00605783AE35801FA8BC2696DA6 /* StatefulTableView.swift in Sources */, 426 | ); 427 | runOnlyForDeploymentPostprocessing = 0; 428 | }; 429 | D93FC75A318E786DF26B352394AA3F6A /* Sources */ = { 430 | isa = PBXSourcesBuildPhase; 431 | buildActionMask = 2147483647; 432 | files = ( 433 | B78692852BEC38605BAEFA7BA06EE70C /* Pods-Demo-dummy.m in Sources */, 434 | ); 435 | runOnlyForDeploymentPostprocessing = 0; 436 | }; 437 | /* End PBXSourcesBuildPhase section */ 438 | 439 | /* Begin PBXTargetDependency section */ 440 | 44E298421443E9697B89C45BE575755B /* PBXTargetDependency */ = { 441 | isa = PBXTargetDependency; 442 | name = StatefulTableView; 443 | target = 3214511D1F9F00A60F9DEB19C260F2E6 /* StatefulTableView */; 444 | targetProxy = 18D85051B53FCE6FC22BA9C2CF5306FD /* PBXContainerItemProxy */; 445 | }; 446 | /* End PBXTargetDependency section */ 447 | 448 | /* Begin XCBuildConfiguration section */ 449 | 07D95F8A99807BA79AEA56910A649394 /* Release */ = { 450 | isa = XCBuildConfiguration; 451 | baseConfigurationReference = F0E1AEB035E705E526843792E79F16D0 /* Pods-DemoUITests.release.xcconfig */; 452 | buildSettings = { 453 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 454 | CURRENT_PROJECT_VERSION = 1; 455 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 456 | DEFINES_MODULE = YES; 457 | DYLIB_COMPATIBILITY_VERSION = 1; 458 | DYLIB_CURRENT_VERSION = 1; 459 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 460 | ENABLE_STRICT_OBJC_MSGSEND = YES; 461 | GCC_NO_COMMON_BLOCKS = YES; 462 | INFOPLIST_FILE = "Target Support Files/Pods-DemoUITests/Info.plist"; 463 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 464 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 465 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 466 | MACH_O_TYPE = staticlib; 467 | MODULEMAP_FILE = "Target Support Files/Pods-DemoUITests/Pods-DemoUITests.modulemap"; 468 | MTL_ENABLE_DEBUG_INFO = NO; 469 | OTHER_LDFLAGS = ""; 470 | OTHER_LIBTOOLFLAGS = ""; 471 | PODS_ROOT = "$(SRCROOT)"; 472 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 473 | PRODUCT_NAME = Pods_DemoUITests; 474 | SDKROOT = iphoneos; 475 | SKIP_INSTALL = YES; 476 | TARGETED_DEVICE_FAMILY = "1,2"; 477 | VERSIONING_SYSTEM = "apple-generic"; 478 | VERSION_INFO_PREFIX = ""; 479 | }; 480 | name = Release; 481 | }; 482 | 2EE348D5C0F86BC6A7EDEBAAFBB35DC4 /* Debug */ = { 483 | isa = XCBuildConfiguration; 484 | baseConfigurationReference = 8723937E63A08BA7C079E319EEF55233 /* Pods-DemoTests.debug.xcconfig */; 485 | buildSettings = { 486 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 487 | CURRENT_PROJECT_VERSION = 1; 488 | DEBUG_INFORMATION_FORMAT = dwarf; 489 | DEFINES_MODULE = YES; 490 | DYLIB_COMPATIBILITY_VERSION = 1; 491 | DYLIB_CURRENT_VERSION = 1; 492 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 493 | ENABLE_STRICT_OBJC_MSGSEND = YES; 494 | GCC_NO_COMMON_BLOCKS = YES; 495 | INFOPLIST_FILE = "Target Support Files/Pods-DemoTests/Info.plist"; 496 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 497 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 498 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 499 | MACH_O_TYPE = staticlib; 500 | MODULEMAP_FILE = "Target Support Files/Pods-DemoTests/Pods-DemoTests.modulemap"; 501 | MTL_ENABLE_DEBUG_INFO = YES; 502 | OTHER_LDFLAGS = ""; 503 | OTHER_LIBTOOLFLAGS = ""; 504 | PODS_ROOT = "$(SRCROOT)"; 505 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 506 | PRODUCT_NAME = Pods_DemoTests; 507 | SDKROOT = iphoneos; 508 | SKIP_INSTALL = YES; 509 | TARGETED_DEVICE_FAMILY = "1,2"; 510 | VERSIONING_SYSTEM = "apple-generic"; 511 | VERSION_INFO_PREFIX = ""; 512 | }; 513 | name = Debug; 514 | }; 515 | 46DF7438E1BFED199432D8984F2110D3 /* Debug */ = { 516 | isa = XCBuildConfiguration; 517 | baseConfigurationReference = B2965FDD73768E96B7AA9AA94792F051 /* Pods-Demo.debug.xcconfig */; 518 | buildSettings = { 519 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 520 | CURRENT_PROJECT_VERSION = 1; 521 | DEBUG_INFORMATION_FORMAT = dwarf; 522 | DEFINES_MODULE = YES; 523 | DYLIB_COMPATIBILITY_VERSION = 1; 524 | DYLIB_CURRENT_VERSION = 1; 525 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 526 | ENABLE_STRICT_OBJC_MSGSEND = YES; 527 | GCC_NO_COMMON_BLOCKS = YES; 528 | INFOPLIST_FILE = "Target Support Files/Pods-Demo/Info.plist"; 529 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 530 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 531 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 532 | MACH_O_TYPE = staticlib; 533 | MODULEMAP_FILE = "Target Support Files/Pods-Demo/Pods-Demo.modulemap"; 534 | MTL_ENABLE_DEBUG_INFO = YES; 535 | OTHER_LDFLAGS = ""; 536 | OTHER_LIBTOOLFLAGS = ""; 537 | PODS_ROOT = "$(SRCROOT)"; 538 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 539 | PRODUCT_NAME = Pods_Demo; 540 | SDKROOT = iphoneos; 541 | SKIP_INSTALL = YES; 542 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 543 | TARGETED_DEVICE_FAMILY = "1,2"; 544 | VERSIONING_SYSTEM = "apple-generic"; 545 | VERSION_INFO_PREFIX = ""; 546 | }; 547 | name = Debug; 548 | }; 549 | 47BEF9D903506B003EA5C2B249729489 /* Debug */ = { 550 | isa = XCBuildConfiguration; 551 | buildSettings = { 552 | ALWAYS_SEARCH_USER_PATHS = NO; 553 | CLANG_ANALYZER_NONNULL = YES; 554 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 555 | CLANG_CXX_LIBRARY = "libc++"; 556 | CLANG_ENABLE_MODULES = YES; 557 | CLANG_ENABLE_OBJC_ARC = YES; 558 | CLANG_WARN_BOOL_CONVERSION = YES; 559 | CLANG_WARN_CONSTANT_CONVERSION = YES; 560 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 561 | CLANG_WARN_EMPTY_BODY = YES; 562 | CLANG_WARN_ENUM_CONVERSION = YES; 563 | CLANG_WARN_INT_CONVERSION = YES; 564 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 565 | CLANG_WARN_UNREACHABLE_CODE = YES; 566 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 567 | COPY_PHASE_STRIP = NO; 568 | ENABLE_TESTABILITY = YES; 569 | GCC_C_LANGUAGE_STANDARD = gnu99; 570 | GCC_DYNAMIC_NO_PIC = NO; 571 | GCC_OPTIMIZATION_LEVEL = 0; 572 | GCC_PREPROCESSOR_DEFINITIONS = ( 573 | "POD_CONFIGURATION_DEBUG=1", 574 | "DEBUG=1", 575 | "$(inherited)", 576 | ); 577 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 578 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 579 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 580 | GCC_WARN_UNDECLARED_SELECTOR = YES; 581 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 582 | GCC_WARN_UNUSED_FUNCTION = YES; 583 | GCC_WARN_UNUSED_VARIABLE = YES; 584 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 585 | ONLY_ACTIVE_ARCH = YES; 586 | STRIP_INSTALLED_PRODUCT = NO; 587 | SYMROOT = "${SRCROOT}/../build"; 588 | }; 589 | name = Debug; 590 | }; 591 | 5997B098846F64B6EFBD0EE0C6D0EDA5 /* Release */ = { 592 | isa = XCBuildConfiguration; 593 | baseConfigurationReference = D5BB793669D989DF955F53AE43448A23 /* Pods-Demo.release.xcconfig */; 594 | buildSettings = { 595 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 596 | CURRENT_PROJECT_VERSION = 1; 597 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 598 | DEFINES_MODULE = YES; 599 | DYLIB_COMPATIBILITY_VERSION = 1; 600 | DYLIB_CURRENT_VERSION = 1; 601 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 602 | ENABLE_STRICT_OBJC_MSGSEND = YES; 603 | GCC_NO_COMMON_BLOCKS = YES; 604 | INFOPLIST_FILE = "Target Support Files/Pods-Demo/Info.plist"; 605 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 606 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 607 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 608 | MACH_O_TYPE = staticlib; 609 | MODULEMAP_FILE = "Target Support Files/Pods-Demo/Pods-Demo.modulemap"; 610 | MTL_ENABLE_DEBUG_INFO = NO; 611 | OTHER_LDFLAGS = ""; 612 | OTHER_LIBTOOLFLAGS = ""; 613 | PODS_ROOT = "$(SRCROOT)"; 614 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 615 | PRODUCT_NAME = Pods_Demo; 616 | SDKROOT = iphoneos; 617 | SKIP_INSTALL = YES; 618 | TARGETED_DEVICE_FAMILY = "1,2"; 619 | VERSIONING_SYSTEM = "apple-generic"; 620 | VERSION_INFO_PREFIX = ""; 621 | }; 622 | name = Release; 623 | }; 624 | 78C91B716809272D1B0F1ECC39623D75 /* Release */ = { 625 | isa = XCBuildConfiguration; 626 | baseConfigurationReference = 23452F029D36A3CAD8679DCB236D55FD /* Pods-DemoTests.release.xcconfig */; 627 | buildSettings = { 628 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 629 | CURRENT_PROJECT_VERSION = 1; 630 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 631 | DEFINES_MODULE = YES; 632 | DYLIB_COMPATIBILITY_VERSION = 1; 633 | DYLIB_CURRENT_VERSION = 1; 634 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 635 | ENABLE_STRICT_OBJC_MSGSEND = YES; 636 | GCC_NO_COMMON_BLOCKS = YES; 637 | INFOPLIST_FILE = "Target Support Files/Pods-DemoTests/Info.plist"; 638 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 639 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 640 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 641 | MACH_O_TYPE = staticlib; 642 | MODULEMAP_FILE = "Target Support Files/Pods-DemoTests/Pods-DemoTests.modulemap"; 643 | MTL_ENABLE_DEBUG_INFO = NO; 644 | OTHER_LDFLAGS = ""; 645 | OTHER_LIBTOOLFLAGS = ""; 646 | PODS_ROOT = "$(SRCROOT)"; 647 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 648 | PRODUCT_NAME = Pods_DemoTests; 649 | SDKROOT = iphoneos; 650 | SKIP_INSTALL = YES; 651 | TARGETED_DEVICE_FAMILY = "1,2"; 652 | VERSIONING_SYSTEM = "apple-generic"; 653 | VERSION_INFO_PREFIX = ""; 654 | }; 655 | name = Release; 656 | }; 657 | AAF678CED40D3499169D10F63CA0719E /* Release */ = { 658 | isa = XCBuildConfiguration; 659 | buildSettings = { 660 | ALWAYS_SEARCH_USER_PATHS = NO; 661 | CLANG_ANALYZER_NONNULL = YES; 662 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 663 | CLANG_CXX_LIBRARY = "libc++"; 664 | CLANG_ENABLE_MODULES = YES; 665 | CLANG_ENABLE_OBJC_ARC = YES; 666 | CLANG_WARN_BOOL_CONVERSION = YES; 667 | CLANG_WARN_CONSTANT_CONVERSION = YES; 668 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; 669 | CLANG_WARN_EMPTY_BODY = YES; 670 | CLANG_WARN_ENUM_CONVERSION = YES; 671 | CLANG_WARN_INT_CONVERSION = YES; 672 | CLANG_WARN_OBJC_ROOT_CLASS = YES; 673 | CLANG_WARN_UNREACHABLE_CODE = YES; 674 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 675 | COPY_PHASE_STRIP = YES; 676 | ENABLE_NS_ASSERTIONS = NO; 677 | GCC_C_LANGUAGE_STANDARD = gnu99; 678 | GCC_PREPROCESSOR_DEFINITIONS = ( 679 | "POD_CONFIGURATION_RELEASE=1", 680 | "$(inherited)", 681 | ); 682 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 683 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 684 | GCC_WARN_UNDECLARED_SELECTOR = YES; 685 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 686 | GCC_WARN_UNUSED_FUNCTION = YES; 687 | GCC_WARN_UNUSED_VARIABLE = YES; 688 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 689 | STRIP_INSTALLED_PRODUCT = NO; 690 | SYMROOT = "${SRCROOT}/../build"; 691 | VALIDATE_PRODUCT = YES; 692 | }; 693 | name = Release; 694 | }; 695 | EAA95C1B5BC8741ADB999C8307E0607E /* Debug */ = { 696 | isa = XCBuildConfiguration; 697 | baseConfigurationReference = A671FE86FDF46B9B96363CCD555EF468 /* StatefulTableView.xcconfig */; 698 | buildSettings = { 699 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 700 | CURRENT_PROJECT_VERSION = 1; 701 | DEBUG_INFORMATION_FORMAT = dwarf; 702 | DEFINES_MODULE = YES; 703 | DYLIB_COMPATIBILITY_VERSION = 1; 704 | DYLIB_CURRENT_VERSION = 1; 705 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 706 | ENABLE_STRICT_OBJC_MSGSEND = YES; 707 | GCC_NO_COMMON_BLOCKS = YES; 708 | GCC_PREFIX_HEADER = "Target Support Files/StatefulTableView/StatefulTableView-prefix.pch"; 709 | INFOPLIST_FILE = "Target Support Files/StatefulTableView/Info.plist"; 710 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 711 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 712 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 713 | MODULEMAP_FILE = "Target Support Files/StatefulTableView/StatefulTableView.modulemap"; 714 | MTL_ENABLE_DEBUG_INFO = YES; 715 | PRODUCT_NAME = StatefulTableView; 716 | SDKROOT = iphoneos; 717 | SKIP_INSTALL = YES; 718 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 719 | TARGETED_DEVICE_FAMILY = "1,2"; 720 | VERSIONING_SYSTEM = "apple-generic"; 721 | VERSION_INFO_PREFIX = ""; 722 | }; 723 | name = Debug; 724 | }; 725 | F982FA552139A988ADC2953024A4C469 /* Release */ = { 726 | isa = XCBuildConfiguration; 727 | baseConfigurationReference = A671FE86FDF46B9B96363CCD555EF468 /* StatefulTableView.xcconfig */; 728 | buildSettings = { 729 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 730 | CURRENT_PROJECT_VERSION = 1; 731 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 732 | DEFINES_MODULE = YES; 733 | DYLIB_COMPATIBILITY_VERSION = 1; 734 | DYLIB_CURRENT_VERSION = 1; 735 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 736 | ENABLE_STRICT_OBJC_MSGSEND = YES; 737 | GCC_NO_COMMON_BLOCKS = YES; 738 | GCC_PREFIX_HEADER = "Target Support Files/StatefulTableView/StatefulTableView-prefix.pch"; 739 | INFOPLIST_FILE = "Target Support Files/StatefulTableView/Info.plist"; 740 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 741 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 742 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 743 | MODULEMAP_FILE = "Target Support Files/StatefulTableView/StatefulTableView.modulemap"; 744 | MTL_ENABLE_DEBUG_INFO = NO; 745 | PRODUCT_NAME = StatefulTableView; 746 | SDKROOT = iphoneos; 747 | SKIP_INSTALL = YES; 748 | TARGETED_DEVICE_FAMILY = "1,2"; 749 | VERSIONING_SYSTEM = "apple-generic"; 750 | VERSION_INFO_PREFIX = ""; 751 | }; 752 | name = Release; 753 | }; 754 | FC41A394AD2F8340F01A4C692E058F0B /* Debug */ = { 755 | isa = XCBuildConfiguration; 756 | baseConfigurationReference = A6015D2D5CA7CEF78BA84D7D44C04FAE /* Pods-DemoUITests.debug.xcconfig */; 757 | buildSettings = { 758 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 759 | CURRENT_PROJECT_VERSION = 1; 760 | DEBUG_INFORMATION_FORMAT = dwarf; 761 | DEFINES_MODULE = YES; 762 | DYLIB_COMPATIBILITY_VERSION = 1; 763 | DYLIB_CURRENT_VERSION = 1; 764 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 765 | ENABLE_STRICT_OBJC_MSGSEND = YES; 766 | GCC_NO_COMMON_BLOCKS = YES; 767 | INFOPLIST_FILE = "Target Support Files/Pods-DemoUITests/Info.plist"; 768 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 769 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 770 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 771 | MACH_O_TYPE = staticlib; 772 | MODULEMAP_FILE = "Target Support Files/Pods-DemoUITests/Pods-DemoUITests.modulemap"; 773 | MTL_ENABLE_DEBUG_INFO = YES; 774 | OTHER_LDFLAGS = ""; 775 | OTHER_LIBTOOLFLAGS = ""; 776 | PODS_ROOT = "$(SRCROOT)"; 777 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; 778 | PRODUCT_NAME = Pods_DemoUITests; 779 | SDKROOT = iphoneos; 780 | SKIP_INSTALL = YES; 781 | TARGETED_DEVICE_FAMILY = "1,2"; 782 | VERSIONING_SYSTEM = "apple-generic"; 783 | VERSION_INFO_PREFIX = ""; 784 | }; 785 | name = Debug; 786 | }; 787 | /* End XCBuildConfiguration section */ 788 | 789 | /* Begin XCConfigurationList section */ 790 | 129101A10255AE6EF678510690CB0DC8 /* Build configuration list for PBXNativeTarget "Pods-DemoTests" */ = { 791 | isa = XCConfigurationList; 792 | buildConfigurations = ( 793 | 2EE348D5C0F86BC6A7EDEBAAFBB35DC4 /* Debug */, 794 | 78C91B716809272D1B0F1ECC39623D75 /* Release */, 795 | ); 796 | defaultConfigurationIsVisible = 0; 797 | defaultConfigurationName = Release; 798 | }; 799 | 2352CB33E448FAF32C50E1D72B893D85 /* Build configuration list for PBXNativeTarget "Pods-DemoUITests" */ = { 800 | isa = XCConfigurationList; 801 | buildConfigurations = ( 802 | FC41A394AD2F8340F01A4C692E058F0B /* Debug */, 803 | 07D95F8A99807BA79AEA56910A649394 /* Release */, 804 | ); 805 | defaultConfigurationIsVisible = 0; 806 | defaultConfigurationName = Release; 807 | }; 808 | 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { 809 | isa = XCConfigurationList; 810 | buildConfigurations = ( 811 | 47BEF9D903506B003EA5C2B249729489 /* Debug */, 812 | AAF678CED40D3499169D10F63CA0719E /* Release */, 813 | ); 814 | defaultConfigurationIsVisible = 0; 815 | defaultConfigurationName = Release; 816 | }; 817 | 51EC227A5307E3367E6751995B945C22 /* Build configuration list for PBXNativeTarget "Pods-Demo" */ = { 818 | isa = XCConfigurationList; 819 | buildConfigurations = ( 820 | 46DF7438E1BFED199432D8984F2110D3 /* Debug */, 821 | 5997B098846F64B6EFBD0EE0C6D0EDA5 /* Release */, 822 | ); 823 | defaultConfigurationIsVisible = 0; 824 | defaultConfigurationName = Release; 825 | }; 826 | B6A94B253EE97A011AD54B563369556D /* Build configuration list for PBXNativeTarget "StatefulTableView" */ = { 827 | isa = XCConfigurationList; 828 | buildConfigurations = ( 829 | EAA95C1B5BC8741ADB999C8307E0607E /* Debug */, 830 | F982FA552139A988ADC2953024A4C469 /* Release */, 831 | ); 832 | defaultConfigurationIsVisible = 0; 833 | defaultConfigurationName = Release; 834 | }; 835 | /* End XCConfigurationList section */ 836 | }; 837 | rootObject = D41D8CD98F00B204E9800998ECF8427E /* Project object */; 838 | } 839 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## StatefulTableView 5 | 6 | The MIT License (MIT) 7 | 8 | Copyright (c) 2016 timominous 9 | 10 | Permission is hereby granted, free of charge, to any person obtaining a copy 11 | of this software and associated documentation files (the "Software"), to deal 12 | in the Software without restriction, including without limitation the rights 13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | copies of the Software, and to permit persons to whom the Software is 15 | furnished to do so, subject to the following conditions: 16 | 17 | The above copyright notice and this permission notice shall be included in all 18 | copies or substantial portions of the Software. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 26 | SOFTWARE. 27 | 28 | Generated by CocoaPods - https://cocoapods.org 29 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | The MIT License (MIT) 18 | 19 | Copyright (c) 2016 timominous 20 | 21 | Permission is hereby granted, free of charge, to any person obtaining a copy 22 | of this software and associated documentation files (the "Software"), to deal 23 | in the Software without restriction, including without limitation the rights 24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 25 | copies of the Software, and to permit persons to whom the Software is 26 | furnished to do so, subject to the following conditions: 27 | 28 | The above copyright notice and this permission notice shall be included in all 29 | copies or substantial portions of the Software. 30 | 31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 37 | SOFTWARE. 38 | 39 | Title 40 | StatefulTableView 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Demo : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Demo 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 5 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 6 | 7 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 8 | 9 | install_framework() 10 | { 11 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 12 | local source="${BUILT_PRODUCTS_DIR}/$1" 13 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 14 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 15 | elif [ -r "$1" ]; then 16 | local source="$1" 17 | fi 18 | 19 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 20 | 21 | if [ -L "${source}" ]; then 22 | echo "Symlinked..." 23 | source="$(readlink "${source}")" 24 | fi 25 | 26 | # use filter instead of exclude so missing patterns dont' throw errors 27 | echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 28 | rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 29 | 30 | local basename 31 | basename="$(basename -s .framework "$1")" 32 | binary="${destination}/${basename}.framework/${basename}" 33 | if ! [ -r "$binary" ]; then 34 | binary="${destination}/${basename}" 35 | fi 36 | 37 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 38 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 39 | strip_invalid_archs "$binary" 40 | fi 41 | 42 | # Resign the code if required by the build settings to avoid unstable apps 43 | code_sign_if_enabled "${destination}/$(basename "$1")" 44 | 45 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 46 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 47 | local swift_runtime_libs 48 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 49 | for lib in $swift_runtime_libs; do 50 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 51 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 52 | code_sign_if_enabled "${destination}/${lib}" 53 | done 54 | fi 55 | } 56 | 57 | # Signs a framework with the provided identity 58 | code_sign_if_enabled() { 59 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 60 | # Use the current code_sign_identitiy 61 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 62 | echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements \"$1\"" 63 | /usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS} --preserve-metadata=identifier,entitlements "$1" 64 | fi 65 | } 66 | 67 | # Strip invalid architectures 68 | strip_invalid_archs() { 69 | binary="$1" 70 | # Get architectures for current file 71 | archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" 72 | stripped="" 73 | for arch in $archs; do 74 | if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then 75 | # Strip non-valid architectures in-place 76 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 77 | stripped="$stripped $arch" 78 | fi 79 | done 80 | if [[ "$stripped" ]]; then 81 | echo "Stripped $binary of architectures:$stripped" 82 | fi 83 | } 84 | 85 | 86 | if [[ "$CONFIGURATION" == "Debug" ]]; then 87 | install_framework "$BUILT_PRODUCTS_DIR/StatefulTableView/StatefulTableView.framework" 88 | fi 89 | if [[ "$CONFIGURATION" == "Release" ]]; then 90 | install_framework "$BUILT_PRODUCTS_DIR/StatefulTableView/StatefulTableView.framework" 91 | fi 92 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 5 | 6 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 7 | > "$RESOURCES_TO_COPY" 8 | 9 | XCASSET_FILES=() 10 | 11 | case "${TARGETED_DEVICE_FAMILY}" in 12 | 1,2) 13 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 14 | ;; 15 | 1) 16 | TARGET_DEVICE_ARGS="--target-device iphone" 17 | ;; 18 | 2) 19 | TARGET_DEVICE_ARGS="--target-device ipad" 20 | ;; 21 | *) 22 | TARGET_DEVICE_ARGS="--target-device mac" 23 | ;; 24 | esac 25 | 26 | realpath() { 27 | DIRECTORY="$(cd "${1%/*}" && pwd)" 28 | FILENAME="${1##*/}" 29 | echo "$DIRECTORY/$FILENAME" 30 | } 31 | 32 | install_resource() 33 | { 34 | if [[ "$1" = /* ]] ; then 35 | RESOURCE_PATH="$1" 36 | else 37 | RESOURCE_PATH="${PODS_ROOT}/$1" 38 | fi 39 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 40 | cat << EOM 41 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 42 | EOM 43 | exit 1 44 | fi 45 | case $RESOURCE_PATH in 46 | *.storyboard) 47 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" 48 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 49 | ;; 50 | *.xib) 51 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT}" 52 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" 53 | ;; 54 | *.framework) 55 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 56 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 57 | echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 58 | rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 59 | ;; 60 | *.xcdatamodel) 61 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" 62 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 63 | ;; 64 | *.xcdatamodeld) 65 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" 66 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 67 | ;; 68 | *.xcmappingmodel) 69 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" 70 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 71 | ;; 72 | *.xcassets) 73 | ABSOLUTE_XCASSET_FILE=$(realpath "$RESOURCE_PATH") 74 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 75 | ;; 76 | *) 77 | echo "$RESOURCE_PATH" 78 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 79 | ;; 80 | esac 81 | } 82 | 83 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 84 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 85 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 86 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 87 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 88 | fi 89 | rm -f "$RESOURCES_TO_COPY" 90 | 91 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "$XCASSET_FILES" ] 92 | then 93 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 94 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 95 | while read line; do 96 | if [[ $line != "`realpath $PODS_ROOT`*" ]]; then 97 | XCASSET_FILES+=("$line") 98 | fi 99 | done <<<"$OTHER_XCASSETS" 100 | 101 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 102 | fi 103 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double Pods_DemoVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char Pods_DemoVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.debug.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/StatefulTableView" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/StatefulTableView/StatefulTableView.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "StatefulTableView" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Demo { 2 | umbrella header "Pods-Demo-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/Pods-Demo/Pods-Demo.release.xcconfig: -------------------------------------------------------------------------------- 1 | EMBEDDED_CONTENT_CONTAINS_SWIFT = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "$PODS_CONFIGURATION_BUILD_DIR/StatefulTableView" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "$PODS_CONFIGURATION_BUILD_DIR/StatefulTableView/StatefulTableView.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "StatefulTableView" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = $BUILD_DIR 9 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_ROOT = ${SRCROOT}/Pods 11 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/StatefulTableView/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.0.7 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/StatefulTableView/StatefulTableView-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_StatefulTableView : NSObject 3 | @end 4 | @implementation PodsDummy_StatefulTableView 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/StatefulTableView/StatefulTableView-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #endif 4 | 5 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/StatefulTableView/StatefulTableView-umbrella.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | FOUNDATION_EXPORT double StatefulTableViewVersionNumber; 5 | FOUNDATION_EXPORT const unsigned char StatefulTableViewVersionString[]; 6 | 7 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/StatefulTableView/StatefulTableView.modulemap: -------------------------------------------------------------------------------- 1 | framework module StatefulTableView { 2 | umbrella header "StatefulTableView-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Pods/Target Support Files/StatefulTableView/StatefulTableView.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = $PODS_CONFIGURATION_BUILD_DIR/StatefulTableView 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | HEADER_SEARCH_PATHS = "${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Public" 4 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 5 | PODS_BUILD_DIR = $BUILD_DIR 6 | PODS_CONFIGURATION_BUILD_DIR = $PODS_BUILD_DIR/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 timominous 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 | # StatefulTableView 2 | 3 | Custom UITableView container class that supports pull-to-refresh, load-more, initial load, and empty states. This library aims to be a drop in replacement for `UITableView`. Swift port of [SKStatefulTableViewController](http://github.com/shiki/SKStatefulTableViewController). 4 | 5 | This is a *work in progress*. A lot of things may break as of the moment. 6 | 7 | ## Installation 8 | 9 | ### Cocoapods 10 | 11 | Add this to your Podfile. 12 | 13 | ```ruby 14 | pod 'StatefulTableView', '0.0.8' 15 | ``` 16 | 17 | ### Credits 18 | 19 | * [SKStatefulTableViewController](http://github.com/shiki/SKStatefulTableViewController) by [shiki](http://github.com/shiki) 20 | -------------------------------------------------------------------------------- /Sources/CGRect+Extensions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGRect+Extensions.swift 3 | // Demo 4 | // 5 | // Created by Tim on 13/05/2016. 6 | // Copyright © 2016 timominous. All rights reserved. 7 | // 8 | 9 | import CoreGraphics 10 | 11 | public extension CGRect { 12 | mutating func centerInFrame(bounds: CGRect) { 13 | origin.x = (bounds.width - width) * 0.5 14 | origin.y = (bounds.height - height) * 0.5 15 | } 16 | } -------------------------------------------------------------------------------- /Sources/StatefulTableDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StatefulTableDelegate.swift 3 | // Demo 4 | // 5 | // Created by Tim on 12/05/2016. 6 | // Copyright © 2016 timominous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public typealias InitialLoadCompletionHandler = (tableIsEmpty: Bool, errorOrNil: NSError?) -> Void 12 | public typealias LoadMoreCompletionHandler = (canLoadMore: Bool, errorOrNil: NSError?, showErrorView: Bool) -> Void 13 | 14 | public protocol StatefulTableDelegate { 15 | /** 16 | This delegate method will be called when the tableView is triggered to load data initially. 17 | 18 | - parameter tvc: The tableView calling the method. 19 | - parameter handler: The completion handler describing if the table is empty and if there is an error. 20 | */ 21 | func statefulTableViewWillBeginInitialLoad(tvc: StatefulTableView, handler: InitialLoadCompletionHandler) 22 | 23 | /** 24 | This delegate method will be called when the user pulls down to refresh. 25 | 26 | - parameter tvc: The tableView calling the method. 27 | - parameter handler: The completion handler describing if the table is empty and if there is an error. 28 | */ 29 | func statefulTableViewWillBeginLoadingFromRefresh(tvc: StatefulTableView, handler: InitialLoadCompletionHandler) 30 | 31 | /** 32 | This delegate method will be called when the user scrolls to load more. 33 | 34 | - parameter tvc: The tableView calling the method. 35 | - parameter handler: The completion handler describing if the table can load more, has an error, and should show an error view. 36 | */ 37 | func statefulTableViewWillBeginLoadingMore(tvc: StatefulTableView, handler: LoadMoreCompletionHandler) 38 | 39 | /// Views 40 | 41 | /** 42 | This delegate method will be called when the tableView is in need of a view to show when it is loading data initially. 43 | 44 | - parameter tvc: The tableView calling the method. 45 | 46 | - returns: An optional view to show. Defaults to built in view when nil. 47 | */ 48 | func statefulTableViewViewForInitialLoad(tvc: StatefulTableView) -> UIView? 49 | 50 | /** 51 | This delegate method will be called when the tableView is in need of a view to show when it's done loading initially and no data/an error was found. 52 | 53 | - parameter tvc: The tableView calling the method. 54 | - parameter forInitialLoadError: The optional error found. 55 | 56 | - returns: An optional view to show. Defaults to built in view when nil. 57 | */ 58 | func statefulTableViewView(tvc: StatefulTableView, forInitialLoadError: NSError?) -> UIView? 59 | 60 | /** 61 | This delegate method will be called when the tableView failed to load more data. 62 | 63 | - parameter tvc: The tableView calling the method. 64 | - parameter forLoadMoreError: The optional error found. 65 | 66 | - returns: An optional view to show. Default to built in view when nil. 67 | */ 68 | func statefulTableViewView(tvc: StatefulTableView, forLoadMoreError: NSError?) -> UIView? 69 | } -------------------------------------------------------------------------------- /Sources/StatefulTableView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // StatefulTableView.swift 3 | // Demo 4 | // 5 | // Created by Tim on 12/05/2016. 6 | // Copyright © 2016 timominous. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public final class StatefulTableView: UIView { 12 | private enum State { 13 | case Idle 14 | case InitialLoading 15 | case InitialLoadingTableView 16 | case EmptyOrInitialLoadError 17 | case LoadingFromPullToRefresh 18 | case LoadingMore 19 | 20 | var isLoading: Bool { 21 | switch self { 22 | case .InitialLoading: fallthrough 23 | case .InitialLoadingTableView: fallthrough 24 | case .LoadingFromPullToRefresh: fallthrough 25 | case .LoadingMore: 26 | return true 27 | default: return false 28 | } 29 | } 30 | 31 | var isInitialLoading: Bool { 32 | switch self { 33 | case .InitialLoading: fallthrough 34 | case .InitialLoadingTableView: 35 | return true 36 | default: return false 37 | } 38 | } 39 | } 40 | 41 | private enum ViewMode { 42 | case Table 43 | case Static 44 | } 45 | 46 | required public init?(coder aDecoder: NSCoder) { 47 | super.init(coder: aDecoder) 48 | commonInit() 49 | } 50 | 51 | public override init(frame: CGRect) { 52 | super.init(frame: frame) 53 | commonInit() 54 | } 55 | 56 | private lazy var tableView = UITableView() 57 | 58 | private lazy var staticContentView: UIView = { [unowned self] in 59 | let view = UIView(frame: self.bounds) 60 | view.backgroundColor = .whiteColor() 61 | view.hidden = true 62 | return view 63 | }() 64 | 65 | private lazy var refreshControl = UIRefreshControl() 66 | 67 | /// Enables the user to pull down on the tableView to initiate a refresh 68 | public var canPullToRefresh = false 69 | 70 | /// Enables the user to control whether to trigger loading of more objects or not 71 | public var canLoadMore = false 72 | 73 | /// Distance from the bottom of the tableView's vertical content offset where load more will be triggered 74 | public var loadMoreTriggerThreshold: CGFloat = 64 75 | 76 | /// Determines if the load more view is for an error or not 77 | private var loadMoreViewIsErrorView = false 78 | private var lastLoadMoreError: NSError? 79 | private var watchForLoadMore = false 80 | 81 | private var state: State = .Idle 82 | 83 | private var viewMode: ViewMode = .Table { 84 | didSet { 85 | let hidden = viewMode == .Table 86 | 87 | guard staticContentView.hidden != hidden else { return } 88 | staticContentView.hidden = hidden 89 | } 90 | } 91 | 92 | public var statefulDelegate: StatefulTableDelegate? 93 | public var dataSource: UITableViewDataSource? { 94 | set { tableView.dataSource = newValue } 95 | get { return tableView.dataSource } 96 | } 97 | 98 | public var delegate: UITableViewDelegate? { 99 | set { tableView.delegate = newValue } 100 | get { return tableView.delegate } 101 | } 102 | 103 | func commonInit() { 104 | addSubview(tableView) 105 | addSubview(staticContentView) 106 | 107 | refreshControl.addTarget(self, 108 | action: #selector(refreshControlValueChanged), forControlEvents: .ValueChanged) 109 | tableView.addSubview(refreshControl) 110 | } 111 | 112 | override public func layoutSubviews() { 113 | super.layoutSubviews() 114 | tableView.frame = bounds 115 | staticContentView.frame = bounds 116 | } 117 | } 118 | 119 | // MARK: - UITableView bridge 120 | extension StatefulTableView { 121 | /// Bridge for UITableivew methods. Read UITableView documentation for more details 122 | 123 | public var rowHeight: CGFloat { 124 | set { tableView.rowHeight = newValue } 125 | get { return tableView.rowHeight } 126 | } 127 | 128 | public var sectionHeaderHeight: CGFloat { 129 | set { tableView.sectionHeaderHeight = newValue } 130 | get { return tableView.sectionHeaderHeight } 131 | } 132 | 133 | public var sectionFooterHeight: CGFloat { 134 | set { tableView.sectionFooterHeight = newValue } 135 | get { return tableView.sectionFooterHeight } 136 | } 137 | 138 | @available(iOS 7.0, *) 139 | public var estimatedRowHeight: CGFloat { 140 | set { tableView.estimatedRowHeight = newValue } 141 | get { return tableView.estimatedRowHeight } 142 | } 143 | 144 | @available(iOS 7.0, *) 145 | public var estimatedSectionHeaderHeight: CGFloat { 146 | set { tableView.estimatedSectionHeaderHeight = newValue } 147 | get { return tableView.estimatedSectionHeaderHeight } 148 | } 149 | 150 | @available(iOS 7.0, *) 151 | public var estimatedSectionFooterHeight: CGFloat { 152 | set { tableView.estimatedSectionFooterHeight = newValue } 153 | get { return tableView.estimatedSectionHeaderHeight } 154 | } 155 | 156 | @available(iOS 7.0, *) 157 | public var separatorInset: UIEdgeInsets { 158 | set { tableView.separatorInset = newValue } 159 | get { return tableView.separatorInset } 160 | } 161 | 162 | /// Data 163 | 164 | public func reloadData() { 165 | dispatch_async(dispatch_get_main_queue()) { 166 | self.tableView.reloadData() 167 | } 168 | } 169 | 170 | @available(iOS 3.0, *) 171 | public func reloadSectionIndexTitles() { 172 | dispatch_async(dispatch_get_main_queue()) { 173 | self.tableView.reloadSectionIndexTitles() 174 | } 175 | } 176 | 177 | /// Info 178 | 179 | public var numberOfSections: Int { 180 | return tableView.numberOfSections 181 | } 182 | 183 | public func numberOfRowsInSection(section: Int) -> Int { 184 | return tableView.numberOfRowsInSection(section) 185 | } 186 | 187 | public func rectForSection(section: Int) -> CGRect { 188 | return tableView.rectForSection(section) 189 | } 190 | 191 | public func rectFotHeaderInSection(section: Int) -> CGRect { 192 | return tableView.rectForHeaderInSection(section) 193 | } 194 | 195 | public func rectForFooterInSection(section: Int) -> CGRect { 196 | return tableView.rectForFooterInSection(section) 197 | } 198 | 199 | public func rectForRowRowAtIndexPath(indexPath: NSIndexPath) -> CGRect { 200 | return tableView.rectForRowAtIndexPath(indexPath) 201 | } 202 | 203 | public func indexPathForRowAtPoint(point: CGPoint) -> NSIndexPath? { 204 | return tableView.indexPathForRowAtPoint(point) 205 | } 206 | 207 | public func indexPathForCell(cell: UITableViewCell) -> NSIndexPath? { 208 | return tableView.indexPathForCell(cell) 209 | } 210 | 211 | public func indexPathsForRowsInRect(rect: CGRect) -> [NSIndexPath]? { 212 | return tableView.indexPathsForRowsInRect(rect) 213 | } 214 | 215 | public func cellForRowAtIndexPath(indexPath: NSIndexPath) -> UITableViewCell? { 216 | return tableView.cellForRowAtIndexPath(indexPath) 217 | } 218 | 219 | public var visibleCells: [UITableViewCell] { 220 | return tableView.visibleCells 221 | } 222 | 223 | public var indexPathsForVisibleRows: [NSIndexPath]? { 224 | return tableView.indexPathsForVisibleRows; 225 | } 226 | 227 | @available(iOS 6.0, *) 228 | public func headerViewForSection(section: Int) -> UITableViewHeaderFooterView? { 229 | return tableView.headerViewForSection(section) 230 | } 231 | 232 | @available(iOS 6.0, *) 233 | public func footerViewForSection(section: Int) -> UITableViewHeaderFooterView? { 234 | return tableView.footerViewForSection(section) 235 | } 236 | 237 | public func scrollToRowAtIndexPath(indexPath: NSIndexPath, atScrollPosition scrollPosition: UITableViewScrollPosition, animated: Bool) { 238 | tableView.scrollToRowAtIndexPath(indexPath, atScrollPosition: scrollPosition, animated: animated) 239 | } 240 | 241 | public func scrollToNearestSelectedRowAtScrollPosition(scrollPosition: UITableViewScrollPosition, animated: Bool) { 242 | tableView.scrollToNearestSelectedRowAtScrollPosition(scrollPosition, animated: animated) 243 | } 244 | 245 | /// Row insertion/deletion/reloading 246 | 247 | public func beginUpdates() { 248 | tableView.beginUpdates() 249 | } 250 | 251 | public func endUpdates() { 252 | tableView.endUpdates() 253 | } 254 | 255 | public func insertSections(sections: NSIndexSet, withRowAnimation animation: UITableViewRowAnimation) { 256 | tableView.insertSections(sections, withRowAnimation: animation) 257 | } 258 | 259 | public func deleteSections(sections: NSIndexSet, withRowAnimation animation: UITableViewRowAnimation) { 260 | tableView.deleteSections(sections, withRowAnimation: animation) 261 | } 262 | 263 | @available(iOS 3.0, *) 264 | public func reloadSections(sections: NSIndexSet, withRowAnimation animation: UITableViewRowAnimation) { 265 | tableView.reloadSections(sections, withRowAnimation: animation) 266 | } 267 | 268 | @available(iOS 5.0, *) 269 | public func moveSection(section: Int, toSection newSection: Int) { 270 | tableView.moveSection(section, toSection: newSection) 271 | } 272 | 273 | public func insertRowsAtIndexPaths(indexPaths: [NSIndexPath], withRowAnimation animation: UITableViewRowAnimation) { 274 | tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: animation) 275 | } 276 | 277 | public func deleteRowsAtIndexPaths(indexPaths: [NSIndexPath], withRowAnimation animation: UITableViewRowAnimation) { 278 | tableView.deleteRowsAtIndexPaths(indexPaths, withRowAnimation: animation) 279 | } 280 | 281 | @available(iOS 3.0, *) 282 | public func reloadRowsAtIndexPaths(indexPaths: [NSIndexPath], withRowAnimation animation: UITableViewRowAnimation) { 283 | tableView.reloadRowsAtIndexPaths(indexPaths, withRowAnimation: animation) 284 | } 285 | 286 | @available(iOS 5.0, *) 287 | public func moveRowAtIndexPath(indexPath: NSIndexPath, toIndexPath newIndexPath: NSIndexPath) { 288 | tableView.moveRowAtIndexPath(indexPath, toIndexPath: newIndexPath) 289 | } 290 | 291 | /// Editing. When set, rows show insert/delete/reorder control based on data source queries 292 | 293 | public var editing: Bool { 294 | set { tableView.editing = newValue } 295 | get { return tableView.editing } 296 | } 297 | 298 | public func setEditing(editing: Bool, animated: Bool) { 299 | tableView.setEditing(editing, animated: animated) 300 | } 301 | 302 | @available(iOS 3.0, *) 303 | public var allowsSelection: Bool { 304 | set { tableView.allowsSelection = newValue } 305 | get { return tableView.allowsSelection } 306 | } 307 | 308 | public var allowsSelectionDuringEditing: Bool { 309 | set { tableView.allowsSelectionDuringEditing = newValue } 310 | get { return tableView.allowsSelectionDuringEditing } 311 | } 312 | 313 | @available(iOS 5.0, *) 314 | public var allowsMultipleSelection: Bool { 315 | set { tableView.allowsMultipleSelection = newValue } 316 | get { return tableView.allowsMultipleSelection } 317 | } 318 | 319 | @available(iOS 5.0, *) 320 | public var allowsMultipleSelectionDuringEditing: Bool { 321 | set { tableView.allowsMultipleSelectionDuringEditing = newValue } 322 | get { return tableView.allowsMultipleSelectionDuringEditing } 323 | } 324 | 325 | /// Selection 326 | 327 | public var indexPathForSelectedRow: NSIndexPath? { 328 | return tableView.indexPathForSelectedRow 329 | } 330 | 331 | @available(iOS 5.0, *) 332 | public var indexPathsForSelectedRows: [NSIndexPath]? { 333 | return tableView.indexPathsForSelectedRows 334 | } 335 | 336 | public func selectRowAtIndexPath(indexPath: NSIndexPath?, animated: Bool, scrollPosition: UITableViewScrollPosition) { 337 | tableView.selectRowAtIndexPath(indexPath, animated: animated, scrollPosition: scrollPosition) 338 | } 339 | 340 | public func deselectRowAtIndexPath(indexPath: NSIndexPath, animated: Bool) { 341 | tableView.deselectRowAtIndexPath(indexPath, animated: animated) 342 | } 343 | 344 | /// Appearance 345 | 346 | public var sectionIndexMinimumDisplayRowCount: Int { 347 | set { tableView.sectionIndexMinimumDisplayRowCount = newValue } 348 | get { return tableView.sectionIndexMinimumDisplayRowCount } 349 | } 350 | 351 | @available(iOS 6.0, *) 352 | public var sectionIndexColor: UIColor? { 353 | set { tableView.sectionIndexColor = newValue } 354 | get { return tableView.sectionIndexColor } 355 | } 356 | 357 | @available(iOS 7.0, *) 358 | public var sectionIndexBackgroundColor: UIColor? { 359 | set { tableView.sectionIndexBackgroundColor = newValue } 360 | get { return tableView.sectionIndexBackgroundColor } 361 | } 362 | 363 | @available(iOS 6.0, *) 364 | public var sectionIndexTrackingBackgroundColor: UIColor? { 365 | set { tableView.sectionIndexTrackingBackgroundColor = newValue } 366 | get { return tableView.sectionIndexTrackingBackgroundColor } 367 | } 368 | 369 | public var separatorStyle: UITableViewCellSeparatorStyle { 370 | set { tableView.separatorStyle = newValue } 371 | get { return tableView.separatorStyle } 372 | } 373 | 374 | public var separatorColor: UIColor? { 375 | set { tableView.separatorColor = newValue } 376 | get { return tableView.separatorColor } 377 | } 378 | 379 | @available(iOS 8.0, *) 380 | public var separatorEffect: UIVisualEffect? { 381 | set { tableView.separatorEffect = newValue } 382 | get { return tableView.separatorEffect } 383 | } 384 | 385 | @available(iOS 9.0, *) 386 | public var cellLayoutMarginsFollowReadableWidth: Bool { 387 | set { tableView.cellLayoutMarginsFollowReadableWidth = newValue } 388 | get { return tableView.cellLayoutMarginsFollowReadableWidth } 389 | } 390 | 391 | public var tableHeaderView: UIView? { 392 | set { tableView.tableHeaderView = newValue } 393 | get { return tableView.tableHeaderView } 394 | } 395 | 396 | public var tableFooterView: UIView? { 397 | set { tableView.tableFooterView = newValue } 398 | get { return tableView.tableFooterView } 399 | } 400 | 401 | public func dequeueReusableCellWithIdentifier(identifier: String) -> UITableViewCell? { 402 | return tableView.dequeueReusableCellWithIdentifier(identifier) 403 | } 404 | 405 | @available(iOS 6.0, *) 406 | public func dequeueReusableCellWithIdentifier(identifier: String, forIndexPath indexPath: NSIndexPath) -> UITableViewCell { 407 | return tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath) 408 | } 409 | 410 | @available(iOS 6.0, *) 411 | public func dequeueReusableHeaderFooterViewWithIdentifier(identifier: String) -> UITableViewHeaderFooterView? { 412 | return tableView.dequeueReusableHeaderFooterViewWithIdentifier(identifier) 413 | } 414 | 415 | /// Beginning in iOS 6, clients can register a nib or class for each cell. 416 | /// If all reuse identifiers are registered, use the newer -dequeueReusableCellWithIdentifier:forIndexPath: to guarantee that a cell instance is returned. 417 | /// Instances returned from the new dequeue method will also be properly sized when they are returned. 418 | 419 | @available(iOS 5.0, *) 420 | public func registerNib(nib: UINib?, forCellReuseIdentifier identifier: String) { 421 | tableView.registerNib(nib, forCellReuseIdentifier: identifier) 422 | } 423 | 424 | @available(iOS 6.0, *) 425 | public func registerClass(cellClass: AnyClass?, forCellReuseIdentifier identifier: String) { 426 | tableView.registerClass(cellClass, forCellReuseIdentifier: identifier) 427 | } 428 | 429 | @available(iOS 6.0, *) 430 | public func registerNib(nib: UINib?, forHeaderFooterViewReuseIdentifier identifier: String) { 431 | tableView.registerNib(nib, forHeaderFooterViewReuseIdentifier: identifier) 432 | } 433 | 434 | @available(iOS 6.0, *) 435 | public func registerClass(aClass: AnyClass?, forHeaderFooterViewReuseIdentifier identifier: String) { 436 | tableView.registerClass(aClass, forHeaderFooterViewReuseIdentifier: identifier) 437 | } 438 | 439 | /// Focus 440 | 441 | @available(iOS 9.0, *) 442 | public var remembersLastFocusedIndexPath: Bool { 443 | set { tableView.remembersLastFocusedIndexPath = newValue } 444 | get { return tableView.remembersLastFocusedIndexPath } 445 | } 446 | } 447 | 448 | // MARK: - Pull to refresh 449 | extension StatefulTableView { 450 | func refreshControlValueChanged() { 451 | if state != .LoadingFromPullToRefresh && !state.isLoading { 452 | if (!triggerPullToRefresh()) { 453 | refreshControl.endRefreshing() 454 | } 455 | } 456 | } 457 | 458 | /** 459 | Triggers pull to refresh programatically. Also called when the user pulls down to refresh on the tableView. 460 | 461 | - returns: Boolean for success status. 462 | */ 463 | public func triggerPullToRefresh() -> Bool { 464 | guard !state.isLoading && canPullToRefresh else { return false } 465 | 466 | self.setState(.LoadingFromPullToRefresh, updateView: false, error: nil) 467 | 468 | if let delegate = statefulDelegate { 469 | delegate.statefulTableViewWillBeginLoadingFromRefresh(self, handler: { [weak self](tableIsEmpty, errorOrNil) in 470 | self?.setHasFinishedLoadingFromPullToRefresh(tableIsEmpty, error: errorOrNil) 471 | }) 472 | } 473 | 474 | refreshControl.beginRefreshing() 475 | 476 | return true 477 | } 478 | 479 | func setHasFinishedLoadingFromPullToRefresh(tableIsEmpty: Bool, error: NSError?) { 480 | guard state == .LoadingFromPullToRefresh else { return } 481 | 482 | refreshControl.endRefreshing() 483 | 484 | if tableIsEmpty { 485 | self.setState(.EmptyOrInitialLoadError, updateView: true, error: error) 486 | } else { 487 | self.setState(.Idle) 488 | } 489 | } 490 | } 491 | 492 | // MARK: - Initial load 493 | extension StatefulTableView { 494 | 495 | /** 496 | Triggers initial load of data programatically. Defaults to hiding the tableView. 497 | 498 | - returns: Boolean for success status. 499 | */ 500 | public func triggerInitialLoad() -> Bool { 501 | return triggerInitialLoad(false) 502 | } 503 | 504 | /** 505 | Triggers initial load of data programatically. 506 | 507 | - parameter shouldShowTableView: Control if the container should show the tableView or not. 508 | 509 | - returns: Boolean for success status. 510 | */ 511 | public func triggerInitialLoad(shouldShowTableView: Bool) -> Bool { 512 | guard !state.isLoading else { return false } 513 | 514 | if shouldShowTableView { 515 | self.setState(.InitialLoadingTableView) 516 | } else { 517 | self.setState(.InitialLoading) 518 | } 519 | 520 | if let delegate = statefulDelegate { 521 | delegate.statefulTableViewWillBeginInitialLoad(self, handler: { [weak self](tableIsEmpty, errorOrNil) in 522 | self?.setHasFinishedInitialLoad(tableIsEmpty, error: errorOrNil) 523 | }) 524 | } 525 | 526 | return true 527 | } 528 | 529 | func setHasFinishedInitialLoad(tableIsEmpty: Bool, error: NSError?) { 530 | guard state.isInitialLoading else { return } 531 | 532 | if tableIsEmpty { 533 | self.setState(.EmptyOrInitialLoadError, updateView: true, error: error) 534 | } else { 535 | self.setState(.Idle) 536 | } 537 | } 538 | } 539 | 540 | // MARK: - Load more 541 | extension StatefulTableView { 542 | /** 543 | Tiggers loading more of data. Also called when the scroll content offset reaches the `loadMoreTriggerThreshold`. 544 | */ 545 | public func triggerLoadMore() { 546 | guard !state.isLoading else { return } 547 | 548 | loadMoreViewIsErrorView = false 549 | lastLoadMoreError = nil 550 | updateLoadMoreView() 551 | 552 | setState(.LoadingMore) 553 | 554 | if let delegate = statefulDelegate { 555 | delegate.statefulTableViewWillBeginLoadingMore(self, handler: { [weak self](canLoadMore, errorOrNil, showErrorView) in 556 | self?.setHasFinishedLoadingMore(canLoadMore, error: errorOrNil, showErrorView: showErrorView) 557 | }) 558 | } 559 | } 560 | 561 | func updateLoadMoreView() { 562 | if watchForLoadMore { 563 | tableView.tableFooterView = viewForLoadingMore(withError: (loadMoreViewIsErrorView ? lastLoadMoreError : nil)) 564 | } else { 565 | tableView.tableFooterView = UIView() 566 | } 567 | } 568 | 569 | func viewForLoadingMore(withError error: NSError?) -> UIView { 570 | if let view = statefulDelegate?.statefulTableViewView(self, forLoadMoreError: error) { return view } 571 | 572 | let container = UIView(frame: CGRect(origin: .zero, size: CGSize(width: tableView.bounds.width, height: 44))) 573 | 574 | if let error = error { 575 | let label = UILabel() 576 | label.text = error.localizedDescription 577 | label.font = UIFont.systemFontOfSize(12) 578 | label.textAlignment = .Center 579 | label.frame = container.bounds 580 | container.addSubview(label) 581 | } else { 582 | let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: .Gray) 583 | activityIndicator.frame.centerInFrame(container.bounds) 584 | activityIndicator.startAnimating() 585 | container.addSubview(activityIndicator) 586 | } 587 | 588 | return container 589 | } 590 | 591 | func setHasFinishedLoadingMore(canLoadMore: Bool, error: NSError?, showErrorView: Bool) { 592 | guard state == .LoadingMore else { return } 593 | 594 | self.canLoadMore = canLoadMore 595 | loadMoreViewIsErrorView = (error != nil) && showErrorView 596 | lastLoadMoreError = error 597 | 598 | if let _ = error { 599 | updateLoadMoreView() 600 | } 601 | 602 | setState(.Idle) 603 | } 604 | 605 | func watchForLoadMoreIfApplicable(watch: Bool) { 606 | var watch = watch 607 | 608 | if (watch && !canLoadMore) { 609 | watch = false 610 | } 611 | watchForLoadMore = watch 612 | updateLoadMoreView() 613 | 614 | triggerLoadMoreIfApplicable(tableView) 615 | } 616 | 617 | /** 618 | Should be called when scrolling the tableView. This determines when to call `triggerLoadMore` 619 | 620 | - parameter scrollView: The scrolling view. 621 | */ 622 | public func scrollViewDidScroll(scrollView: UIScrollView) { 623 | triggerLoadMoreIfApplicable(scrollView) 624 | } 625 | 626 | func triggerLoadMoreIfApplicable(scrollView: UIScrollView) { 627 | guard watchForLoadMore && !loadMoreViewIsErrorView else { return } 628 | 629 | let scrollPosition = scrollView.contentSize.height - scrollView.frame.size.height - scrollView.contentOffset.y 630 | if scrollPosition < loadMoreTriggerThreshold { 631 | triggerLoadMore() 632 | } 633 | } 634 | } 635 | 636 | // MARK: - States 637 | extension StatefulTableView { 638 | private func setState(newState: State) { 639 | setState(newState, updateView: true, error: nil) 640 | } 641 | 642 | private func setState(newState: State, error: NSError?) { 643 | setState(newState, updateView: true, error: error) 644 | } 645 | 646 | private func setState(newState: State, updateView: Bool, error: NSError?) { 647 | state = newState 648 | 649 | switch state { 650 | case .InitialLoading: 651 | resetStaticContentView(withChildView: viewForInitialLoad) 652 | case .EmptyOrInitialLoadError: 653 | resetStaticContentView(withChildView: viewForEmptyInitialLoad(withError: error)) 654 | default: break 655 | } 656 | 657 | switch state { 658 | case .Idle: 659 | watchForLoadMoreIfApplicable(true) 660 | case .EmptyOrInitialLoadError: 661 | watchForLoadMoreIfApplicable(false) 662 | default: break 663 | } 664 | 665 | if updateView { 666 | let mode: ViewMode 667 | 668 | switch state { 669 | case .InitialLoading: fallthrough 670 | case .EmptyOrInitialLoadError: 671 | mode = .Static 672 | default: mode = .Table 673 | } 674 | 675 | viewMode = mode 676 | } 677 | } 678 | } 679 | 680 | // MARK: - Views 681 | extension StatefulTableView { 682 | func resetStaticContentView(withChildView childView: UIView) { 683 | staticContentView.subviews.forEach { $0.removeFromSuperview() } 684 | staticContentView.addSubview(childView) 685 | 686 | childView.translatesAutoresizingMaskIntoConstraints = false 687 | 688 | let attributes: [NSLayoutAttribute] = [.Top, .Bottom, .Leading, .Trailing] 689 | let constraints = attributes.map { 690 | return NSLayoutConstraint(item: childView, attribute: $0, relatedBy: .Equal, 691 | toItem: staticContentView, attribute: $0, multiplier: 1, constant: 0) 692 | } 693 | 694 | staticContentView.addConstraints(constraints) 695 | } 696 | 697 | var viewForInitialLoad: UIView { 698 | if let view = statefulDelegate?.statefulTableViewViewForInitialLoad(self) { 699 | return view 700 | } 701 | 702 | let activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .Gray) 703 | activityIndicatorView.startAnimating() 704 | activityIndicatorView.frame.centerInFrame(staticContentView.bounds) 705 | 706 | return activityIndicatorView 707 | } 708 | 709 | func viewForEmptyInitialLoad(withError error: NSError?) -> UIView { 710 | if let view = statefulDelegate?.statefulTableViewView(self, forInitialLoadError: error) { return view } 711 | 712 | var frame = CGRect(origin: .zero, size: CGSize(width: staticContentView.bounds.width, height: 120)) 713 | frame.centerInFrame(staticContentView.bounds) 714 | 715 | let container = UIView(frame: frame) 716 | 717 | let label = UILabel() 718 | label.textAlignment = .Center 719 | label.text = error?.localizedDescription ?? "No records found" 720 | label.sizeToFit() 721 | 722 | label.frame.origin.x = (container.bounds.width - label.bounds.width) * 0.5 723 | 724 | if let _ = error { 725 | let button = UIButton(type: .System) 726 | button.setTitle("Try Again", forState: .Normal) 727 | button.addTarget(self, action: #selector(triggerPullToRefresh), forControlEvents: .TouchUpInside) 728 | 729 | button.frame.size = CGSize(width: 130, height: 32) 730 | button.frame.origin.x = (container.bounds.width - button.bounds.width) * 0.5 731 | button.frame.origin.y = label.frame.maxY + 10 732 | 733 | container.addSubview(button) 734 | } 735 | 736 | container.addSubview(label) 737 | 738 | return container 739 | } 740 | } -------------------------------------------------------------------------------- /StatefulTableView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'StatefulTableView' 3 | s.version = '0.0.8' 4 | s.license = { 5 | :type => 'MIT', 6 | :file => 'LICENSE' 7 | } 8 | s.homepage = 'http://github.com/timominous/StatefulTableView' 9 | s.description = 'Custom UITableView container class that supports pull-to-refresh, load-more, initial load, and empty states. Swift port of SKStatefulTableViewController' 10 | s.summary = 'Custom UITableView container class that supports pull-to-refresh, load-more, initial load, and empty states.' 11 | s.author = { 12 | 'timominous' => 'timominous@gmail.com' 13 | } 14 | s.source = { 15 | :git => 'https://github.com/timominous/StatefulTableView.git', 16 | :tag => s.version.to_s 17 | } 18 | s.ios.deployment_target = "8.0" 19 | s.source_files = 'Sources/*.swift' 20 | s.requires_arc = true 21 | end --------------------------------------------------------------------------------