├── .gitignore ├── ESSSquareProgressIndicator.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── ESSSquareProgressIndicator ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── ESSSquareProgressIndicator.h ├── ESSSquareProgressIndicator.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── ViewController.h ├── ViewController.m └── main.m ├── ESSSquareProgressIndicatorTests ├── ESSSquareProgressIndicatorTests.m └── Info.plist └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 392C472C1ACD28830053B770 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 392C472B1ACD28830053B770 /* main.m */; }; 11 | 392C472F1ACD28830053B770 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 392C472E1ACD28830053B770 /* AppDelegate.m */; }; 12 | 392C47321ACD28830053B770 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 392C47311ACD28830053B770 /* ViewController.m */; }; 13 | 392C47351ACD28830053B770 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 392C47331ACD28830053B770 /* Main.storyboard */; }; 14 | 392C47371ACD28830053B770 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 392C47361ACD28830053B770 /* Images.xcassets */; }; 15 | 392C473A1ACD28830053B770 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 392C47381ACD28830053B770 /* LaunchScreen.xib */; }; 16 | 392C47461ACD28830053B770 /* ESSSquareProgressIndicatorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 392C47451ACD28830053B770 /* ESSSquareProgressIndicatorTests.m */; }; 17 | 392C47511ACD28BD0053B770 /* ESSSquareProgressIndicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 392C47501ACD28BD0053B770 /* ESSSquareProgressIndicator.m */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 392C47401ACD28830053B770 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 392C471E1ACD28830053B770 /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = 392C47251ACD28830053B770; 26 | remoteInfo = ESSSquareProgressIndicator; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | 392C47261ACD28830053B770 /* ESSSquareProgressIndicator.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ESSSquareProgressIndicator.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 392C472A1ACD28830053B770 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 392C472B1ACD28830053B770 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 392C472D1ACD28830053B770 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 35 | 392C472E1ACD28830053B770 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 36 | 392C47301ACD28830053B770 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 37 | 392C47311ACD28830053B770 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 38 | 392C47341ACD28830053B770 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 39 | 392C47361ACD28830053B770 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 40 | 392C47391ACD28830053B770 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 41 | 392C473F1ACD28830053B770 /* ESSSquareProgressIndicatorTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ESSSquareProgressIndicatorTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 42 | 392C47441ACD28830053B770 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 43 | 392C47451ACD28830053B770 /* ESSSquareProgressIndicatorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ESSSquareProgressIndicatorTests.m; sourceTree = ""; }; 44 | 392C474F1ACD28BD0053B770 /* ESSSquareProgressIndicator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ESSSquareProgressIndicator.h; sourceTree = ""; }; 45 | 392C47501ACD28BD0053B770 /* ESSSquareProgressIndicator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ESSSquareProgressIndicator.m; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | 392C47231ACD28830053B770 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | 392C473C1ACD28830053B770 /* Frameworks */ = { 57 | isa = PBXFrameworksBuildPhase; 58 | buildActionMask = 2147483647; 59 | files = ( 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | 392C471D1ACD28830053B770 = { 67 | isa = PBXGroup; 68 | children = ( 69 | 392C47281ACD28830053B770 /* ESSSquareProgressIndicator */, 70 | 392C47421ACD28830053B770 /* ESSSquareProgressIndicatorTests */, 71 | 392C47271ACD28830053B770 /* Products */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | 392C47271ACD28830053B770 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 392C47261ACD28830053B770 /* ESSSquareProgressIndicator.app */, 79 | 392C473F1ACD28830053B770 /* ESSSquareProgressIndicatorTests.xctest */, 80 | ); 81 | name = Products; 82 | sourceTree = ""; 83 | }; 84 | 392C47281ACD28830053B770 /* ESSSquareProgressIndicator */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 392C474F1ACD28BD0053B770 /* ESSSquareProgressIndicator.h */, 88 | 392C47501ACD28BD0053B770 /* ESSSquareProgressIndicator.m */, 89 | 392C472D1ACD28830053B770 /* AppDelegate.h */, 90 | 392C472E1ACD28830053B770 /* AppDelegate.m */, 91 | 392C47301ACD28830053B770 /* ViewController.h */, 92 | 392C47311ACD28830053B770 /* ViewController.m */, 93 | 392C47331ACD28830053B770 /* Main.storyboard */, 94 | 392C47361ACD28830053B770 /* Images.xcassets */, 95 | 392C47381ACD28830053B770 /* LaunchScreen.xib */, 96 | 392C47291ACD28830053B770 /* Supporting Files */, 97 | ); 98 | path = ESSSquareProgressIndicator; 99 | sourceTree = ""; 100 | }; 101 | 392C47291ACD28830053B770 /* Supporting Files */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 392C472A1ACD28830053B770 /* Info.plist */, 105 | 392C472B1ACD28830053B770 /* main.m */, 106 | ); 107 | name = "Supporting Files"; 108 | sourceTree = ""; 109 | }; 110 | 392C47421ACD28830053B770 /* ESSSquareProgressIndicatorTests */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 392C47451ACD28830053B770 /* ESSSquareProgressIndicatorTests.m */, 114 | 392C47431ACD28830053B770 /* Supporting Files */, 115 | ); 116 | path = ESSSquareProgressIndicatorTests; 117 | sourceTree = ""; 118 | }; 119 | 392C47431ACD28830053B770 /* Supporting Files */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 392C47441ACD28830053B770 /* Info.plist */, 123 | ); 124 | name = "Supporting Files"; 125 | sourceTree = ""; 126 | }; 127 | /* End PBXGroup section */ 128 | 129 | /* Begin PBXNativeTarget section */ 130 | 392C47251ACD28830053B770 /* ESSSquareProgressIndicator */ = { 131 | isa = PBXNativeTarget; 132 | buildConfigurationList = 392C47491ACD28830053B770 /* Build configuration list for PBXNativeTarget "ESSSquareProgressIndicator" */; 133 | buildPhases = ( 134 | 392C47221ACD28830053B770 /* Sources */, 135 | 392C47231ACD28830053B770 /* Frameworks */, 136 | 392C47241ACD28830053B770 /* Resources */, 137 | ); 138 | buildRules = ( 139 | ); 140 | dependencies = ( 141 | ); 142 | name = ESSSquareProgressIndicator; 143 | productName = ESSSquareProgressIndicator; 144 | productReference = 392C47261ACD28830053B770 /* ESSSquareProgressIndicator.app */; 145 | productType = "com.apple.product-type.application"; 146 | }; 147 | 392C473E1ACD28830053B770 /* ESSSquareProgressIndicatorTests */ = { 148 | isa = PBXNativeTarget; 149 | buildConfigurationList = 392C474C1ACD28830053B770 /* Build configuration list for PBXNativeTarget "ESSSquareProgressIndicatorTests" */; 150 | buildPhases = ( 151 | 392C473B1ACD28830053B770 /* Sources */, 152 | 392C473C1ACD28830053B770 /* Frameworks */, 153 | 392C473D1ACD28830053B770 /* Resources */, 154 | ); 155 | buildRules = ( 156 | ); 157 | dependencies = ( 158 | 392C47411ACD28830053B770 /* PBXTargetDependency */, 159 | ); 160 | name = ESSSquareProgressIndicatorTests; 161 | productName = ESSSquareProgressIndicatorTests; 162 | productReference = 392C473F1ACD28830053B770 /* ESSSquareProgressIndicatorTests.xctest */; 163 | productType = "com.apple.product-type.bundle.unit-test"; 164 | }; 165 | /* End PBXNativeTarget section */ 166 | 167 | /* Begin PBXProject section */ 168 | 392C471E1ACD28830053B770 /* Project object */ = { 169 | isa = PBXProject; 170 | attributes = { 171 | LastUpgradeCheck = 0620; 172 | ORGANIZATIONNAME = "Eternal Storms Software"; 173 | TargetAttributes = { 174 | 392C47251ACD28830053B770 = { 175 | CreatedOnToolsVersion = 6.2; 176 | }; 177 | 392C473E1ACD28830053B770 = { 178 | CreatedOnToolsVersion = 6.2; 179 | TestTargetID = 392C47251ACD28830053B770; 180 | }; 181 | }; 182 | }; 183 | buildConfigurationList = 392C47211ACD28830053B770 /* Build configuration list for PBXProject "ESSSquareProgressIndicator" */; 184 | compatibilityVersion = "Xcode 3.2"; 185 | developmentRegion = English; 186 | hasScannedForEncodings = 0; 187 | knownRegions = ( 188 | en, 189 | Base, 190 | ); 191 | mainGroup = 392C471D1ACD28830053B770; 192 | productRefGroup = 392C47271ACD28830053B770 /* Products */; 193 | projectDirPath = ""; 194 | projectRoot = ""; 195 | targets = ( 196 | 392C47251ACD28830053B770 /* ESSSquareProgressIndicator */, 197 | 392C473E1ACD28830053B770 /* ESSSquareProgressIndicatorTests */, 198 | ); 199 | }; 200 | /* End PBXProject section */ 201 | 202 | /* Begin PBXResourcesBuildPhase section */ 203 | 392C47241ACD28830053B770 /* Resources */ = { 204 | isa = PBXResourcesBuildPhase; 205 | buildActionMask = 2147483647; 206 | files = ( 207 | 392C47351ACD28830053B770 /* Main.storyboard in Resources */, 208 | 392C473A1ACD28830053B770 /* LaunchScreen.xib in Resources */, 209 | 392C47371ACD28830053B770 /* Images.xcassets in Resources */, 210 | ); 211 | runOnlyForDeploymentPostprocessing = 0; 212 | }; 213 | 392C473D1ACD28830053B770 /* Resources */ = { 214 | isa = PBXResourcesBuildPhase; 215 | buildActionMask = 2147483647; 216 | files = ( 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXResourcesBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | 392C47221ACD28830053B770 /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | 392C47321ACD28830053B770 /* ViewController.m in Sources */, 228 | 392C47511ACD28BD0053B770 /* ESSSquareProgressIndicator.m in Sources */, 229 | 392C472F1ACD28830053B770 /* AppDelegate.m in Sources */, 230 | 392C472C1ACD28830053B770 /* main.m in Sources */, 231 | ); 232 | runOnlyForDeploymentPostprocessing = 0; 233 | }; 234 | 392C473B1ACD28830053B770 /* Sources */ = { 235 | isa = PBXSourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | 392C47461ACD28830053B770 /* ESSSquareProgressIndicatorTests.m in Sources */, 239 | ); 240 | runOnlyForDeploymentPostprocessing = 0; 241 | }; 242 | /* End PBXSourcesBuildPhase section */ 243 | 244 | /* Begin PBXTargetDependency section */ 245 | 392C47411ACD28830053B770 /* PBXTargetDependency */ = { 246 | isa = PBXTargetDependency; 247 | target = 392C47251ACD28830053B770 /* ESSSquareProgressIndicator */; 248 | targetProxy = 392C47401ACD28830053B770 /* PBXContainerItemProxy */; 249 | }; 250 | /* End PBXTargetDependency section */ 251 | 252 | /* Begin PBXVariantGroup section */ 253 | 392C47331ACD28830053B770 /* Main.storyboard */ = { 254 | isa = PBXVariantGroup; 255 | children = ( 256 | 392C47341ACD28830053B770 /* Base */, 257 | ); 258 | name = Main.storyboard; 259 | sourceTree = ""; 260 | }; 261 | 392C47381ACD28830053B770 /* LaunchScreen.xib */ = { 262 | isa = PBXVariantGroup; 263 | children = ( 264 | 392C47391ACD28830053B770 /* Base */, 265 | ); 266 | name = LaunchScreen.xib; 267 | sourceTree = ""; 268 | }; 269 | /* End PBXVariantGroup section */ 270 | 271 | /* Begin XCBuildConfiguration section */ 272 | 392C47471ACD28830053B770 /* Debug */ = { 273 | isa = XCBuildConfiguration; 274 | buildSettings = { 275 | ALWAYS_SEARCH_USER_PATHS = NO; 276 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 277 | CLANG_CXX_LIBRARY = "libc++"; 278 | CLANG_ENABLE_MODULES = YES; 279 | CLANG_ENABLE_OBJC_ARC = YES; 280 | CLANG_WARN_BOOL_CONVERSION = YES; 281 | CLANG_WARN_CONSTANT_CONVERSION = YES; 282 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 283 | CLANG_WARN_EMPTY_BODY = YES; 284 | CLANG_WARN_ENUM_CONVERSION = YES; 285 | CLANG_WARN_INT_CONVERSION = YES; 286 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 287 | CLANG_WARN_UNREACHABLE_CODE = YES; 288 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 289 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 290 | COPY_PHASE_STRIP = NO; 291 | ENABLE_STRICT_OBJC_MSGSEND = YES; 292 | GCC_C_LANGUAGE_STANDARD = gnu99; 293 | GCC_DYNAMIC_NO_PIC = NO; 294 | GCC_OPTIMIZATION_LEVEL = 0; 295 | GCC_PREPROCESSOR_DEFINITIONS = ( 296 | "DEBUG=1", 297 | "$(inherited)", 298 | ); 299 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 300 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 301 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 302 | GCC_WARN_UNDECLARED_SELECTOR = YES; 303 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 304 | GCC_WARN_UNUSED_FUNCTION = YES; 305 | GCC_WARN_UNUSED_VARIABLE = YES; 306 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 307 | MTL_ENABLE_DEBUG_INFO = YES; 308 | ONLY_ACTIVE_ARCH = YES; 309 | SDKROOT = iphoneos; 310 | TARGETED_DEVICE_FAMILY = "1,2"; 311 | }; 312 | name = Debug; 313 | }; 314 | 392C47481ACD28830053B770 /* Release */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ALWAYS_SEARCH_USER_PATHS = NO; 318 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 319 | CLANG_CXX_LIBRARY = "libc++"; 320 | CLANG_ENABLE_MODULES = YES; 321 | CLANG_ENABLE_OBJC_ARC = YES; 322 | CLANG_WARN_BOOL_CONVERSION = YES; 323 | CLANG_WARN_CONSTANT_CONVERSION = YES; 324 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 325 | CLANG_WARN_EMPTY_BODY = YES; 326 | CLANG_WARN_ENUM_CONVERSION = YES; 327 | CLANG_WARN_INT_CONVERSION = YES; 328 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 329 | CLANG_WARN_UNREACHABLE_CODE = YES; 330 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 331 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 332 | COPY_PHASE_STRIP = NO; 333 | ENABLE_NS_ASSERTIONS = NO; 334 | ENABLE_STRICT_OBJC_MSGSEND = YES; 335 | GCC_C_LANGUAGE_STANDARD = gnu99; 336 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 337 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 338 | GCC_WARN_UNDECLARED_SELECTOR = YES; 339 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 340 | GCC_WARN_UNUSED_FUNCTION = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 343 | MTL_ENABLE_DEBUG_INFO = NO; 344 | SDKROOT = iphoneos; 345 | TARGETED_DEVICE_FAMILY = "1,2"; 346 | VALIDATE_PRODUCT = YES; 347 | }; 348 | name = Release; 349 | }; 350 | 392C474A1ACD28830053B770 /* Debug */ = { 351 | isa = XCBuildConfiguration; 352 | buildSettings = { 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | INFOPLIST_FILE = ESSSquareProgressIndicator/Info.plist; 355 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 356 | PRODUCT_NAME = "$(TARGET_NAME)"; 357 | }; 358 | name = Debug; 359 | }; 360 | 392C474B1ACD28830053B770 /* Release */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 364 | INFOPLIST_FILE = ESSSquareProgressIndicator/Info.plist; 365 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 366 | PRODUCT_NAME = "$(TARGET_NAME)"; 367 | }; 368 | name = Release; 369 | }; 370 | 392C474D1ACD28830053B770 /* Debug */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | BUNDLE_LOADER = "$(TEST_HOST)"; 374 | FRAMEWORK_SEARCH_PATHS = ( 375 | "$(SDKROOT)/Developer/Library/Frameworks", 376 | "$(inherited)", 377 | ); 378 | GCC_PREPROCESSOR_DEFINITIONS = ( 379 | "DEBUG=1", 380 | "$(inherited)", 381 | ); 382 | INFOPLIST_FILE = ESSSquareProgressIndicatorTests/Info.plist; 383 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 384 | PRODUCT_NAME = "$(TARGET_NAME)"; 385 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ESSSquareProgressIndicator.app/ESSSquareProgressIndicator"; 386 | }; 387 | name = Debug; 388 | }; 389 | 392C474E1ACD28830053B770 /* Release */ = { 390 | isa = XCBuildConfiguration; 391 | buildSettings = { 392 | BUNDLE_LOADER = "$(TEST_HOST)"; 393 | FRAMEWORK_SEARCH_PATHS = ( 394 | "$(SDKROOT)/Developer/Library/Frameworks", 395 | "$(inherited)", 396 | ); 397 | INFOPLIST_FILE = ESSSquareProgressIndicatorTests/Info.plist; 398 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 399 | PRODUCT_NAME = "$(TARGET_NAME)"; 400 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ESSSquareProgressIndicator.app/ESSSquareProgressIndicator"; 401 | }; 402 | name = Release; 403 | }; 404 | /* End XCBuildConfiguration section */ 405 | 406 | /* Begin XCConfigurationList section */ 407 | 392C47211ACD28830053B770 /* Build configuration list for PBXProject "ESSSquareProgressIndicator" */ = { 408 | isa = XCConfigurationList; 409 | buildConfigurations = ( 410 | 392C47471ACD28830053B770 /* Debug */, 411 | 392C47481ACD28830053B770 /* Release */, 412 | ); 413 | defaultConfigurationIsVisible = 0; 414 | defaultConfigurationName = Release; 415 | }; 416 | 392C47491ACD28830053B770 /* Build configuration list for PBXNativeTarget "ESSSquareProgressIndicator" */ = { 417 | isa = XCConfigurationList; 418 | buildConfigurations = ( 419 | 392C474A1ACD28830053B770 /* Debug */, 420 | 392C474B1ACD28830053B770 /* Release */, 421 | ); 422 | defaultConfigurationIsVisible = 0; 423 | }; 424 | 392C474C1ACD28830053B770 /* Build configuration list for PBXNativeTarget "ESSSquareProgressIndicatorTests" */ = { 425 | isa = XCConfigurationList; 426 | buildConfigurations = ( 427 | 392C474D1ACD28830053B770 /* Debug */, 428 | 392C474E1ACD28830053B770 /* Release */, 429 | ); 430 | defaultConfigurationIsVisible = 0; 431 | }; 432 | /* End XCConfigurationList section */ 433 | }; 434 | rootObject = 392C471E1ACD28830053B770 /* Project object */; 435 | } 436 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ESSSquareProgressIndicator 4 | // 5 | // Created by Matthias Gansrigler on 02.04.2015. 6 | // Copyright (c) 2015 Eternal Storms Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ESSSquareProgressIndicator 4 | // 5 | // Created by Matthias Gansrigler on 02.04.2015. 6 | // Copyright (c) 2015 Eternal Storms Software. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/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 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/ESSSquareProgressIndicator.h: -------------------------------------------------------------------------------- 1 | // 2 | // ESSSquareProgressIndicator.h 3 | // 4 | // Created by Matthias Gansrigler on 14.10.2014. 5 | // Copyright (c) 2014 Eternal Storms Software. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | #define isMac (!TARGET_OS_IPHONE && !TARGET_OS_EMBEDDED && !TARGET_IPHONE_SIMULATOR) 11 | #define isiOS ((TARGET_OS_IPHONE || TARGET_OS_EMBEDDED || TARGET_IPHONE_SIMULATOR)) 12 | 13 | #if (isiOS) 14 | 15 | #import 16 | 17 | IB_DESIGNABLE @interface ESSSquareProgressIndicator : UIView 18 | 19 | #else 20 | 21 | #import 22 | #import 23 | 24 | IB_DESIGNABLE @interface ESSSquareProgressIndicator : NSView 25 | 26 | #endif 27 | 28 | /*! 29 | @class ESSSquareProgressIndicator 30 | 31 | @abstract 32 | An indeterminate progress indicator that animates in a square form. 33 | 34 | @discussion 35 | Drop a UIView in your interface file and set its class to ESSSquareProgressIndicator. It will animate as long as it's a subview of a UIView or not hidden. The animation will stop when removed from the superview or when the view is hidden. 36 | 37 | The point of this class is that a CAShapeLayer can not animate beyond its 1.0 -strokeEnd value to make for a continuous animation. ESSSquareProgressIndicator hence uses two (2) CAShapeLayers to do its job. 38 | 39 | It was created in the process of developing the iOS game ReachZEN http://zen.gansrigler.com 40 | */ 41 | 42 | /*! 43 | @property strokeColor 44 | @abstract The NSColor/UIColor the progress indicator should be drawn in. 45 | */ 46 | #if isiOS 47 | @property (strong) IBInspectable UIColor *strokeColor; 48 | #else 49 | @property (strong) IBInspectable NSColor *strokeColor; 50 | #endif 51 | 52 | /*! 53 | @property strokeWidth 54 | @abstract The width of the progress indicator's line. 55 | @discussion Minimum value is 2.0. 56 | */ 57 | @property (assign) IBInspectable CGFloat strokeWidth; 58 | 59 | @end -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/ESSSquareProgressIndicator.m: -------------------------------------------------------------------------------- 1 | // 2 | // ESSSquareProgressIndicator.m 3 | // 4 | // Created by Matthias Gansrigler on 14.10.2014. 5 | // Copyright (c) 2014 Eternal Storms Software. All rights reserved. 6 | // 7 | 8 | #import "ESSSquareProgressIndicator.h" 9 | 10 | @interface ESSSquareProgressIndicator () 11 | 12 | /*! 13 | @property shapeLayer 14 | @abstract One of the shape layers used for animating the progress indicator. 15 | @discussion Two shape layers are needed because -strokeEnd can not be animated beyond 1.0. With two layers, the illusion is created that the line moves endlessly around the rect. 16 | */ 17 | @property (strong) CAShapeLayer *shapeLayer; 18 | 19 | /*! 20 | @property shapeLayer2 21 | @abstract One of the shape layers used for animating the progress indicator. 22 | @discussion Two shape layers are needed because -strokeEnd can not be animated beyond 1.0. With two layers, the illusion is created that the line moves endlessly around the rect. 23 | */ 24 | @property (strong) CAShapeLayer *shapeLayer2; 25 | 26 | /*! 27 | @property shouldAnimate 28 | @abstract Indicates whether animation should continue. 29 | @discussion If set to NO, another round of animation is not started. 30 | */ 31 | @property (assign) BOOL shouldAnimate; 32 | 33 | @end 34 | 35 | @implementation ESSSquareProgressIndicator 36 | #if !TARGET_INTERFACE_BUILDER 37 | - (void)awakeFromNib 38 | { 39 | self.shouldAnimate = !(self.isHidden); 40 | 41 | if (self.strokeWidth <= 2.0) 42 | self.strokeWidth = 2.0; 43 | 44 | CGFloat strokeWidthHalf = self.strokeWidth/2.0; 45 | 46 | //we do this instead of CGPathCreateWithRect() because if we did that, the direction would be counter-clockwise, but we want it clockwise. 47 | #if (isiOS) 48 | CGMutablePathRef pathRef = CGPathCreateMutable(); 49 | CGPathMoveToPoint(pathRef, nil, strokeWidthHalf, 0+strokeWidthHalf); 50 | CGPathAddLineToPoint(pathRef, nil, self.frame.size.width-strokeWidthHalf, 0+strokeWidthHalf); 51 | CGPathMoveToPoint(pathRef, nil, self.frame.size.width-strokeWidthHalf, 0+strokeWidthHalf); 52 | CGPathAddLineToPoint(pathRef, nil, self.frame.size.width-strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 53 | CGPathMoveToPoint(pathRef, nil, self.frame.size.width-strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 54 | CGPathAddLineToPoint(pathRef, nil, strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 55 | CGPathMoveToPoint(pathRef, nil, strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 56 | CGPathAddLineToPoint(pathRef, nil, strokeWidthHalf, 0+strokeWidthHalf); 57 | CGPathMoveToPoint(pathRef, nil, strokeWidthHalf, 0+strokeWidthHalf); 58 | CGPathCloseSubpath(pathRef); 59 | #elif (isMac) 60 | CGMutablePathRef pathRef = CGPathCreateMutable(); 61 | CGPathMoveToPoint(pathRef, nil, strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 62 | CGPathAddLineToPoint(pathRef, nil, self.frame.size.width-strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 63 | CGPathMoveToPoint(pathRef, nil, self.frame.size.width-strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 64 | CGPathAddLineToPoint(pathRef, nil, self.frame.size.width-strokeWidthHalf, strokeWidthHalf); 65 | CGPathMoveToPoint(pathRef, nil, self.frame.size.width-strokeWidthHalf, strokeWidthHalf); 66 | CGPathAddLineToPoint(pathRef, nil, strokeWidthHalf, strokeWidthHalf); 67 | CGPathMoveToPoint(pathRef, nil, strokeWidthHalf, strokeWidthHalf); 68 | CGPathAddLineToPoint(pathRef, nil, strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 69 | CGPathMoveToPoint(pathRef, nil, strokeWidthHalf, self.frame.size.height-strokeWidthHalf); 70 | CGPathCloseSubpath(pathRef); 71 | #endif 72 | 73 | self.shapeLayer = [CAShapeLayer layer]; 74 | self.shapeLayer2 = [CAShapeLayer layer]; 75 | 76 | self.shapeLayer.path = pathRef; 77 | self.shapeLayer.lineWidth = self.strokeWidth; 78 | self.shapeLayer2.path = pathRef; 79 | self.shapeLayer2.lineWidth = self.strokeWidth; 80 | 81 | self.shapeLayer.strokeStart = 0.0; 82 | self.shapeLayer.strokeEnd = 0.125; 83 | self.shapeLayer2.strokeStart = 0.75+0.125; 84 | self.shapeLayer2.strokeEnd = 1.0; 85 | 86 | #if (isiOS) 87 | self.backgroundColor = [UIColor clearColor]; 88 | 89 | if (self.strokeColor == nil) 90 | self.strokeColor = [UIColor blackColor]; 91 | 92 | self.shapeLayer.fillColor = [[UIColor clearColor] CGColor]; 93 | self.shapeLayer2.fillColor = [[UIColor clearColor] CGColor]; 94 | #else //isMac 95 | if (self.strokeColor == nil) 96 | self.strokeColor = [NSColor whiteColor]; 97 | 98 | self.shapeLayer.fillColor = [[NSColor clearColor] CGColor]; 99 | self.shapeLayer2.fillColor = [[NSColor clearColor] CGColor]; 100 | #endif 101 | 102 | self.shapeLayer.strokeColor = self.strokeColor.CGColor; 103 | self.shapeLayer2.strokeColor = self.strokeColor.CGColor; 104 | [self.layer addSublayer:self.shapeLayer]; 105 | [self.layer addSublayer:self.shapeLayer2]; 106 | 107 | CGPathRelease(pathRef); 108 | 109 | [self addObserver:self forKeyPath:@"color" options:NSKeyValueObservingOptionNew context:nil]; 110 | [self addObserver:self forKeyPath:@"lineWidth" options:NSKeyValueObservingOptionNew context:nil]; 111 | } 112 | 113 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 114 | { 115 | if (object == self && [keyPath isEqualToString:@"color"]) 116 | { 117 | self.shapeLayer.strokeColor = self.strokeColor.CGColor; 118 | self.shapeLayer2.strokeColor = self.strokeColor.CGColor; 119 | return; 120 | } else if (object == self && [keyPath isEqualToString:@"lineWidth"]) 121 | { 122 | if (self.strokeWidth <= 2.0) 123 | self.strokeWidth = 2.0; 124 | 125 | self.shapeLayer.lineWidth = self.strokeWidth; 126 | self.shapeLayer2.lineWidth = self.strokeWidth; 127 | return; 128 | } 129 | 130 | [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 131 | } 132 | 133 | - (void)removeFromSuperview 134 | { 135 | self.shouldAnimate = NO; 136 | 137 | [super removeFromSuperview]; 138 | } 139 | 140 | - (void)setHidden:(BOOL)hidden 141 | { 142 | self.shouldAnimate = !hidden; 143 | if (hidden) 144 | [super setHidden:hidden]; 145 | else 146 | { 147 | [super setHidden:hidden]; 148 | [self _animate]; 149 | } 150 | } 151 | 152 | static CAMediaTimingFunction *tf = nil; 153 | static CGFloat duration = 0.125; 154 | - (void)_animate 155 | { 156 | if (tf == nil) 157 | tf = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]; 158 | 159 | //second animation, to whole left line 160 | [CATransaction setCompletionBlock:^{ 161 | [CATransaction begin]; 162 | [CATransaction setAnimationDuration:0.0]; 163 | self.shapeLayer2.strokeStart = 0.75; 164 | self.shapeLayer2.strokeEnd = 0.75; 165 | [CATransaction commit]; 166 | [CATransaction flush]; 167 | 168 | [CATransaction setCompletionBlock:^{ 169 | [CATransaction begin]; 170 | [CATransaction setAnimationDuration:0.0]; 171 | self.shapeLayer2.strokeStart = 0.75; 172 | self.shapeLayer2.strokeEnd = 1.0; 173 | self.shapeLayer.strokeStart = 0.0; 174 | self.shapeLayer.strokeEnd = 0.0; 175 | [CATransaction commit]; 176 | [CATransaction flush]; 177 | //third animation, to half left line and half top line 178 | [CATransaction setCompletionBlock:^{ 179 | if (self.shouldAnimate) 180 | [self _animate]; 181 | }]; 182 | [CATransaction begin]; 183 | [CATransaction setAnimationTimingFunction:tf]; 184 | [CATransaction setAnimationDuration:duration]; 185 | self.shapeLayer2.strokeStart = 0.75+0.125; 186 | self.shapeLayer.strokeEnd = 0.125; 187 | [CATransaction commit]; 188 | 189 | /* 4; animate back to initial position: 190 | 191 | | - - . 192 | | . 193 | . . 194 | . . . . 195 | 196 | */ 197 | }]; 198 | [CATransaction begin]; 199 | [CATransaction setAnimationTimingFunction:tf]; 200 | [CATransaction setAnimationDuration:duration*6]; //*6 because it's 6 steps 201 | self.shapeLayer.strokeStart = 0.75; 202 | self.shapeLayer.strokeEnd = 1.0; 203 | [CATransaction commit]; 204 | 205 | /* 3; animate to this (second animation, all done in one animation) 206 | 207 | . - - | 208 | . | 209 | . . 210 | . . . . 211 | 212 | . . . | 213 | . | 214 | . | 215 | . . . | 216 | 217 | . . . . 218 | . . 219 | . | 220 | . _ _ | 221 | 222 | . . . . 223 | . . 224 | . . 225 | _ _ _ _ 226 | 227 | . . . . 228 | | . 229 | | . 230 | _ _ . . 231 | 232 | | . . . 233 | | . 234 | | . 235 | | . . . 236 | 237 | */ 238 | }]; 239 | 240 | //first animation, from left half and top half to top whole line 241 | /* 1; initial position: 242 | 243 | | - - . 244 | | . 245 | . . 246 | . . . . 247 | 248 | */ 249 | [CATransaction begin]; 250 | [CATransaction setAnimationTimingFunction:tf]; 251 | [CATransaction setAnimationDuration:duration]; 252 | 253 | self.shapeLayer2.strokeStart = 1.0; 254 | self.shapeLayer2.strokeEnd = 1.0; 255 | 256 | self.shapeLayer.strokeStart = 0.0; 257 | self.shapeLayer.strokeEnd = 0.25; 258 | [CATransaction commit]; 259 | 260 | /* 2; animated to this: 261 | 262 | - - - - 263 | . . 264 | . . 265 | . . . . 266 | 267 | */ 268 | } 269 | 270 | - (void)dealloc 271 | { 272 | [self removeObserver:self forKeyPath:@"color"]; 273 | [self removeObserver:self forKeyPath:@"lineWidth"]; 274 | } 275 | 276 | #else //is Interface Builder 277 | #pragma mark - Interface Builder Mockup Drawing 278 | 279 | #if (isiOS) 280 | - (instancetype)initWithFrame:(CGRect)frameRect 281 | #elif (isMac) 282 | - (instancetype)initWithFrame:(NSRect)frameRect 283 | #endif 284 | { 285 | if (self = [super initWithFrame:frameRect]) 286 | { 287 | [self inspectableDefaults]; 288 | return self; 289 | } 290 | 291 | return nil; 292 | } 293 | 294 | - (instancetype)initWithCoder:(NSCoder *)coder 295 | { 296 | if (self = [super initWithCoder:coder]) 297 | { 298 | [self inspectableDefaults]; 299 | return self; 300 | } 301 | 302 | return nil; 303 | } 304 | 305 | - (void)inspectableDefaults 306 | { 307 | #if (isiOS) 308 | _strokeColor = [UIColor blackColor]; 309 | #elif (isMac) 310 | _strokeColor = [NSColor blackColor]; 311 | #endif 312 | _strokeWidth = 2.0; 313 | } 314 | 315 | /* 316 | Draws a part of the path that will be animated in the built app. 317 | Animation with CALayer seems to be not supported by live rendering. 318 | */ 319 | #if (isiOS) 320 | - (void)drawRect:(CGRect)rect 321 | #elif (isMac) 322 | - (void)drawRect:(NSRect)dirtyRect 323 | #endif 324 | { 325 | [_strokeColor set]; 326 | CGFloat strokeWidthHalf = _strokeWidth/2.0; 327 | 328 | #if (isiOS) 329 | UIBezierPath *bp = [UIBezierPath bezierPath]; 330 | bp.lineWidth = _strokeWidth; 331 | [bp moveToPoint:CGPointMake(strokeWidthHalf, self.frame.size.height/2.0)]; 332 | [bp addLineToPoint:CGPointMake(strokeWidthHalf, 0+strokeWidthHalf)]; 333 | [bp moveToPoint:CGPointMake(strokeWidthHalf, 0+strokeWidthHalf)]; 334 | [bp addLineToPoint:CGPointMake(self.frame.size.width/2.0, 0+strokeWidthHalf)]; 335 | #elif (isMac) 336 | NSBezierPath *bp = [NSBezierPath bezierPath]; 337 | bp.lineWidth = _strokeWidth; 338 | [bp moveToPoint:NSMakePoint(strokeWidthHalf, self.frame.size.height/2.0)]; 339 | [bp lineToPoint:NSMakePoint(strokeWidthHalf, self.frame.size.height-strokeWidthHalf)]; 340 | [bp moveToPoint:NSMakePoint(strokeWidthHalf, self.frame.size.height-strokeWidthHalf)]; 341 | [bp lineToPoint:NSMakePoint(self.frame.size.width/2.0, self.frame.size.height-strokeWidthHalf)]; 342 | #endif 343 | [bp closePath]; 344 | [bp stroke]; 345 | } 346 | 347 | #endif 348 | @end 349 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/Images.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 | } -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | at.EternalStorms.$(PRODUCT_NAME:rfc1034identifier) 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 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // ESSSquareProgressIndicator 4 | // 5 | // Created by Matthias Gansrigler on 02.04.2015. 6 | // Copyright (c) 2015 Eternal Storms Software. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // ESSSquareProgressIndicator 4 | // 5 | // Created by Matthias Gansrigler on 02.04.2015. 6 | // Copyright (c) 2015 Eternal Storms Software. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | 11 | @interface ViewController () 12 | 13 | @end 14 | 15 | @implementation ViewController 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | // Do any additional setup after loading the view, typically from a nib. 20 | } 21 | 22 | - (void)didReceiveMemoryWarning { 23 | [super didReceiveMemoryWarning]; 24 | // Dispose of any resources that can be recreated. 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicator/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ESSSquareProgressIndicator 4 | // 5 | // Created by Matthias Gansrigler on 02.04.2015. 6 | // Copyright (c) 2015 Eternal Storms Software. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicatorTests/ESSSquareProgressIndicatorTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ESSSquareProgressIndicatorTests.m 3 | // ESSSquareProgressIndicatorTests 4 | // 5 | // Created by Matthias Gansrigler on 02.04.2015. 6 | // Copyright (c) 2015 Eternal Storms Software. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ESSSquareProgressIndicatorTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation ESSSquareProgressIndicatorTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /ESSSquareProgressIndicatorTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | at.EternalStorms.$(PRODUCT_NAME:rfc1034identifier) 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESSSquareProgressIndicator 2 | A rectangular (square), indeterminate progress indicator for iOS and OS X ([Blog Post](https://eternalstorms.wordpress.com/2015/04/02/esssquareprogressindicator-for-ios-and-os-x/)) 3 | 4 | ![ESSSquareProgressIndicator Animation](http://eternalstorms.at/opensource/ESSSquareProgressIndicator/indicator.gif "ESSSquareProgressIndicator Animation") 5 | 6 | It was created during the development of the iOS game [Reach ZEN](http://zen.gansrigler.com). 7 | 8 | ## First, the License Agreement 9 | 10 | 1) You can use the code in your own products. 11 | 2) You can modify the code as you wish, and use the modified code in your products. 12 | 3) You can redistribute the original, unmodified code, but you have to include the full license text below. 13 | 4) You can redistribute the modified code as you wish (without the full license text below). 14 | 5) In all cases, you must include a credit mentioning Matthias Gansrigler as the original author of the source. 15 | 6) I’m not liable for anything you do with the code, no matter what. So be sensible. 16 | 7) You can’t use my name or other marks to promote your products based on the code. 17 | 8) If you agree to all of that, go ahead and download the source. Otherwise, don’t. 18 | 19 | # How To Use ESSSquareProgressIndicator 20 | 21 | Place a UIView / NSView in your interface and set its class to ESSSquareProgressIndicator. Done. 22 | The color and stroke width of the progress indicator can be changed in code or in Interface Builder due to IB_DESIGNABLE and IBInspectable. 23 | 24 | ## Requirements 25 | This code has been tested on iOS 7.1 and OS X Yosemite 10.10. It might work with earlier versions of these platforms. 26 | Developed with Xcode 6.2 27 | 28 | ## Support 29 | The framework and code is provided as-is, but if you need help or have suggestions, you can contact me anytime at [opensource@eternalstorms.at](mailto:opensource@eternalstorms.at) or [@eternalstorms on twitter](http://twitter.com/eternalstorms) 30 | 31 | For other Open Source projects of mine, please visit http://www.eternalstorms.at/opensource 32 | 33 | # I want to hear from you 34 | If you use ESSSquareProgressIndicator in one of your projects, please [let me know](mailto:opensource@eternalstorms.at)! I'd love to hear about your apps and mention them here on this project page :) !! --------------------------------------------------------------------------------