├── CHANGELOG.md ├── Example ├── .gitignore ├── Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── Example.xcworkspace │ └── contents.xcworkspacedata ├── Example │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Info.plist │ └── ViewController.swift └── Podfile ├── LICENSE ├── README.md ├── Screenshot.gif ├── Source ├── ImageSliderCell.swift ├── ImageSliderCellDelegate.swift ├── ImageSliderUtility.swift ├── ImageSliderView.swift ├── ImageSliderViewController.swift └── ImageSliderViewDelegate.swift ├── SwiftImageSlider.bundle ├── en.lproj │ └── SwiftImageSlider.strings └── zh-Hans.lproj │ └── SwiftImageSlider.strings └── SwiftImageSlider.podspec /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 0.2.1 2016-11-11 2 | * Replace Kingfisher api with [Kingfisher3.0](https://github.com/onevcat/Kingfisher/wiki/Kingfisher-3.0-Migration-Guide) 3 | 4 | ## 0.2.0 2016-11-10 5 | * Migrate to swift 3.0 6 | 7 | ## 0.1.6 2016-06-15 8 | * Set access level to public for ImageSliderView#scrollView & ImageSliderView#delegate 9 | 10 | ## 0.1.5 2016-06-15 11 | * Set access level to public for ImageSliderViewController#imageSliderView & ImageSliderViewController#displayLabel 12 | 13 | ## 0.1.3 2016-06-08 14 | * Let image fix scroll view width all time 15 | 16 | ## 0.1.0 2016-06-05 17 | * Initial release 18 | -------------------------------------------------------------------------------- /Example/.gitignore: -------------------------------------------------------------------------------- 1 | ## Build generated 2 | build/ 3 | DerivedData 4 | 5 | ## Various settings 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | 16 | ## Other 17 | *.xccheckout 18 | *.moved-aside 19 | *.xcuserstate 20 | *.xcscmblueprint 21 | 22 | ## Obj-C/Swift specific 23 | *.hmap 24 | *.ipa 25 | 26 | Pods/ 27 | 28 | **/.DS_Store 29 | Podfile.lock -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6A2FFDA3BC3AEED1E9812B3C /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1C63FFC89D1DF6FC4743794 /* Pods_Example.framework */; }; 11 | E2AAFC401D02C00700F85EB1 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2AAFC3F1D02C00700F85EB1 /* AppDelegate.swift */; }; 12 | E2AAFC421D02C00700F85EB1 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2AAFC411D02C00700F85EB1 /* ViewController.swift */; }; 13 | E2AAFC451D02C00700F85EB1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E2AAFC431D02C00700F85EB1 /* Main.storyboard */; }; 14 | E2AAFC471D02C00700F85EB1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E2AAFC461D02C00700F85EB1 /* Assets.xcassets */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | A1C63FFC89D1DF6FC4743794 /* Pods_Example.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | B17E902500E1C67590DF71FC /* Pods-Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig"; sourceTree = ""; }; 20 | C8C4C2C83CBA2AF09B8C50E4 /* Pods-Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig"; sourceTree = ""; }; 21 | E2AAFC3C1D02C00700F85EB1 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | E2AAFC3F1D02C00700F85EB1 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 23 | E2AAFC411D02C00700F85EB1 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 24 | E2AAFC441D02C00700F85EB1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 25 | E2AAFC461D02C00700F85EB1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | E2AAFC4B1D02C00700F85EB1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 27 | /* End PBXFileReference section */ 28 | 29 | /* Begin PBXFrameworksBuildPhase section */ 30 | E2AAFC391D02C00700F85EB1 /* Frameworks */ = { 31 | isa = PBXFrameworksBuildPhase; 32 | buildActionMask = 2147483647; 33 | files = ( 34 | 6A2FFDA3BC3AEED1E9812B3C /* Pods_Example.framework in Frameworks */, 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | E2AAFC331D02C00700F85EB1 = { 42 | isa = PBXGroup; 43 | children = ( 44 | E2AAFC3E1D02C00700F85EB1 /* Example */, 45 | E2AAFC3D1D02C00700F85EB1 /* Products */, 46 | FDC68372E016134075A09FF6 /* Pods */, 47 | EA73C8C6CEC6B890EAEF3B13 /* Frameworks */, 48 | ); 49 | sourceTree = ""; 50 | }; 51 | E2AAFC3D1D02C00700F85EB1 /* Products */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | E2AAFC3C1D02C00700F85EB1 /* Example.app */, 55 | ); 56 | name = Products; 57 | sourceTree = ""; 58 | }; 59 | E2AAFC3E1D02C00700F85EB1 /* Example */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | E2AAFC3F1D02C00700F85EB1 /* AppDelegate.swift */, 63 | E2AAFC411D02C00700F85EB1 /* ViewController.swift */, 64 | E2AAFC431D02C00700F85EB1 /* Main.storyboard */, 65 | E2AAFC461D02C00700F85EB1 /* Assets.xcassets */, 66 | E2AAFC4B1D02C00700F85EB1 /* Info.plist */, 67 | ); 68 | path = Example; 69 | sourceTree = ""; 70 | }; 71 | EA73C8C6CEC6B890EAEF3B13 /* Frameworks */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | A1C63FFC89D1DF6FC4743794 /* Pods_Example.framework */, 75 | ); 76 | name = Frameworks; 77 | sourceTree = ""; 78 | }; 79 | FDC68372E016134075A09FF6 /* Pods */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | C8C4C2C83CBA2AF09B8C50E4 /* Pods-Example.debug.xcconfig */, 83 | B17E902500E1C67590DF71FC /* Pods-Example.release.xcconfig */, 84 | ); 85 | name = Pods; 86 | sourceTree = ""; 87 | }; 88 | /* End PBXGroup section */ 89 | 90 | /* Begin PBXNativeTarget section */ 91 | E2AAFC3B1D02C00700F85EB1 /* Example */ = { 92 | isa = PBXNativeTarget; 93 | buildConfigurationList = E2AAFC4E1D02C00700F85EB1 /* Build configuration list for PBXNativeTarget "Example" */; 94 | buildPhases = ( 95 | C06D7B3F46D69C697F4975F3 /* [CP] Check Pods Manifest.lock */, 96 | E2AAFC381D02C00700F85EB1 /* Sources */, 97 | E2AAFC391D02C00700F85EB1 /* Frameworks */, 98 | E2AAFC3A1D02C00700F85EB1 /* Resources */, 99 | 975A3B4FD971F08EACC9E37C /* [CP] Embed Pods Frameworks */, 100 | 8F6B7CC8E53497DA8FB42B69 /* [CP] Copy Pods Resources */, 101 | ); 102 | buildRules = ( 103 | ); 104 | dependencies = ( 105 | ); 106 | name = Example; 107 | productName = Example; 108 | productReference = E2AAFC3C1D02C00700F85EB1 /* Example.app */; 109 | productType = "com.apple.product-type.application"; 110 | }; 111 | /* End PBXNativeTarget section */ 112 | 113 | /* Begin PBXProject section */ 114 | E2AAFC341D02C00700F85EB1 /* Project object */ = { 115 | isa = PBXProject; 116 | attributes = { 117 | LastSwiftUpdateCheck = 0730; 118 | LastUpgradeCheck = 0730; 119 | ORGANIZATIONNAME = TomHuang; 120 | TargetAttributes = { 121 | E2AAFC3B1D02C00700F85EB1 = { 122 | CreatedOnToolsVersion = 7.3.1; 123 | LastSwiftMigration = 0810; 124 | }; 125 | }; 126 | }; 127 | buildConfigurationList = E2AAFC371D02C00700F85EB1 /* Build configuration list for PBXProject "Example" */; 128 | compatibilityVersion = "Xcode 3.2"; 129 | developmentRegion = English; 130 | hasScannedForEncodings = 0; 131 | knownRegions = ( 132 | en, 133 | Base, 134 | ); 135 | mainGroup = E2AAFC331D02C00700F85EB1; 136 | productRefGroup = E2AAFC3D1D02C00700F85EB1 /* Products */; 137 | projectDirPath = ""; 138 | projectRoot = ""; 139 | targets = ( 140 | E2AAFC3B1D02C00700F85EB1 /* Example */, 141 | ); 142 | }; 143 | /* End PBXProject section */ 144 | 145 | /* Begin PBXResourcesBuildPhase section */ 146 | E2AAFC3A1D02C00700F85EB1 /* Resources */ = { 147 | isa = PBXResourcesBuildPhase; 148 | buildActionMask = 2147483647; 149 | files = ( 150 | E2AAFC471D02C00700F85EB1 /* Assets.xcassets in Resources */, 151 | E2AAFC451D02C00700F85EB1 /* Main.storyboard in Resources */, 152 | ); 153 | runOnlyForDeploymentPostprocessing = 0; 154 | }; 155 | /* End PBXResourcesBuildPhase section */ 156 | 157 | /* Begin PBXShellScriptBuildPhase section */ 158 | 8F6B7CC8E53497DA8FB42B69 /* [CP] Copy Pods Resources */ = { 159 | isa = PBXShellScriptBuildPhase; 160 | buildActionMask = 2147483647; 161 | files = ( 162 | ); 163 | inputPaths = ( 164 | ); 165 | name = "[CP] Copy Pods Resources"; 166 | outputPaths = ( 167 | ); 168 | runOnlyForDeploymentPostprocessing = 0; 169 | shellPath = /bin/sh; 170 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-resources.sh\"\n"; 171 | showEnvVarsInLog = 0; 172 | }; 173 | 975A3B4FD971F08EACC9E37C /* [CP] Embed Pods Frameworks */ = { 174 | isa = PBXShellScriptBuildPhase; 175 | buildActionMask = 2147483647; 176 | files = ( 177 | ); 178 | inputPaths = ( 179 | ); 180 | name = "[CP] Embed Pods Frameworks"; 181 | outputPaths = ( 182 | ); 183 | runOnlyForDeploymentPostprocessing = 0; 184 | shellPath = /bin/sh; 185 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks.sh\"\n"; 186 | showEnvVarsInLog = 0; 187 | }; 188 | C06D7B3F46D69C697F4975F3 /* [CP] Check Pods Manifest.lock */ = { 189 | isa = PBXShellScriptBuildPhase; 190 | buildActionMask = 2147483647; 191 | files = ( 192 | ); 193 | inputPaths = ( 194 | ); 195 | name = "[CP] Check Pods Manifest.lock"; 196 | outputPaths = ( 197 | ); 198 | runOnlyForDeploymentPostprocessing = 0; 199 | shellPath = /bin/sh; 200 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; 201 | showEnvVarsInLog = 0; 202 | }; 203 | /* End PBXShellScriptBuildPhase section */ 204 | 205 | /* Begin PBXSourcesBuildPhase section */ 206 | E2AAFC381D02C00700F85EB1 /* Sources */ = { 207 | isa = PBXSourcesBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | E2AAFC421D02C00700F85EB1 /* ViewController.swift in Sources */, 211 | E2AAFC401D02C00700F85EB1 /* AppDelegate.swift in Sources */, 212 | ); 213 | runOnlyForDeploymentPostprocessing = 0; 214 | }; 215 | /* End PBXSourcesBuildPhase section */ 216 | 217 | /* Begin PBXVariantGroup section */ 218 | E2AAFC431D02C00700F85EB1 /* Main.storyboard */ = { 219 | isa = PBXVariantGroup; 220 | children = ( 221 | E2AAFC441D02C00700F85EB1 /* Base */, 222 | ); 223 | name = Main.storyboard; 224 | sourceTree = ""; 225 | }; 226 | /* End PBXVariantGroup section */ 227 | 228 | /* Begin XCBuildConfiguration section */ 229 | E2AAFC4C1D02C00700F85EB1 /* Debug */ = { 230 | isa = XCBuildConfiguration; 231 | buildSettings = { 232 | ALWAYS_SEARCH_USER_PATHS = NO; 233 | CLANG_ANALYZER_NONNULL = YES; 234 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 235 | CLANG_CXX_LIBRARY = "libc++"; 236 | CLANG_ENABLE_MODULES = YES; 237 | CLANG_ENABLE_OBJC_ARC = YES; 238 | CLANG_WARN_BOOL_CONVERSION = YES; 239 | CLANG_WARN_CONSTANT_CONVERSION = YES; 240 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 241 | CLANG_WARN_EMPTY_BODY = YES; 242 | CLANG_WARN_ENUM_CONVERSION = YES; 243 | CLANG_WARN_INT_CONVERSION = YES; 244 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 245 | CLANG_WARN_UNREACHABLE_CODE = YES; 246 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 247 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 248 | COPY_PHASE_STRIP = NO; 249 | DEBUG_INFORMATION_FORMAT = dwarf; 250 | ENABLE_STRICT_OBJC_MSGSEND = YES; 251 | ENABLE_TESTABILITY = YES; 252 | GCC_C_LANGUAGE_STANDARD = gnu99; 253 | GCC_DYNAMIC_NO_PIC = NO; 254 | GCC_NO_COMMON_BLOCKS = YES; 255 | GCC_OPTIMIZATION_LEVEL = 0; 256 | GCC_PREPROCESSOR_DEFINITIONS = ( 257 | "DEBUG=1", 258 | "$(inherited)", 259 | ); 260 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 261 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 262 | GCC_WARN_UNDECLARED_SELECTOR = YES; 263 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 264 | GCC_WARN_UNUSED_FUNCTION = YES; 265 | GCC_WARN_UNUSED_VARIABLE = YES; 266 | IPHONEOS_DEPLOYMENT_TARGET = 9.3; 267 | MTL_ENABLE_DEBUG_INFO = YES; 268 | ONLY_ACTIVE_ARCH = YES; 269 | SDKROOT = iphoneos; 270 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 271 | TARGETED_DEVICE_FAMILY = "1,2"; 272 | }; 273 | name = Debug; 274 | }; 275 | E2AAFC4D1D02C00700F85EB1 /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ALWAYS_SEARCH_USER_PATHS = NO; 279 | CLANG_ANALYZER_NONNULL = YES; 280 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 281 | CLANG_CXX_LIBRARY = "libc++"; 282 | CLANG_ENABLE_MODULES = YES; 283 | CLANG_ENABLE_OBJC_ARC = YES; 284 | CLANG_WARN_BOOL_CONVERSION = YES; 285 | CLANG_WARN_CONSTANT_CONVERSION = YES; 286 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 287 | CLANG_WARN_EMPTY_BODY = YES; 288 | CLANG_WARN_ENUM_CONVERSION = YES; 289 | CLANG_WARN_INT_CONVERSION = YES; 290 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 291 | CLANG_WARN_UNREACHABLE_CODE = YES; 292 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 293 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 294 | COPY_PHASE_STRIP = NO; 295 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 296 | ENABLE_NS_ASSERTIONS = NO; 297 | ENABLE_STRICT_OBJC_MSGSEND = YES; 298 | GCC_C_LANGUAGE_STANDARD = gnu99; 299 | GCC_NO_COMMON_BLOCKS = YES; 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 = 9.3; 307 | MTL_ENABLE_DEBUG_INFO = NO; 308 | SDKROOT = iphoneos; 309 | TARGETED_DEVICE_FAMILY = "1,2"; 310 | VALIDATE_PRODUCT = YES; 311 | }; 312 | name = Release; 313 | }; 314 | E2AAFC4F1D02C00700F85EB1 /* Debug */ = { 315 | isa = XCBuildConfiguration; 316 | baseConfigurationReference = C8C4C2C83CBA2AF09B8C50E4 /* Pods-Example.debug.xcconfig */; 317 | buildSettings = { 318 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 319 | INFOPLIST_FILE = Example/Info.plist; 320 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 321 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 322 | PRODUCT_BUNDLE_IDENTIFIER = me.tom.Example; 323 | PRODUCT_NAME = "$(TARGET_NAME)"; 324 | SWIFT_VERSION = 3.0; 325 | }; 326 | name = Debug; 327 | }; 328 | E2AAFC501D02C00700F85EB1 /* Release */ = { 329 | isa = XCBuildConfiguration; 330 | baseConfigurationReference = B17E902500E1C67590DF71FC /* Pods-Example.release.xcconfig */; 331 | buildSettings = { 332 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 333 | INFOPLIST_FILE = Example/Info.plist; 334 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 335 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 336 | PRODUCT_BUNDLE_IDENTIFIER = me.tom.Example; 337 | PRODUCT_NAME = "$(TARGET_NAME)"; 338 | SWIFT_VERSION = 3.0; 339 | }; 340 | name = Release; 341 | }; 342 | /* End XCBuildConfiguration section */ 343 | 344 | /* Begin XCConfigurationList section */ 345 | E2AAFC371D02C00700F85EB1 /* Build configuration list for PBXProject "Example" */ = { 346 | isa = XCConfigurationList; 347 | buildConfigurations = ( 348 | E2AAFC4C1D02C00700F85EB1 /* Debug */, 349 | E2AAFC4D1D02C00700F85EB1 /* Release */, 350 | ); 351 | defaultConfigurationIsVisible = 0; 352 | defaultConfigurationName = Release; 353 | }; 354 | E2AAFC4E1D02C00700F85EB1 /* Build configuration list for PBXNativeTarget "Example" */ = { 355 | isa = XCConfigurationList; 356 | buildConfigurations = ( 357 | E2AAFC4F1D02C00700F85EB1 /* Debug */, 358 | E2AAFC501D02C00700F85EB1 /* Release */, 359 | ); 360 | defaultConfigurationIsVisible = 0; 361 | defaultConfigurationName = Release; 362 | }; 363 | /* End XCConfigurationList section */ 364 | }; 365 | rootObject = E2AAFC341D02C00700F85EB1 /* Project object */; 366 | } 367 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/Example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Example 4 | // 5 | // Created by TomHuang on 16/6/4. 6 | // Copyright © 2016年 TomHuang. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // 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. 24 | // 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. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // 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. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // 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. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Example/Example/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Example/Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | NSAppTransportSecurity 8 | 9 | NSAllowsArbitraryLoads 10 | 11 | 12 | CFBundleExecutable 13 | $(EXECUTABLE_NAME) 14 | CFBundleIdentifier 15 | $(PRODUCT_BUNDLE_IDENTIFIER) 16 | CFBundleInfoDictionaryVersion 17 | 6.0 18 | CFBundleName 19 | $(PRODUCT_NAME) 20 | CFBundlePackageType 21 | APPL 22 | CFBundleShortVersionString 23 | 1.0 24 | CFBundleSignature 25 | ???? 26 | CFBundleVersion 27 | 1 28 | LSRequiresIPhoneOS 29 | 30 | UILaunchStoryboardName 31 | Main 32 | UIMainStoryboardFile 33 | Main 34 | UIRequiredDeviceCapabilities 35 | 36 | armv7 37 | 38 | UISupportedInterfaceOrientations 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | UISupportedInterfaceOrientations~ipad 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationPortraitUpsideDown 48 | UIInterfaceOrientationLandscapeLeft 49 | UIInterfaceOrientationLandscapeRight 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /Example/Example/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import SwiftImageSlider 3 | 4 | class ViewController: UIViewController { 5 | 6 | @IBAction func showImageSlider(_ sender: AnyObject) { 7 | let imageUrls = [ 8 | "http://img.bimg.126.net/photo/qwLaXLhl3boN0bUPMGRPiA==/5704653352996391616.jpg", 9 | "http://img1.cache.netease.com/catchpic/5/5C/5C02C05BD566B31FDF6F4A0D16E5C260.jpg", 10 | "http://imgsrc.baidu.com/forum/w%3D580/sign=20af00b006087bf47dec57e1c2d2575e/bd291cd162d9f2d36a161b14adec8a136227cc27.jpg", 11 | "http://tw.bid.yimg.com/pimg1/77/8c/p080324724868-item-2640xf1x0490x0395-m.jpg" 12 | ] 13 | let controller = ImageSliderViewController(currentIndex: 0, imageUrls: imageUrls) 14 | present(controller, animated: true, completion: nil) 15 | 16 | } 17 | } 18 | 19 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '8.0' 2 | 3 | use_frameworks! 4 | 5 | target 'Example' do 6 | pod 'SwiftImageSlider', :path => '../' 7 | end 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Tom.Huang 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. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftImageSlider 2 | A simple image slide show library by Swift. 3 | 4 | # Screenshot 5 | 6 | ![SwiftRangeSlider Screenshot](Screenshot.gif) 7 | 8 | # Setup 9 | 10 | #### Install with [CocoaPods](http://cocoapods.org/) 11 | 12 | ```ruby 13 | platform :ios, '8.0' 14 | pod 'SwiftImageSlider', '~> 0.2.1' 15 | ``` 16 | 17 | #### [Example](Example/Example/ViewController.swift) 18 | 19 | # Thanks 20 | 21 | * [Kingfisher](https://github.com/onevcat/Kingfisher) 22 | * [Toast-Swift](https://github.com/scalessec/Toast-Swift) 23 | 24 | # License 25 | 26 | [MIT](LICENSE) -------------------------------------------------------------------------------- /Screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nanjingboy/SwiftImageSlider/3a03d9b4ac8008d8f8f549556f15d2b07ae55488/Screenshot.gif -------------------------------------------------------------------------------- /Source/ImageSliderCell.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Kingfisher 3 | import Toast_Swift 4 | 5 | class ImageSliderCell: UIView, UIScrollViewDelegate { 6 | 7 | var delegate: ImageSliderCellDelegate? 8 | let imageUrl: String 9 | 10 | fileprivate let imageView = UIImageView() 11 | fileprivate let scrollView = UIScrollView() 12 | 13 | override var frame: CGRect { 14 | didSet { 15 | if !frame.equalTo(CGRect.zero) { 16 | scrollView.frame = bounds 17 | resetZoomScale() 18 | drawImage() 19 | } 20 | } 21 | } 22 | 23 | init(imageUrl: String) { 24 | self.imageUrl = imageUrl 25 | super.init(frame: CGRect.zero) 26 | initialize() 27 | } 28 | 29 | required init?(coder aDecoder: NSCoder) { 30 | self.imageUrl = "" 31 | super.init(coder: aDecoder) 32 | initialize() 33 | } 34 | 35 | func initialize() { 36 | imageView.contentMode = UIViewContentMode.scaleAspectFit 37 | 38 | scrollView.clipsToBounds = true 39 | scrollView.delegate = self 40 | scrollView.showsHorizontalScrollIndicator = false 41 | scrollView.showsVerticalScrollIndicator = false 42 | scrollView.decelerationRate /= 2 43 | scrollView.bouncesZoom = true 44 | scrollView.addSubview(imageView) 45 | addSubview(scrollView) 46 | 47 | let doubleTap = UITapGestureRecognizer(target: self, action: #selector(imageSliderCellDoubleTap)) 48 | doubleTap.numberOfTapsRequired = 2 49 | scrollView.addGestureRecognizer(doubleTap) 50 | 51 | let singleTap = UITapGestureRecognizer(target: self, action: #selector(imageSliderCellSingleTap)) 52 | singleTap.numberOfTapsRequired = 1 53 | singleTap.require(toFail: doubleTap) 54 | scrollView.addGestureRecognizer(singleTap) 55 | } 56 | 57 | func imageSliderCellDoubleTap(_ tap: UITapGestureRecognizer) { 58 | let touchPoint = tap.location(in: self) 59 | if (scrollView.zoomScale == scrollView.minimumZoomScale) { 60 | scrollView.zoom(to: CGRect(x: touchPoint.x, y: touchPoint.y, width: 1, height: 1), animated: true) 61 | } else { 62 | scrollView.setZoomScale(scrollView.minimumZoomScale, animated: true) 63 | } 64 | } 65 | 66 | func imageSliderCellSingleTap(_ tap: UITapGestureRecognizer) { 67 | delegate?.imageSliderCellSingleTap(tap) 68 | } 69 | 70 | func viewForZooming(in scrollView: UIScrollView) -> UIView? { 71 | return imageView 72 | } 73 | 74 | func scrollViewDidZoom(_ scrollView: UIScrollView) { 75 | imageView.center = centerOfScrollView(scrollView) 76 | } 77 | 78 | func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) { 79 | UIView.animate(withDuration: 0.25, animations: { 80 | view?.center = self.centerOfScrollView(scrollView) 81 | }) 82 | } 83 | 84 | func loadImage() { 85 | if let _ = imageView.image { 86 | return 87 | } 88 | 89 | makeToastActivity(.center) 90 | scrollView.frame = bounds 91 | resetZoomScale() 92 | imageView.kf.setImage(with: URL(string: imageUrl)!, 93 | placeholder: nil, 94 | options: nil, 95 | progressBlock: nil, 96 | completionHandler: {(image, error, cacheType, imageURL) -> () in 97 | self.hideToastActivity() 98 | if image == nil || error != nil { 99 | var style = ToastStyle() 100 | style.messageAlignment = NSTextAlignment.center 101 | self.makeToast(ImageSliderUtility.localizedString("Failed to load the image"), duration: 2, position: .center, style: style) 102 | } else { 103 | self.drawImage() 104 | } 105 | } 106 | ) 107 | } 108 | 109 | func resetZoomScale() { 110 | scrollView.minimumZoomScale = 1.0 111 | scrollView.maximumZoomScale = 1.0 112 | scrollView.zoomScale = 1.0 113 | } 114 | 115 | func drawImage() { 116 | var scrollViewFrame = scrollView.frame 117 | if imageView.image == nil { 118 | scrollViewFrame.origin = CGPoint.zero 119 | imageView.frame = scrollViewFrame 120 | scrollView.contentSize = imageView.frame.size 121 | resetZoomScale() 122 | } else { 123 | let imageSize = imageView.image!.size 124 | let ratio = scrollViewFrame.size.width / imageSize.width 125 | imageView.frame = CGRect(x: 0, y: 0, width: scrollViewFrame.size.width, height: imageSize.height * ratio) 126 | scrollView.contentSize = imageView.frame.size 127 | imageView.center = centerOfScrollView(scrollView) 128 | scrollView.minimumZoomScale = 1.0 129 | scrollView.maximumZoomScale = scrollViewFrame.height / imageView.frame.size.height 130 | scrollView.zoomScale = 1.0 131 | } 132 | scrollView.contentOffset = CGPoint.zero 133 | } 134 | 135 | func centerOfScrollView(_ scrollView: UIScrollView) -> CGPoint { 136 | var offsetX: CGFloat 137 | if scrollView.bounds.size.width > scrollView.bounds.size.height { 138 | offsetX = (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 139 | } else { 140 | offsetX = 0.0 141 | } 142 | 143 | var offsetY: CGFloat 144 | if scrollView.bounds.size.height > scrollView.contentSize.height { 145 | offsetY = (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 146 | } else { 147 | offsetY = 0.0 148 | } 149 | 150 | return CGPoint(x: scrollView.contentSize.width * 0.5 + offsetX, 151 | y: scrollView.contentSize.height * 0.5 + offsetY) 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Source/ImageSliderCellDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | protocol ImageSliderCellDelegate { 4 | 5 | func imageSliderCellSingleTap(_ tap: UITapGestureRecognizer) 6 | } 7 | -------------------------------------------------------------------------------- /Source/ImageSliderUtility.swift: -------------------------------------------------------------------------------- 1 | class ImageSliderUtility: NSObject { 2 | 3 | static func localizedString(_ key: String) -> String { 4 | if let bundleUrl = Bundle(for: classForCoder()).url(forResource: "SwiftImageSlider", withExtension: "bundle") { 5 | if let bundle = Bundle(url: bundleUrl) { 6 | return bundle.localizedString(forKey: key, value: key, table: "SwiftImageSlider") 7 | } 8 | } 9 | 10 | return key 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Source/ImageSliderView.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | open class ImageSliderView: UIView, UIScrollViewDelegate, ImageSliderCellDelegate { 4 | 5 | fileprivate var currentIndex: Int 6 | fileprivate var sliderCells: [ImageSliderCell] = [] 7 | fileprivate var isUpdatingCellFrames = false 8 | 9 | open var delegate: ImageSliderViewDelegate? 10 | open let scrollView = UIScrollView() 11 | 12 | open override var bounds: CGRect { 13 | didSet { 14 | updateCellFrames() 15 | } 16 | } 17 | 18 | public init(currntIndex: Int, imageUrls: [String]) { 19 | self.currentIndex = currntIndex 20 | super.init(frame: CGRect.zero) 21 | initialize(imageUrls) 22 | } 23 | 24 | public required init?(coder aDecoder: NSCoder) { 25 | self.currentIndex = 0 26 | super.init(coder: aDecoder) 27 | initialize([]) 28 | } 29 | 30 | open func scrollViewDidScroll(_ scrollView: UIScrollView) { 31 | if (isUpdatingCellFrames) { 32 | isUpdatingCellFrames = false 33 | return 34 | } 35 | self.scrollView.contentOffset = CGPoint(x: scrollView.contentOffset.x, y: 0) 36 | let width = self.scrollView.frame.width 37 | let index = Int(floor((self.scrollView.contentOffset.x - width / 2) / width) + 1) 38 | if (currentIndex != index) { 39 | switchImage(index) 40 | } 41 | } 42 | 43 | func initialize(_ imageUrls: [String]) { 44 | clipsToBounds = false 45 | 46 | scrollView.scrollsToTop = false 47 | scrollView.isPagingEnabled = true 48 | scrollView.delegate = self 49 | scrollView.showsVerticalScrollIndicator = false 50 | scrollView.showsHorizontalScrollIndicator = false 51 | scrollView.autoresizesSubviews = false 52 | scrollView.autoresizingMask = UIViewAutoresizing() 53 | scrollView.translatesAutoresizingMaskIntoConstraints = false 54 | 55 | for imageUrl in imageUrls { 56 | let sliderCell = ImageSliderCell(imageUrl: imageUrl) 57 | sliderCell.delegate = self 58 | sliderCells.append(sliderCell) 59 | scrollView.addSubview(sliderCell) 60 | } 61 | 62 | addSubview(scrollView) 63 | } 64 | 65 | func updateCellFrames() { 66 | let pageCount = sliderCells.count 67 | let sliderViewFrame = bounds 68 | 69 | isUpdatingCellFrames = true 70 | scrollView.frame = sliderViewFrame 71 | scrollView.contentSize = CGSize(width: sliderViewFrame.size.width * CGFloat(pageCount), 72 | height: sliderViewFrame.size.height * CGFloat(pageCount)) 73 | 74 | scrollView.contentOffset = CGPoint(x: CGFloat(currentIndex) * sliderViewFrame.size.width, y: 0) 75 | let scrollViewBounds = scrollView.bounds 76 | for index in 0 ..< pageCount { 77 | let sliderCell = sliderCells[index] 78 | sliderCell.frame = CGRect(x: scrollViewBounds.width * CGFloat(index), 79 | y: scrollViewBounds.minY, 80 | width: scrollViewBounds.width, 81 | height: scrollViewBounds.height) 82 | } 83 | 84 | switchImage(currentIndex) 85 | } 86 | 87 | func switchImage(_ index: Int) { 88 | let sliderCell = sliderCells[index] 89 | sliderCell.loadImage() 90 | currentIndex = index 91 | delegate?.imageSliderViewImageSwitch(index, count: sliderCells.count, imageUrl: sliderCell.imageUrl) 92 | } 93 | 94 | func imageSliderCellSingleTap(_ tap: UITapGestureRecognizer) { 95 | delegate?.imageSliderViewSingleTap(tap) 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /Source/ImageSliderViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | open class ImageSliderViewController: UIViewController, ImageSliderViewDelegate { 4 | 5 | open let imageSliderView: ImageSliderView 6 | open let pageControl = UIPageControl() 7 | 8 | public init(currentIndex: Int, imageUrls: [String]) { 9 | imageSliderView = ImageSliderView(currntIndex: currentIndex, imageUrls: imageUrls) 10 | super.init(nibName: nil, bundle: nil) 11 | imageSliderViewImageSwitch(currentIndex, count: imageUrls.count, imageUrl: imageUrls[currentIndex]) 12 | } 13 | 14 | public required init?(coder aDecoder: NSCoder) { 15 | imageSliderView = ImageSliderView(currntIndex: 0, imageUrls: []) 16 | super.init(coder: aDecoder) 17 | imageSliderViewImageSwitch(0, count: 0, imageUrl: nil) 18 | } 19 | 20 | open override func viewDidLoad() { 21 | super.viewDidLoad() 22 | view.clipsToBounds = true 23 | view.backgroundColor = UIColor.black 24 | 25 | imageSliderView.delegate = self 26 | imageSliderView.translatesAutoresizingMaskIntoConstraints = false 27 | view.addSubview(imageSliderView) 28 | setImageSliderViewConstraints() 29 | 30 | pageControl.translatesAutoresizingMaskIntoConstraints = false 31 | 32 | view.addSubview(pageControl) 33 | setDisplayLabelConstraints() 34 | } 35 | 36 | open func setImageSliderViewConstraints() { 37 | let imageSliderViewHConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[imageSliderView]-0-|", 38 | options: [], 39 | metrics: nil, 40 | views: ["imageSliderView": imageSliderView]) 41 | view.addConstraints(imageSliderViewHConstraints) 42 | 43 | let imageSliderViewVConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[imageSliderView]-0-|", 44 | options: [], 45 | metrics: nil, 46 | views: ["imageSliderView": imageSliderView]) 47 | view.addConstraints(imageSliderViewVConstraints) 48 | } 49 | 50 | open func setDisplayLabelConstraints() { 51 | let constraint = NSLayoutConstraint(item: pageControl, 52 | attribute: NSLayoutAttribute.centerX, 53 | relatedBy: NSLayoutRelation.equal, 54 | toItem: view, 55 | attribute: NSLayoutAttribute.centerX, 56 | multiplier: 1.0, 57 | constant: 0.0) 58 | view.addConstraint(constraint) 59 | 60 | let displayLabelVConstraints = NSLayoutConstraint.constraints(withVisualFormat: "V:[pageControl]-20-|", 61 | options: [], 62 | metrics: nil, 63 | views: ["pageControl": pageControl]) 64 | view.addConstraints(displayLabelVConstraints) 65 | } 66 | 67 | open func imageSliderViewSingleTap(_ tap: UITapGestureRecognizer) { 68 | dismiss(animated: true, completion: nil) 69 | } 70 | 71 | open func imageSliderViewImageSwitch(_ index: Int, count: Int, imageUrl: String?) { 72 | pageControl.numberOfPages = count 73 | pageControl.currentPage = index 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Source/ImageSliderViewDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public protocol ImageSliderViewDelegate { 4 | 5 | func imageSliderViewSingleTap(_ tap: UITapGestureRecognizer) 6 | 7 | func imageSliderViewImageSwitch(_ index: Int, count: Int, imageUrl: String?) 8 | } 9 | -------------------------------------------------------------------------------- /SwiftImageSlider.bundle/en.lproj/SwiftImageSlider.strings: -------------------------------------------------------------------------------- 1 | "Failed to load the image" = "Failed to load the image"; -------------------------------------------------------------------------------- /SwiftImageSlider.bundle/zh-Hans.lproj/SwiftImageSlider.strings: -------------------------------------------------------------------------------- 1 | "Failed to load the image" = "图片加载失败"; -------------------------------------------------------------------------------- /SwiftImageSlider.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'SwiftImageSlider' 3 | s.version = '0.2.1' 4 | s.summary = 'A simple image slide show library by Swift.' 5 | s.homepage = 'https://github.com/nanjingboy/SwiftImageSlider' 6 | s.license = { :type => 'MIT', :file => 'LICENSE' } 7 | s.author = { 'Tom.Huang' => 'hzlhu.dargon@gmail.com' } 8 | s.source = { :git => 'https://github.com/nanjingboy/SwiftImageSlider.git', :tag => s.version.to_s } 9 | s.ios.deployment_target = '8.0' 10 | s.source_files = "Source/*.swift" 11 | s.resources = 'SwiftImageSlider.bundle' 12 | s.dependency "Kingfisher", "~> 3.2" 13 | s.dependency "Toast-Swift", "~> 2.0" 14 | end 15 | --------------------------------------------------------------------------------