├── .gitignore ├── .gitmodules ├── AnimatedImagesViewSampleApp ├── AnimatedImagesViewSampleApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── javiersoto.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── javiersoto.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints.xcbkptlist │ │ └── xcschemes │ │ ├── AnimatedImagesViewSampleApp.xcscheme │ │ └── xcschememanagement.plist └── AnimatedImagesViewSampleApp │ ├── AnimatedImagesViewSampleApp-Info.plist │ ├── AnimatedImagesViewSampleApp-Prefix.pch │ ├── JSAppDelegate.h │ ├── JSAppDelegate.m │ ├── JSViewController.h │ ├── JSViewController.m │ ├── Resources │ ├── Default-568h@2x.png │ ├── image1.jpg │ ├── image2.jpg │ └── image3.jpg │ ├── en.lproj │ ├── InfoPlist.strings │ └── JSViewController.xib │ └── main.m ├── JSAnimatedImagesView.h ├── JSAnimatedImagesView.m ├── JSAnimatedImagesView.podspec ├── LICENSE └── README.markdown /.gitignore: -------------------------------------------------------------------------------- 1 | # xcode noise 2 | *.mode1v3 3 | *.pbxuser 4 | *.perspective 5 | *.perspectivev3 6 | *.pyc 7 | *~.nib/ 8 | build/* 9 | xcuserdata 10 | *.xcuserdatad 11 | 12 | # Textmate - if you build your xcode projects with it 13 | *.tm_build_errors 14 | 15 | # old skool 16 | .svn 17 | 18 | # osx noise 19 | *.DS_Store 20 | profile -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Dependencies/MSWeakTimer"] 2 | path = Dependencies/MSWeakTimer 3 | url = git@github.com:mindsnacks/MSWeakTimer.git 4 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 1D51247214EBC8DC00117DD2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D51247114EBC8DC00117DD2 /* UIKit.framework */; }; 11 | 1D51247414EBC8DC00117DD2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D51247314EBC8DC00117DD2 /* Foundation.framework */; }; 12 | 1D51247614EBC8DC00117DD2 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D51247514EBC8DC00117DD2 /* CoreGraphics.framework */; }; 13 | 1D51247C14EBC8DC00117DD2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1D51247A14EBC8DC00117DD2 /* InfoPlist.strings */; }; 14 | 1D51247E14EBC8DC00117DD2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D51247D14EBC8DC00117DD2 /* main.m */; }; 15 | 1D51248214EBC8DC00117DD2 /* JSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D51248114EBC8DC00117DD2 /* JSAppDelegate.m */; }; 16 | 1D51248514EBC8DC00117DD2 /* JSViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D51248414EBC8DC00117DD2 /* JSViewController.m */; }; 17 | 1D51248814EBC8DC00117DD2 /* JSViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1D51248614EBC8DC00117DD2 /* JSViewController.xib */; }; 18 | 1D51249114EBC8FA00117DD2 /* JSAnimatedImagesView.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D51248F14EBC8FA00117DD2 /* JSAnimatedImagesView.m */; }; 19 | 1D51249C14EBCCBB00117DD2 /* image1.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1D51249914EBCCBB00117DD2 /* image1.jpg */; }; 20 | 1D51249D14EBCCBB00117DD2 /* image2.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1D51249A14EBCCBB00117DD2 /* image2.jpg */; }; 21 | 1D51249E14EBCCBB00117DD2 /* image3.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 1D51249B14EBCCBB00117DD2 /* image3.jpg */; }; 22 | D04F4701178F8E7E00C7B81D /* MSWeakTimer.m in Sources */ = {isa = PBXBuildFile; fileRef = D04F4700178F8E7E00C7B81D /* MSWeakTimer.m */; }; 23 | D05E21EF162D0EAC00E962ED /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D05E21EE162D0EAC00E962ED /* Default-568h@2x.png */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXFileReference section */ 27 | 1D51246D14EBC8DC00117DD2 /* AnimatedImagesViewSampleApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AnimatedImagesViewSampleApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 28 | 1D51247114EBC8DC00117DD2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 29 | 1D51247314EBC8DC00117DD2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 30 | 1D51247514EBC8DC00117DD2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 31 | 1D51247914EBC8DC00117DD2 /* AnimatedImagesViewSampleApp-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AnimatedImagesViewSampleApp-Info.plist"; sourceTree = ""; }; 32 | 1D51247B14EBC8DC00117DD2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 33 | 1D51247D14EBC8DC00117DD2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 1D51247F14EBC8DC00117DD2 /* AnimatedImagesViewSampleApp-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AnimatedImagesViewSampleApp-Prefix.pch"; sourceTree = ""; }; 35 | 1D51248014EBC8DC00117DD2 /* JSAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSAppDelegate.h; sourceTree = ""; }; 36 | 1D51248114EBC8DC00117DD2 /* JSAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JSAppDelegate.m; sourceTree = ""; }; 37 | 1D51248314EBC8DC00117DD2 /* JSViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSViewController.h; sourceTree = ""; }; 38 | 1D51248414EBC8DC00117DD2 /* JSViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = JSViewController.m; sourceTree = ""; }; 39 | 1D51248714EBC8DC00117DD2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/JSViewController.xib; sourceTree = ""; }; 40 | 1D51248F14EBC8FA00117DD2 /* JSAnimatedImagesView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSAnimatedImagesView.m; path = ../../JSAnimatedImagesView.m; sourceTree = ""; }; 41 | 1D51249014EBC8FA00117DD2 /* JSAnimatedImagesView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSAnimatedImagesView.h; path = ../../JSAnimatedImagesView.h; sourceTree = ""; }; 42 | 1D51249914EBCCBB00117DD2 /* image1.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = image1.jpg; path = Resources/image1.jpg; sourceTree = ""; }; 43 | 1D51249A14EBCCBB00117DD2 /* image2.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = image2.jpg; path = Resources/image2.jpg; sourceTree = ""; }; 44 | 1D51249B14EBCCBB00117DD2 /* image3.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; name = image3.jpg; path = Resources/image3.jpg; sourceTree = ""; }; 45 | D04F46FF178F8E7E00C7B81D /* MSWeakTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MSWeakTimer.h; path = ../../Dependencies/MSWeakTimer/MSWeakTimer.h; sourceTree = ""; }; 46 | D04F4700178F8E7E00C7B81D /* MSWeakTimer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MSWeakTimer.m; path = ../../Dependencies/MSWeakTimer/MSWeakTimer.m; sourceTree = ""; }; 47 | D05E21EE162D0EAC00E962ED /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-568h@2x.png"; path = "Resources/Default-568h@2x.png"; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 1D51246A14EBC8DC00117DD2 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | 1D51247214EBC8DC00117DD2 /* UIKit.framework in Frameworks */, 56 | 1D51247414EBC8DC00117DD2 /* Foundation.framework in Frameworks */, 57 | 1D51247614EBC8DC00117DD2 /* CoreGraphics.framework in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | 1D51246214EBC8DB00117DD2 = { 65 | isa = PBXGroup; 66 | children = ( 67 | 1D51247714EBC8DC00117DD2 /* AnimatedImagesViewSampleApp */, 68 | 1D51247014EBC8DC00117DD2 /* Frameworks */, 69 | 1D51246E14EBC8DC00117DD2 /* Products */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | 1D51246E14EBC8DC00117DD2 /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | 1D51246D14EBC8DC00117DD2 /* AnimatedImagesViewSampleApp.app */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | 1D51247014EBC8DC00117DD2 /* Frameworks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 1D51247114EBC8DC00117DD2 /* UIKit.framework */, 85 | 1D51247314EBC8DC00117DD2 /* Foundation.framework */, 86 | 1D51247514EBC8DC00117DD2 /* CoreGraphics.framework */, 87 | ); 88 | name = Frameworks; 89 | sourceTree = ""; 90 | }; 91 | 1D51247714EBC8DC00117DD2 /* AnimatedImagesViewSampleApp */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 1D51248014EBC8DC00117DD2 /* JSAppDelegate.h */, 95 | 1D51248114EBC8DC00117DD2 /* JSAppDelegate.m */, 96 | 1D51248314EBC8DC00117DD2 /* JSViewController.h */, 97 | 1D51248414EBC8DC00117DD2 /* JSViewController.m */, 98 | 1D51248614EBC8DC00117DD2 /* JSViewController.xib */, 99 | 1D51248E14EBC8F200117DD2 /* JSAnimatedImagesView */, 100 | D04F46FE178F8E7500C7B81D /* MSWeakTimer */, 101 | 1D51249814EBCCB000117DD2 /* Resources */, 102 | 1D51247814EBC8DC00117DD2 /* Supporting Files */, 103 | ); 104 | path = AnimatedImagesViewSampleApp; 105 | sourceTree = ""; 106 | }; 107 | 1D51247814EBC8DC00117DD2 /* Supporting Files */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | 1D51247914EBC8DC00117DD2 /* AnimatedImagesViewSampleApp-Info.plist */, 111 | 1D51247A14EBC8DC00117DD2 /* InfoPlist.strings */, 112 | 1D51247D14EBC8DC00117DD2 /* main.m */, 113 | 1D51247F14EBC8DC00117DD2 /* AnimatedImagesViewSampleApp-Prefix.pch */, 114 | ); 115 | name = "Supporting Files"; 116 | sourceTree = ""; 117 | }; 118 | 1D51248E14EBC8F200117DD2 /* JSAnimatedImagesView */ = { 119 | isa = PBXGroup; 120 | children = ( 121 | 1D51249014EBC8FA00117DD2 /* JSAnimatedImagesView.h */, 122 | 1D51248F14EBC8FA00117DD2 /* JSAnimatedImagesView.m */, 123 | ); 124 | name = JSAnimatedImagesView; 125 | sourceTree = ""; 126 | }; 127 | 1D51249814EBCCB000117DD2 /* Resources */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | 1D51249914EBCCBB00117DD2 /* image1.jpg */, 131 | 1D51249A14EBCCBB00117DD2 /* image2.jpg */, 132 | 1D51249B14EBCCBB00117DD2 /* image3.jpg */, 133 | D05E21EE162D0EAC00E962ED /* Default-568h@2x.png */, 134 | ); 135 | name = Resources; 136 | sourceTree = ""; 137 | }; 138 | D04F46FE178F8E7500C7B81D /* MSWeakTimer */ = { 139 | isa = PBXGroup; 140 | children = ( 141 | D04F46FF178F8E7E00C7B81D /* MSWeakTimer.h */, 142 | D04F4700178F8E7E00C7B81D /* MSWeakTimer.m */, 143 | ); 144 | name = MSWeakTimer; 145 | sourceTree = ""; 146 | }; 147 | /* End PBXGroup section */ 148 | 149 | /* Begin PBXNativeTarget section */ 150 | 1D51246C14EBC8DC00117DD2 /* AnimatedImagesViewSampleApp */ = { 151 | isa = PBXNativeTarget; 152 | buildConfigurationList = 1D51248B14EBC8DC00117DD2 /* Build configuration list for PBXNativeTarget "AnimatedImagesViewSampleApp" */; 153 | buildPhases = ( 154 | 1D51246914EBC8DC00117DD2 /* Sources */, 155 | 1D51246A14EBC8DC00117DD2 /* Frameworks */, 156 | 1D51246B14EBC8DC00117DD2 /* Resources */, 157 | ); 158 | buildRules = ( 159 | ); 160 | dependencies = ( 161 | ); 162 | name = AnimatedImagesViewSampleApp; 163 | productName = AnimatedImagesViewSampleApp; 164 | productReference = 1D51246D14EBC8DC00117DD2 /* AnimatedImagesViewSampleApp.app */; 165 | productType = "com.apple.product-type.application"; 166 | }; 167 | /* End PBXNativeTarget section */ 168 | 169 | /* Begin PBXProject section */ 170 | 1D51246414EBC8DC00117DD2 /* Project object */ = { 171 | isa = PBXProject; 172 | attributes = { 173 | LastUpgradeCheck = 0420; 174 | }; 175 | buildConfigurationList = 1D51246714EBC8DC00117DD2 /* Build configuration list for PBXProject "AnimatedImagesViewSampleApp" */; 176 | compatibilityVersion = "Xcode 3.2"; 177 | developmentRegion = English; 178 | hasScannedForEncodings = 0; 179 | knownRegions = ( 180 | en, 181 | ); 182 | mainGroup = 1D51246214EBC8DB00117DD2; 183 | productRefGroup = 1D51246E14EBC8DC00117DD2 /* Products */; 184 | projectDirPath = ""; 185 | projectRoot = ""; 186 | targets = ( 187 | 1D51246C14EBC8DC00117DD2 /* AnimatedImagesViewSampleApp */, 188 | ); 189 | }; 190 | /* End PBXProject section */ 191 | 192 | /* Begin PBXResourcesBuildPhase section */ 193 | 1D51246B14EBC8DC00117DD2 /* Resources */ = { 194 | isa = PBXResourcesBuildPhase; 195 | buildActionMask = 2147483647; 196 | files = ( 197 | 1D51247C14EBC8DC00117DD2 /* InfoPlist.strings in Resources */, 198 | 1D51248814EBC8DC00117DD2 /* JSViewController.xib in Resources */, 199 | 1D51249C14EBCCBB00117DD2 /* image1.jpg in Resources */, 200 | 1D51249D14EBCCBB00117DD2 /* image2.jpg in Resources */, 201 | 1D51249E14EBCCBB00117DD2 /* image3.jpg in Resources */, 202 | D05E21EF162D0EAC00E962ED /* Default-568h@2x.png in Resources */, 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | }; 206 | /* End PBXResourcesBuildPhase section */ 207 | 208 | /* Begin PBXSourcesBuildPhase section */ 209 | 1D51246914EBC8DC00117DD2 /* Sources */ = { 210 | isa = PBXSourcesBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | 1D51247E14EBC8DC00117DD2 /* main.m in Sources */, 214 | 1D51248214EBC8DC00117DD2 /* JSAppDelegate.m in Sources */, 215 | 1D51248514EBC8DC00117DD2 /* JSViewController.m in Sources */, 216 | 1D51249114EBC8FA00117DD2 /* JSAnimatedImagesView.m in Sources */, 217 | D04F4701178F8E7E00C7B81D /* MSWeakTimer.m in Sources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXSourcesBuildPhase section */ 222 | 223 | /* Begin PBXVariantGroup section */ 224 | 1D51247A14EBC8DC00117DD2 /* InfoPlist.strings */ = { 225 | isa = PBXVariantGroup; 226 | children = ( 227 | 1D51247B14EBC8DC00117DD2 /* en */, 228 | ); 229 | name = InfoPlist.strings; 230 | sourceTree = ""; 231 | }; 232 | 1D51248614EBC8DC00117DD2 /* JSViewController.xib */ = { 233 | isa = PBXVariantGroup; 234 | children = ( 235 | 1D51248714EBC8DC00117DD2 /* en */, 236 | ); 237 | name = JSViewController.xib; 238 | sourceTree = ""; 239 | }; 240 | /* End PBXVariantGroup section */ 241 | 242 | /* Begin XCBuildConfiguration section */ 243 | 1D51248914EBC8DC00117DD2 /* Debug */ = { 244 | isa = XCBuildConfiguration; 245 | buildSettings = { 246 | ALWAYS_SEARCH_USER_PATHS = NO; 247 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 248 | CLANG_ENABLE_OBJC_ARC = YES; 249 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 250 | COPY_PHASE_STRIP = NO; 251 | GCC_C_LANGUAGE_STANDARD = gnu99; 252 | GCC_DYNAMIC_NO_PIC = NO; 253 | GCC_OPTIMIZATION_LEVEL = 0; 254 | GCC_PREPROCESSOR_DEFINITIONS = ( 255 | "DEBUG=1", 256 | "$(inherited)", 257 | ); 258 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 259 | GCC_VERSION = ""; 260 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 261 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 262 | GCC_WARN_UNUSED_VARIABLE = YES; 263 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 264 | SDKROOT = iphoneos; 265 | }; 266 | name = Debug; 267 | }; 268 | 1D51248A14EBC8DC00117DD2 /* Release */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | ALWAYS_SEARCH_USER_PATHS = NO; 272 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 273 | CLANG_ENABLE_OBJC_ARC = YES; 274 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 275 | COPY_PHASE_STRIP = YES; 276 | GCC_C_LANGUAGE_STANDARD = gnu99; 277 | GCC_VERSION = ""; 278 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 279 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 280 | GCC_WARN_UNUSED_VARIABLE = YES; 281 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 282 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 283 | SDKROOT = iphoneos; 284 | VALIDATE_PRODUCT = YES; 285 | }; 286 | name = Release; 287 | }; 288 | 1D51248C14EBC8DC00117DD2 /* Debug */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 292 | GCC_PREFIX_HEADER = "AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp-Prefix.pch"; 293 | INFOPLIST_FILE = "AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp-Info.plist"; 294 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 295 | PRODUCT_NAME = "$(TARGET_NAME)"; 296 | WRAPPER_EXTENSION = app; 297 | }; 298 | name = Debug; 299 | }; 300 | 1D51248D14EBC8DC00117DD2 /* Release */ = { 301 | isa = XCBuildConfiguration; 302 | buildSettings = { 303 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 304 | GCC_PREFIX_HEADER = "AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp-Prefix.pch"; 305 | INFOPLIST_FILE = "AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp-Info.plist"; 306 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 307 | PRODUCT_NAME = "$(TARGET_NAME)"; 308 | WRAPPER_EXTENSION = app; 309 | }; 310 | name = Release; 311 | }; 312 | /* End XCBuildConfiguration section */ 313 | 314 | /* Begin XCConfigurationList section */ 315 | 1D51246714EBC8DC00117DD2 /* Build configuration list for PBXProject "AnimatedImagesViewSampleApp" */ = { 316 | isa = XCConfigurationList; 317 | buildConfigurations = ( 318 | 1D51248914EBC8DC00117DD2 /* Debug */, 319 | 1D51248A14EBC8DC00117DD2 /* Release */, 320 | ); 321 | defaultConfigurationIsVisible = 0; 322 | defaultConfigurationName = Release; 323 | }; 324 | 1D51248B14EBC8DC00117DD2 /* Build configuration list for PBXNativeTarget "AnimatedImagesViewSampleApp" */ = { 325 | isa = XCConfigurationList; 326 | buildConfigurations = ( 327 | 1D51248C14EBC8DC00117DD2 /* Debug */, 328 | 1D51248D14EBC8DC00117DD2 /* Release */, 329 | ); 330 | defaultConfigurationIsVisible = 0; 331 | defaultConfigurationName = Release; 332 | }; 333 | /* End XCConfigurationList section */ 334 | }; 335 | rootObject = 1D51246414EBC8DC00117DD2 /* Project object */; 336 | } 337 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp.xcodeproj/project.xcworkspace/xcuserdata/javiersoto.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaviSoto/JSAnimatedImagesView/38870abfb7810a60531f1218fcb551a74d5bb2da/AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp.xcodeproj/project.xcworkspace/xcuserdata/javiersoto.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp.xcodeproj/xcuserdata/javiersoto.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp.xcodeproj/xcuserdata/javiersoto.xcuserdatad/xcschemes/AnimatedImagesViewSampleApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 4 | 7 | 8 | 14 | 20 | 21 | 22 | 23 | 24 | 29 | 30 | 31 | 32 | 38 | 39 | 40 | 41 | 49 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 67 | 68 | 74 | 75 | 76 | 77 | 79 | 80 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp.xcodeproj/xcuserdata/javiersoto.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | AnimatedImagesViewSampleApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 1D51246C14EBC8DC00117DD2 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | es.javisoto.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | UIStatusBarStyle 28 | UIStatusBarStyleBlackOpaque 29 | LSRequiresIPhoneOS 30 | 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'AnimatedImagesViewSampleApp' target in the 'AnimatedImagesViewSampleApp' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_5_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/JSAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // JSAppDelegate.h 3 | // AnimatedImagesViewSampleApp 4 | // 5 | // Created by Javier Soto on 2/15/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class JSViewController; 12 | 13 | @interface JSAppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) JSViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/JSAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // JSAppDelegate.m 3 | // AnimatedImagesViewSampleApp 4 | // 5 | // Created by Javier Soto on 2/15/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "JSAppDelegate.h" 10 | 11 | #import "JSViewController.h" 12 | 13 | @implementation JSAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | 19 | self.viewController = [[JSViewController alloc] initWithNibName:@"JSViewController" bundle:nil]; 20 | self.window.rootViewController = self.viewController; 21 | [self.window makeKeyAndVisible]; 22 | 23 | return YES; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/JSViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // JSViewController.h 3 | // AnimatedImagesViewSampleApp 4 | // 5 | // Created by Javier Soto on 2/15/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "JSAnimatedImagesView.h" 12 | 13 | @interface JSViewController : UIViewController 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/JSViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // JSViewController.m 3 | // AnimatedImagesViewSampleApp 4 | // 5 | // Created by Javier Soto on 2/15/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import "JSViewController.h" 10 | 11 | #import 12 | 13 | @interface JSViewController() 14 | 15 | @property (strong, nonatomic) IBOutlet JSAnimatedImagesView *animatedImagesView; 16 | @property (strong, nonatomic) IBOutlet UIView *infoBox; 17 | 18 | @end 19 | 20 | @implementation JSViewController 21 | 22 | #pragma mark - View Life Cycle 23 | 24 | - (void)viewDidLoad 25 | { 26 | [super viewDidLoad]; 27 | 28 | self.animatedImagesView.dataSource = self; 29 | 30 | self.infoBox.layer.cornerRadius = 6; 31 | } 32 | 33 | #pragma mark - JSAnimatedImagesViewDataSource Methods 34 | 35 | - (NSUInteger)animatedImagesNumberOfImages:(JSAnimatedImagesView *)animatedImagesView 36 | { 37 | return 3; 38 | } 39 | 40 | - (UIImage *)animatedImagesView:(JSAnimatedImagesView *)animatedImagesView imageAtIndex:(NSUInteger)index 41 | { 42 | return [UIImage imageNamed:[NSString stringWithFormat:@"image%d.jpg", index + 1]]; 43 | } 44 | 45 | #pragma mark - UI 46 | 47 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation 48 | { 49 | return (toInterfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); 50 | } 51 | 52 | #ifdef __IPHONE_6_0 53 | - (NSUInteger)supportedInterfaceOrientations 54 | { 55 | return UIInterfaceOrientationMaskAllButUpsideDown; 56 | } 57 | #endif 58 | 59 | @end -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaviSoto/JSAnimatedImagesView/38870abfb7810a60531f1218fcb551a74d5bb2da/AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/Resources/image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaviSoto/JSAnimatedImagesView/38870abfb7810a60531f1218fcb551a74d5bb2da/AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/Resources/image1.jpg -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/Resources/image2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaviSoto/JSAnimatedImagesView/38870abfb7810a60531f1218fcb551a74d5bb2da/AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/Resources/image2.jpg -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/Resources/image3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JaviSoto/JSAnimatedImagesView/38870abfb7810a60531f1218fcb551a74d5bb2da/AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/Resources/image3.jpg -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/en.lproj/JSViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 11D50 6 | 1938 7 | 1138.32 8 | 568.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 933 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | IBUILabel 17 | 18 | 19 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 20 | 21 | 22 | PluginDependencyRecalculationVersion 23 | 24 | 25 | 26 | 27 | IBFilesOwner 28 | IBCocoaTouchFramework 29 | 30 | 31 | IBFirstResponder 32 | IBCocoaTouchFramework 33 | 34 | 35 | 36 | 274 37 | 38 | 39 | 40 | 274 41 | {320, 460} 42 | 43 | 44 | _NS:196 45 | 46 | 3 47 | MAA 48 | 49 | IBCocoaTouchFramework 50 | 51 | 52 | 53 | 265 54 | 55 | 56 | 57 | 289 58 | {{52, 45}, {158, 21}} 59 | 60 | 61 | _NS:328 62 | NO 63 | YES 64 | 7 65 | NO 66 | IBCocoaTouchFramework 67 | https://github.com/JaviSoto 68 | 69 | 3 70 | MQA 71 | 72 | 73 | 1 74 | NO 75 | 10 76 | 2 77 | 78 | 1 79 | 11 80 | 81 | 82 | Helvetica 83 | 11 84 | 16 85 | 86 | 87 | 88 | 89 | 289 90 | {{0, 8}, {210, 21}} 91 | 92 | 93 | _NS:328 94 | NO 95 | YES 96 | 7 97 | NO 98 | IBCocoaTouchFramework 99 | JSAnimatedImagesView 100 | 101 | 102 | 103 | 3 104 | MCAwLjU3AA 105 | 106 | {0, 1} 107 | 1 108 | NO 109 | 10 110 | 2 111 | 112 | HelveticaNeue-Bold 113 | Helvetica Neue 114 | 2 115 | 17 116 | 117 | 118 | HelveticaNeue-Bold 119 | 17 120 | 16 121 | 122 | 123 | 124 | 125 | 289 126 | {{130, 27}, {80, 21}} 127 | 128 | 129 | _NS:328 130 | NO 131 | YES 132 | 7 133 | NO 134 | IBCocoaTouchFramework 135 | Javier Soto 136 | 137 | 138 | 1 139 | NO 140 | 10 141 | 2 142 | 143 | 1 144 | 15 145 | 146 | 147 | Helvetica 148 | 15 149 | 16 150 | 151 | 152 | 153 | {{79, 367}, {221, 73}} 154 | 155 | 156 | _NS:196 157 | 158 | 3 159 | MCAwLjY1AA 160 | 161 | IBCocoaTouchFramework 162 | 163 | 164 | {{0, 20}, {320, 460}} 165 | 166 | 167 | 168 | NO 169 | 170 | 2 171 | 172 | IBCocoaTouchFramework 173 | 174 | 175 | 176 | 177 | 178 | 179 | view 180 | 181 | 182 | 183 | 7 184 | 185 | 186 | 187 | animatedImagesView 188 | 189 | 190 | 191 | 9 192 | 193 | 194 | 195 | infoBox 196 | 197 | 198 | 199 | 14 200 | 201 | 202 | 203 | 204 | 205 | 0 206 | 207 | 208 | 209 | 210 | 211 | -1 212 | 213 | 214 | File's Owner 215 | 216 | 217 | -2 218 | 219 | 220 | 221 | 222 | 6 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 8 232 | 233 | 234 | 235 | 236 | 237 | 13 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | Info 246 | 247 | 248 | 12 249 | 250 | 251 | 252 | 253 | 10 254 | 255 | 256 | 257 | 258 | 11 259 | 260 | 261 | 262 | 263 | 264 | 265 | JSViewController 266 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 267 | UIResponder 268 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 269 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 270 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 271 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 272 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 273 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 274 | JSAnimatedImagesView 275 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 276 | 277 | 278 | 279 | 280 | 281 | 14 282 | 283 | 284 | 0 285 | IBCocoaTouchFramework 286 | YES 287 | 3 288 | 933 289 | 290 | 291 | -------------------------------------------------------------------------------- /AnimatedImagesViewSampleApp/AnimatedImagesViewSampleApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AnimatedImagesViewSampleApp 4 | // 5 | // Created by Javier Soto on 2/15/12. 6 | // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "JSAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([JSAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /JSAnimatedImagesView.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 JaviSoto (http://www.javisoto.me) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #import 24 | 25 | static const CGFloat JSAnimatedImagesViewDefaultTimePerImage = 5.0f; 26 | static const CGFloat JSAnimatedImagesViewDefaultImageSwappingAnimationDuration = 1.0f; 27 | static const BOOL JSAnimatedImagesViewDefaultMotionAnimationEnabled = YES; 28 | 29 | @protocol JSAnimatedImagesViewDataSource; 30 | 31 | @interface JSAnimatedImagesView : UIView 32 | 33 | @property (nonatomic, weak) id dataSource; 34 | 35 | /** 36 | Time between image transitions. 37 | @note The default value is `JSAnimatedImagesViewDefaultTimePerImage` 38 | */ 39 | @property (nonatomic, assign) NSTimeInterval timePerImage; 40 | 41 | /** 42 | The time it takes for images to fade out. 43 | @note The default value is `JSAnimatedImagesViewDefaultImageSwappingAnimationDuration` 44 | */ 45 | @property (nonatomic, assign) NSTimeInterval transitionDuration; 46 | 47 | /** 48 | Indicates weather the image should be zoomed and moved during display time. 49 | Setting this property affects only upcoming images if the animation has already been started. 50 | @note The default value is `JSAnimatedImagesViewDefaultMotionAnimationEnabled` 51 | */ 52 | @property (nonatomic, assign) BOOL motionAnimationEnabled; 53 | 54 | /** 55 | The view starts animating automatically when it becomes visible, but you can use this method to start the animations again if you stop them using the `stopAnimating`. 56 | */ 57 | - (void)startAnimating; 58 | 59 | /** 60 | The view automatically stops animating when it goes out of the screen, but you can choose to stop it manually using this method. You can re-start the animation using `startAnimating`. 61 | */ 62 | - (void)stopAnimating; 63 | 64 | /** 65 | Forces `JSAnimatedImagesView` to call the data source methods again. 66 | You can use this method if the number of images has changed. 67 | */ 68 | - (void)reloadData; 69 | 70 | @end 71 | 72 | @protocol JSAnimatedImagesViewDataSource 73 | 74 | /** 75 | Implement this method to tell `JSAnimatedImagesView` how many images it has to display. 76 | @param animatedImagesView The view that is requesting the number of images. 77 | */ 78 | - (NSUInteger)animatedImagesNumberOfImages:(JSAnimatedImagesView *)animatedImagesView; 79 | 80 | /** 81 | Implement this method to provide an image for `JSAnimatedImagesView` to display inmediately after. 82 | @param animatedImagesView The view that is requesting the image object. 83 | @param index The index of the image to return. This is a value between `0` and `totalNumberOfImages - 1` (@see `animatedImagesNumberOfImages:`). 84 | */ 85 | - (UIImage *)animatedImagesView:(JSAnimatedImagesView *)animatedImagesView imageAtIndex:(NSUInteger)index; 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /JSAnimatedImagesView.m: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2012 JaviSoto (http://www.javisoto.me) 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #import "JSAnimatedImagesView.h" 24 | 25 | #import "MSWeakTimer.h" 26 | 27 | #if !__has_feature(objc_arc) 28 | #error JSAnimatedImagesView requires ARC enabled. Mark the .m file with the objc_arc linker flag. 29 | #endif 30 | 31 | static const NSUInteger JSAnimatedImagesViewNoImageDisplayingIndex = -1; 32 | 33 | static const CGFloat JSAnimatedImagesViewImageViewsBorderOffset = 10; 34 | 35 | @interface JSAnimatedImagesView() 36 | { 37 | BOOL _animating; 38 | NSUInteger _totalImages; 39 | NSUInteger _currentlyDisplayingImageViewIndex; 40 | NSInteger _currentlyDisplayingImageIndex; 41 | 42 | NSArray *_imageViews; 43 | } 44 | 45 | @property (nonatomic, strong) MSWeakTimer *imageSwappingTimer; 46 | 47 | @end 48 | 49 | @implementation JSAnimatedImagesView 50 | 51 | - (id)initWithCoder:(NSCoder *)aDecoder 52 | { 53 | if ((self = [super initWithCoder:aDecoder])) 54 | { 55 | [self commonInit]; 56 | } 57 | 58 | return self; 59 | } 60 | 61 | - (id)initWithFrame:(CGRect)frame 62 | { 63 | if ((self = [super initWithFrame:frame])) 64 | { 65 | [self commonInit]; 66 | } 67 | 68 | return self; 69 | } 70 | 71 | - (void)commonInit 72 | { 73 | NSMutableArray *imageViews = [NSMutableArray array]; 74 | 75 | const NSUInteger numberOfImageViews = 2; 76 | 77 | for (int i = 0; i < numberOfImageViews; i++) 78 | { 79 | UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectInset(self.bounds, -JSAnimatedImagesViewImageViewsBorderOffset, -JSAnimatedImagesViewImageViewsBorderOffset)]; 80 | 81 | imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 82 | imageView.contentMode = UIViewContentModeScaleAspectFill; 83 | imageView.clipsToBounds = YES; 84 | 85 | [self addSubview:imageView]; 86 | 87 | [imageViews addObject:imageView]; 88 | } 89 | 90 | _imageViews = imageViews; 91 | 92 | _currentlyDisplayingImageIndex = JSAnimatedImagesViewNoImageDisplayingIndex; 93 | _timePerImage = JSAnimatedImagesViewDefaultTimePerImage; 94 | _transitionDuration = JSAnimatedImagesViewDefaultImageSwappingAnimationDuration; 95 | _motionAnimationEnabled = JSAnimatedImagesViewDefaultMotionAnimationEnabled; 96 | } 97 | 98 | #pragma mark - Animations 99 | 100 | - (void)startAnimating 101 | { 102 | NSAssert(self.dataSource != nil, @"You need to set the data source property"); 103 | 104 | if (!_animating) 105 | { 106 | _animating = YES; 107 | [self.imageSwappingTimer fire]; 108 | } 109 | } 110 | 111 | - (void)bringNextImage 112 | { 113 | NSAssert(_totalImages > 1, @"There should be more than 1 image to swap"); 114 | 115 | UIImageView *imageViewToHide = [_imageViews objectAtIndex:_currentlyDisplayingImageViewIndex]; 116 | 117 | _currentlyDisplayingImageViewIndex = _currentlyDisplayingImageViewIndex == 0 ? 1 : 0; 118 | 119 | UIImageView *imageViewToShow = [_imageViews objectAtIndex:_currentlyDisplayingImageViewIndex]; 120 | 121 | NSUInteger nextImageToShowIndex = _currentlyDisplayingImageIndex; 122 | 123 | do 124 | { 125 | nextImageToShowIndex = [[self class] randomNumberBetweenNumber:0 andNumber:_totalImages - 1]; 126 | } 127 | while (nextImageToShowIndex == _currentlyDisplayingImageIndex); 128 | 129 | _currentlyDisplayingImageIndex = nextImageToShowIndex; 130 | 131 | UIImage *imageToShow = [self.dataSource animatedImagesView:self imageAtIndex:nextImageToShowIndex]; 132 | NSAssert(imageToShow != nil, @"Must return an image"); 133 | 134 | imageViewToShow.image = imageToShow; 135 | 136 | static const CGFloat kMovementAndTransitionTimeOffset = 0.1; 137 | 138 | /* Move image animation */ 139 | if (self.motionAnimationEnabled) { 140 | [UIView animateWithDuration:self.timePerImage + self.transitionDuration + kMovementAndTransitionTimeOffset 141 | delay:0.0 142 | options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseIn 143 | animations:^ 144 | { 145 | NSInteger randomTranslationValueX = [[self class] randomNumberBetweenNumber:0 andNumber:JSAnimatedImagesViewImageViewsBorderOffset] - JSAnimatedImagesViewImageViewsBorderOffset; 146 | NSInteger randomTranslationValueY = [[self class] randomNumberBetweenNumber:0 andNumber:JSAnimatedImagesViewImageViewsBorderOffset] - JSAnimatedImagesViewImageViewsBorderOffset; 147 | 148 | CGAffineTransform translationTransform = CGAffineTransformMakeTranslation(randomTranslationValueX, randomTranslationValueY); 149 | 150 | CGFloat randomScaleTransformValue = [[self class] randomNumberBetweenNumber:115 andNumber:120] / 100.0f; 151 | 152 | CGAffineTransform scaleTransform = CGAffineTransformMakeScale(randomScaleTransformValue, randomScaleTransformValue); 153 | 154 | imageViewToShow.transform = CGAffineTransformConcat(scaleTransform, translationTransform); 155 | } 156 | completion:NULL]; 157 | } 158 | 159 | /* Fade animation */ 160 | [UIView animateWithDuration:self.transitionDuration 161 | delay:kMovementAndTransitionTimeOffset 162 | options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationCurveEaseIn 163 | animations:^ 164 | { 165 | imageViewToShow.alpha = 1.0; 166 | imageViewToHide.alpha = 0.0; 167 | } 168 | completion:^(BOOL finished) 169 | { 170 | if (finished) 171 | { 172 | imageViewToHide.transform = CGAffineTransformIdentity; 173 | } 174 | }]; 175 | } 176 | 177 | - (void)reloadData 178 | { 179 | _totalImages = [self.dataSource animatedImagesNumberOfImages:self]; 180 | 181 | // Using the ivar directly. If there's no timer, it's because the animations are stopped. 182 | [_imageSwappingTimer fire]; 183 | } 184 | 185 | - (void)stopAnimating 186 | { 187 | if (_animating) 188 | { 189 | self.imageSwappingTimer = nil; 190 | 191 | // Fade all image views out 192 | [UIView animateWithDuration:self.transitionDuration 193 | delay:0.0 194 | options:UIViewAnimationOptionBeginFromCurrentState 195 | animations:^ 196 | { 197 | for (UIImageView *imageView in _imageViews) 198 | { 199 | imageView.alpha = 0.0; 200 | } 201 | } 202 | completion:^(BOOL finished) 203 | { 204 | _currentlyDisplayingImageIndex = JSAnimatedImagesViewNoImageDisplayingIndex; 205 | _animating = NO; 206 | }]; 207 | } 208 | } 209 | 210 | #pragma mark - Parameters 211 | 212 | - (void)setDataSource:(id)dataSource 213 | { 214 | if (dataSource != _dataSource) 215 | { 216 | _dataSource = dataSource; 217 | _totalImages = [_dataSource animatedImagesNumberOfImages:self]; 218 | } 219 | } 220 | 221 | #pragma mark - Getters 222 | 223 | - (MSWeakTimer *)imageSwappingTimer 224 | { 225 | if (!_imageSwappingTimer) 226 | { 227 | _imageSwappingTimer = [MSWeakTimer scheduledTimerWithTimeInterval:self.timePerImage 228 | target:self 229 | selector:@selector(bringNextImage) 230 | userInfo:nil 231 | repeats:YES 232 | dispatchQueue:dispatch_get_main_queue()]; 233 | } 234 | 235 | return _imageSwappingTimer; 236 | } 237 | 238 | #pragma mark - View Life Cycle 239 | 240 | - (void)didMoveToWindow 241 | { 242 | const BOOL didAppear = (self.window != nil); 243 | 244 | if (didAppear) 245 | { 246 | [self startAnimating]; 247 | } 248 | else 249 | { 250 | [self stopAnimating]; 251 | } 252 | } 253 | 254 | #pragma mark - Random Numbers 255 | 256 | + (NSUInteger)randomNumberBetweenNumber:(NSUInteger)minNumber andNumber:(NSUInteger)maxNumber 257 | { 258 | if (minNumber > maxNumber) 259 | { 260 | return [self randomNumberBetweenNumber:maxNumber andNumber:minNumber]; 261 | } 262 | 263 | NSUInteger randomInt = (arc4random_uniform((u_int32_t)(maxNumber - minNumber + 1))) + minNumber; 264 | 265 | return randomInt; 266 | } 267 | 268 | @end 269 | -------------------------------------------------------------------------------- /JSAnimatedImagesView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "JSAnimatedImagesView" 3 | s.version = "1.0.0" 4 | s.summary = "UIView subclass to easily add a cool animated photo carrusel to your iOS app." 5 | s.homepage = "https://github.com/JaviSoto/JSAnimatedImagesView" 6 | 7 | s.license = { :type => 'MIT', :file => 'LICENSE' } 8 | s.author = { "Javier Soto" => "ios@javisoto.es" } 9 | 10 | s.source = { :git => "https://github.com/JaviSoto/JSAnimatedImagesView.git", :tag => "1.0.0" } 11 | s.platform = :ios, '5.0' 12 | s.platform = :tvos, '9.0' 13 | s.source_files = 'JSAnimatedImagesView.{h,m}' 14 | s.requires_arc = true 15 | s.dependency 'MSWeakTimer', '~> 1.0' 16 | end 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 JaviSoto (http://www.javisoto.me) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ## Description: 2 | Easy to use UIView subclass to quickly add a cool animated carrousel of pictures to your app. 3 | 4 | Documentation: http://cocoadocs.org/docsets/JSAnimatedImagesView/ 5 | 6 | ## Sample: 7 | 8 | ![Video](http://cl.ly/1x0P2o2I053L1W2B2h3J/Screen%20Shot%202012-02-15%20at%202.33.09%20PM.png) 9 | 10 | http://jsoto.es/xmKcLb 11 | 12 | ## Usage 13 | 14 | - Using [CocoaPods](http://cocoapods.org/): 15 | - Add `pod 'JSAnimatedImagesView', '~> 1.0.'` to your `Podfile`. 16 | - You're done! 17 | 18 | -- or -- 19 | 20 | - Clone the repository: 21 | 22 | ```bash 23 | $ git clone git@github.com:JaviSoto/JSAnimatedImagesView.git 24 | ``` 25 | 26 | - Update the submodules: 27 | 28 | ```bash 29 | $ git submodule update --init 30 | ``` 31 | 32 | - Check out the sample project. 33 | - Drag the two files ```JSAnimatedImagesView.(h/m)``` onto your project. 34 | - Drag `Dependencies/MSWeakTimer/MSWeakTimer.(h/m)` onto your project. 35 | - Include the header file ```JSAnimatedImagesView.h``` into the controller where you want to use it. 36 | - Create a ```JSAnimatedImagesView``` instance either via code, or in interface builder (by creating a UIView and changing its class to ```JSAnimatedImagesView```). 37 | - Set the data source property on the view (probably on the ```viewDidLoad``` method): 38 | 39 | ```objc 40 | self.animatedImagesView.dataSource = self; 41 | ``` 42 | 43 | - Implement the data source methods: 44 | 45 | ```objectivec 46 | 47 | @interface MyViewController () // Conform to the protocol 48 | 49 | @end 50 | ``` 51 | 52 | ```objc 53 | @implementation MyViewController 54 | 55 | - (NSUInteger)animatedImagesNumberOfImages:(JSAnimatedImagesView *)animatedImagesView 56 | { 57 | return self.myImageNames.count; 58 | } 59 | 60 | - (UIImage *)animatedImagesView:(JSAnimatedImagesView *)animatedImagesView imageAtIndex:(NSUInteger)index 61 | { 62 | return [UIImage imageNamed:[self.myImageNames objectAtIndex:index]]; 63 | } 64 | 65 | @end 66 | ``` 67 | 68 | ## Configuration 69 | 70 | ```objc 71 | @property (nonatomic, assign) NSTimeInterval timePerImage; 72 | ``` 73 | 74 | Specifies the time each image is viewed until the next image is faded in. 75 | 76 | ```objc 77 | @property (nonatomic, assign) NSTimeInterval transitionDuration; 78 | ``` 79 | 80 | Specifies the duration of the transition (fade-out/fade-in) animation. 81 | 82 | 83 | ## Compatibility 84 | - ```JSAnimatedImagesView``` is compatible with iOS5.0+ 85 | - ```JSAnimatedImagesView``` requires ARC. 86 | 87 | ## Attributions (Creative Commons Images) 88 | + http://www.flickr.com/photos/blmiers2/ 89 | + http://www.flickr.com/photos/niamor/ 90 | + http://www.flickr.com/photos/macieklew/ 91 | 92 | ## License 93 | `JSAnimatedImagesView` is available under the MIT license. See the LICENSE file for more info. 94 | --------------------------------------------------------------------------------