├── .DS_Store ├── .gitignore ├── ICETutorial.xcodeproj └── project.pbxproj ├── ICETutorial ├── AppDelegate.swift ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── Info.plist └── Libraries │ ├── ICETutorialController.swift │ └── ICETutorialPage.swift ├── ICETutorialTests ├── ICETutorialTests.swift └── Info.plist ├── README.md └── Resources ├── Default-568h@2x.png ├── Default.png ├── Default@2x.png ├── background-gradient.png ├── background-gradient@2x.png ├── button-background.png ├── button-background@2x.png ├── tutorial_background_00@2x.jpg ├── tutorial_background_01@2x.jpg ├── tutorial_background_02@2x.jpg ├── tutorial_background_03@2x.jpg └── tutorial_background_04@2x.jpg /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | *.xcworkspacedata 3 | 4 | *.xcuserstate 5 | 6 | *.xcsettings 7 | 8 | *.xcbkptlist 9 | 10 | *.xcscheme 11 | 12 | ICETutorial.xcodeproj/xcuserdata/patrick.trillsam.xcuserdatad/xcschemes/xcschememanagement.plist 13 | 14 | ICETutorial.xcodeproj/xcuserdata/patrick.trillsam.xcuserdatad/xcschemes/ICETutorialSwift.xcscheme 15 | 16 | ICETutorial.xcodeproj/xcuserdata/patrick.trillsam.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist 17 | 18 | ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/patrick.trillsam.xcuserdatad/WorkspaceSettings.xcsettings 19 | 20 | ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/patrick.trillsam.xcuserdatad/UserInterfaceState.xcuserstate 21 | 22 | ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata 23 | -------------------------------------------------------------------------------- /ICETutorial.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 55A1D55F193FEFCC00994874 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A1D55E193FEFCC00994874 /* AppDelegate.swift */; }; 11 | 55A1D561193FEFCC00994874 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D560193FEFCC00994874 /* Images.xcassets */; }; 12 | 55A1D56D193FEFCC00994874 /* ICETutorialTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A1D56C193FEFCC00994874 /* ICETutorialTests.swift */; }; 13 | 55A1D583193FF01600994874 /* background-gradient.png in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D577193FF01600994874 /* background-gradient.png */; }; 14 | 55A1D584193FF01600994874 /* background-gradient@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D578193FF01600994874 /* background-gradient@2x.png */; }; 15 | 55A1D585193FF01600994874 /* button-background.png in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D579193FF01600994874 /* button-background.png */; }; 16 | 55A1D586193FF01600994874 /* button-background@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D57A193FF01600994874 /* button-background@2x.png */; }; 17 | 55A1D587193FF01600994874 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D57B193FF01600994874 /* Default-568h@2x.png */; }; 18 | 55A1D588193FF01600994874 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D57C193FF01600994874 /* Default.png */; }; 19 | 55A1D589193FF01600994874 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D57D193FF01600994874 /* Default@2x.png */; }; 20 | 55A1D58A193FF01600994874 /* tutorial_background_00@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D57E193FF01600994874 /* tutorial_background_00@2x.jpg */; }; 21 | 55A1D58B193FF01600994874 /* tutorial_background_01@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D57F193FF01600994874 /* tutorial_background_01@2x.jpg */; }; 22 | 55A1D58C193FF01600994874 /* tutorial_background_02@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D580193FF01600994874 /* tutorial_background_02@2x.jpg */; }; 23 | 55A1D58D193FF01600994874 /* tutorial_background_03@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D581193FF01600994874 /* tutorial_background_03@2x.jpg */; }; 24 | 55A1D58E193FF01600994874 /* tutorial_background_04@2x.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 55A1D582193FF01600994874 /* tutorial_background_04@2x.jpg */; }; 25 | 55A1D597193FF05400994874 /* ICETutorialPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A1D596193FF05400994874 /* ICETutorialPage.swift */; }; 26 | 55A1D5F3193FFA9300994874 /* ICETutorialController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 55A1D5F2193FFA9300994874 /* ICETutorialController.swift */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXContainerItemProxy section */ 30 | 55A1D567193FEFCC00994874 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 55A1D551193FEFCC00994874 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 55A1D558193FEFCC00994874; 35 | remoteInfo = ICETutorialSwift; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 55A1D559193FEFCC00994874 /* ICETutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ICETutorial.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 55A1D55D193FEFCC00994874 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 42 | 55A1D55E193FEFCC00994874 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 43 | 55A1D560193FEFCC00994874 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 44 | 55A1D566193FEFCC00994874 /* ICETutorialTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ICETutorialTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 45 | 55A1D56B193FEFCC00994874 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 46 | 55A1D56C193FEFCC00994874 /* ICETutorialTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ICETutorialTests.swift; sourceTree = ""; }; 47 | 55A1D577193FF01600994874 /* background-gradient.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background-gradient.png"; sourceTree = ""; }; 48 | 55A1D578193FF01600994874 /* background-gradient@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "background-gradient@2x.png"; sourceTree = ""; }; 49 | 55A1D579193FF01600994874 /* button-background.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "button-background.png"; sourceTree = ""; }; 50 | 55A1D57A193FF01600994874 /* button-background@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "button-background@2x.png"; sourceTree = ""; }; 51 | 55A1D57B193FF01600994874 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 52 | 55A1D57C193FF01600994874 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 53 | 55A1D57D193FF01600994874 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 54 | 55A1D57E193FF01600994874 /* tutorial_background_00@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "tutorial_background_00@2x.jpg"; sourceTree = ""; }; 55 | 55A1D57F193FF01600994874 /* tutorial_background_01@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "tutorial_background_01@2x.jpg"; sourceTree = ""; }; 56 | 55A1D580193FF01600994874 /* tutorial_background_02@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "tutorial_background_02@2x.jpg"; sourceTree = ""; }; 57 | 55A1D581193FF01600994874 /* tutorial_background_03@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "tutorial_background_03@2x.jpg"; sourceTree = ""; }; 58 | 55A1D582193FF01600994874 /* tutorial_background_04@2x.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "tutorial_background_04@2x.jpg"; sourceTree = ""; }; 59 | 55A1D596193FF05400994874 /* ICETutorialPage.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICETutorialPage.swift; sourceTree = ""; }; 60 | 55A1D5F2193FFA9300994874 /* ICETutorialController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ICETutorialController.swift; sourceTree = ""; }; 61 | /* End PBXFileReference section */ 62 | 63 | /* Begin PBXFrameworksBuildPhase section */ 64 | 55A1D556193FEFCC00994874 /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | 55A1D563193FEFCC00994874 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | /* End PBXFrameworksBuildPhase section */ 79 | 80 | /* Begin PBXGroup section */ 81 | 55A1D550193FEFCC00994874 = { 82 | isa = PBXGroup; 83 | children = ( 84 | 55A1D58F193FF02000994874 /* Libraries */, 85 | 55A1D576193FF01600994874 /* Resources */, 86 | 55A1D55B193FEFCC00994874 /* ICETutorial */, 87 | 55A1D569193FEFCC00994874 /* ICETutorialTests */, 88 | 55A1D55A193FEFCC00994874 /* Products */, 89 | ); 90 | sourceTree = ""; 91 | }; 92 | 55A1D55A193FEFCC00994874 /* Products */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 55A1D559193FEFCC00994874 /* ICETutorial.app */, 96 | 55A1D566193FEFCC00994874 /* ICETutorialTests.xctest */, 97 | ); 98 | name = Products; 99 | sourceTree = ""; 100 | }; 101 | 55A1D55B193FEFCC00994874 /* ICETutorial */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 55A1D55E193FEFCC00994874 /* AppDelegate.swift */, 105 | 55A1D560193FEFCC00994874 /* Images.xcassets */, 106 | 55A1D55C193FEFCC00994874 /* Supporting Files */, 107 | ); 108 | path = ICETutorial; 109 | sourceTree = ""; 110 | }; 111 | 55A1D55C193FEFCC00994874 /* Supporting Files */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | 55A1D55D193FEFCC00994874 /* Info.plist */, 115 | ); 116 | name = "Supporting Files"; 117 | sourceTree = ""; 118 | }; 119 | 55A1D569193FEFCC00994874 /* ICETutorialTests */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 55A1D56C193FEFCC00994874 /* ICETutorialTests.swift */, 123 | 55A1D56A193FEFCC00994874 /* Supporting Files */, 124 | ); 125 | path = ICETutorialTests; 126 | sourceTree = ""; 127 | }; 128 | 55A1D56A193FEFCC00994874 /* Supporting Files */ = { 129 | isa = PBXGroup; 130 | children = ( 131 | 55A1D56B193FEFCC00994874 /* Info.plist */, 132 | ); 133 | name = "Supporting Files"; 134 | sourceTree = ""; 135 | }; 136 | 55A1D576193FF01600994874 /* Resources */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 55A1D577193FF01600994874 /* background-gradient.png */, 140 | 55A1D578193FF01600994874 /* background-gradient@2x.png */, 141 | 55A1D579193FF01600994874 /* button-background.png */, 142 | 55A1D57A193FF01600994874 /* button-background@2x.png */, 143 | 55A1D57B193FF01600994874 /* Default-568h@2x.png */, 144 | 55A1D57C193FF01600994874 /* Default.png */, 145 | 55A1D57D193FF01600994874 /* Default@2x.png */, 146 | 55A1D57E193FF01600994874 /* tutorial_background_00@2x.jpg */, 147 | 55A1D57F193FF01600994874 /* tutorial_background_01@2x.jpg */, 148 | 55A1D580193FF01600994874 /* tutorial_background_02@2x.jpg */, 149 | 55A1D581193FF01600994874 /* tutorial_background_03@2x.jpg */, 150 | 55A1D582193FF01600994874 /* tutorial_background_04@2x.jpg */, 151 | ); 152 | path = Resources; 153 | sourceTree = ""; 154 | }; 155 | 55A1D58F193FF02000994874 /* Libraries */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 55A1D596193FF05400994874 /* ICETutorialPage.swift */, 159 | 55A1D5F2193FFA9300994874 /* ICETutorialController.swift */, 160 | ); 161 | name = Libraries; 162 | path = ICETutorial/Libraries; 163 | sourceTree = ""; 164 | }; 165 | /* End PBXGroup section */ 166 | 167 | /* Begin PBXNativeTarget section */ 168 | 55A1D558193FEFCC00994874 /* ICETutorial */ = { 169 | isa = PBXNativeTarget; 170 | buildConfigurationList = 55A1D570193FEFCC00994874 /* Build configuration list for PBXNativeTarget "ICETutorial" */; 171 | buildPhases = ( 172 | 55A1D555193FEFCC00994874 /* Sources */, 173 | 55A1D556193FEFCC00994874 /* Frameworks */, 174 | 55A1D557193FEFCC00994874 /* Resources */, 175 | ); 176 | buildRules = ( 177 | ); 178 | dependencies = ( 179 | ); 180 | name = ICETutorial; 181 | productName = ICETutorialSwift; 182 | productReference = 55A1D559193FEFCC00994874 /* ICETutorial.app */; 183 | productType = "com.apple.product-type.application"; 184 | }; 185 | 55A1D565193FEFCC00994874 /* ICETutorialTests */ = { 186 | isa = PBXNativeTarget; 187 | buildConfigurationList = 55A1D573193FEFCC00994874 /* Build configuration list for PBXNativeTarget "ICETutorialTests" */; 188 | buildPhases = ( 189 | 55A1D562193FEFCC00994874 /* Sources */, 190 | 55A1D563193FEFCC00994874 /* Frameworks */, 191 | 55A1D564193FEFCC00994874 /* Resources */, 192 | ); 193 | buildRules = ( 194 | ); 195 | dependencies = ( 196 | 55A1D568193FEFCC00994874 /* PBXTargetDependency */, 197 | ); 198 | name = ICETutorialTests; 199 | productName = ICETutorialSwiftTests; 200 | productReference = 55A1D566193FEFCC00994874 /* ICETutorialTests.xctest */; 201 | productType = "com.apple.product-type.bundle.unit-test"; 202 | }; 203 | /* End PBXNativeTarget section */ 204 | 205 | /* Begin PBXProject section */ 206 | 55A1D551193FEFCC00994874 /* Project object */ = { 207 | isa = PBXProject; 208 | attributes = { 209 | LastUpgradeCheck = 0600; 210 | ORGANIZATIONNAME = "Patrick Trillsam"; 211 | TargetAttributes = { 212 | 55A1D558193FEFCC00994874 = { 213 | CreatedOnToolsVersion = 6.0; 214 | }; 215 | 55A1D565193FEFCC00994874 = { 216 | CreatedOnToolsVersion = 6.0; 217 | TestTargetID = 55A1D558193FEFCC00994874; 218 | }; 219 | }; 220 | }; 221 | buildConfigurationList = 55A1D554193FEFCC00994874 /* Build configuration list for PBXProject "ICETutorial" */; 222 | compatibilityVersion = "Xcode 3.2"; 223 | developmentRegion = English; 224 | hasScannedForEncodings = 0; 225 | knownRegions = ( 226 | en, 227 | ); 228 | mainGroup = 55A1D550193FEFCC00994874; 229 | productRefGroup = 55A1D55A193FEFCC00994874 /* Products */; 230 | projectDirPath = ""; 231 | projectRoot = ""; 232 | targets = ( 233 | 55A1D558193FEFCC00994874 /* ICETutorial */, 234 | 55A1D565193FEFCC00994874 /* ICETutorialTests */, 235 | ); 236 | }; 237 | /* End PBXProject section */ 238 | 239 | /* Begin PBXResourcesBuildPhase section */ 240 | 55A1D557193FEFCC00994874 /* Resources */ = { 241 | isa = PBXResourcesBuildPhase; 242 | buildActionMask = 2147483647; 243 | files = ( 244 | 55A1D589193FF01600994874 /* Default@2x.png in Resources */, 245 | 55A1D58C193FF01600994874 /* tutorial_background_02@2x.jpg in Resources */, 246 | 55A1D58B193FF01600994874 /* tutorial_background_01@2x.jpg in Resources */, 247 | 55A1D561193FEFCC00994874 /* Images.xcassets in Resources */, 248 | 55A1D586193FF01600994874 /* button-background@2x.png in Resources */, 249 | 55A1D58A193FF01600994874 /* tutorial_background_00@2x.jpg in Resources */, 250 | 55A1D58E193FF01600994874 /* tutorial_background_04@2x.jpg in Resources */, 251 | 55A1D585193FF01600994874 /* button-background.png in Resources */, 252 | 55A1D584193FF01600994874 /* background-gradient@2x.png in Resources */, 253 | 55A1D588193FF01600994874 /* Default.png in Resources */, 254 | 55A1D583193FF01600994874 /* background-gradient.png in Resources */, 255 | 55A1D587193FF01600994874 /* Default-568h@2x.png in Resources */, 256 | 55A1D58D193FF01600994874 /* tutorial_background_03@2x.jpg in Resources */, 257 | ); 258 | runOnlyForDeploymentPostprocessing = 0; 259 | }; 260 | 55A1D564193FEFCC00994874 /* Resources */ = { 261 | isa = PBXResourcesBuildPhase; 262 | buildActionMask = 2147483647; 263 | files = ( 264 | ); 265 | runOnlyForDeploymentPostprocessing = 0; 266 | }; 267 | /* End PBXResourcesBuildPhase section */ 268 | 269 | /* Begin PBXSourcesBuildPhase section */ 270 | 55A1D555193FEFCC00994874 /* Sources */ = { 271 | isa = PBXSourcesBuildPhase; 272 | buildActionMask = 2147483647; 273 | files = ( 274 | 55A1D55F193FEFCC00994874 /* AppDelegate.swift in Sources */, 275 | 55A1D5F3193FFA9300994874 /* ICETutorialController.swift in Sources */, 276 | 55A1D597193FF05400994874 /* ICETutorialPage.swift in Sources */, 277 | ); 278 | runOnlyForDeploymentPostprocessing = 0; 279 | }; 280 | 55A1D562193FEFCC00994874 /* Sources */ = { 281 | isa = PBXSourcesBuildPhase; 282 | buildActionMask = 2147483647; 283 | files = ( 284 | 55A1D56D193FEFCC00994874 /* ICETutorialTests.swift in Sources */, 285 | ); 286 | runOnlyForDeploymentPostprocessing = 0; 287 | }; 288 | /* End PBXSourcesBuildPhase section */ 289 | 290 | /* Begin PBXTargetDependency section */ 291 | 55A1D568193FEFCC00994874 /* PBXTargetDependency */ = { 292 | isa = PBXTargetDependency; 293 | target = 55A1D558193FEFCC00994874 /* ICETutorial */; 294 | targetProxy = 55A1D567193FEFCC00994874 /* PBXContainerItemProxy */; 295 | }; 296 | /* End PBXTargetDependency section */ 297 | 298 | /* Begin XCBuildConfiguration section */ 299 | 55A1D56E193FEFCC00994874 /* Debug */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | ALWAYS_SEARCH_USER_PATHS = NO; 303 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 304 | CLANG_CXX_LIBRARY = "libc++"; 305 | CLANG_ENABLE_MODULES = YES; 306 | CLANG_ENABLE_OBJC_ARC = YES; 307 | CLANG_WARN_BOOL_CONVERSION = YES; 308 | CLANG_WARN_CONSTANT_CONVERSION = YES; 309 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 310 | CLANG_WARN_EMPTY_BODY = YES; 311 | CLANG_WARN_ENUM_CONVERSION = YES; 312 | CLANG_WARN_INT_CONVERSION = YES; 313 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 314 | CLANG_WARN_UNREACHABLE_CODE = YES; 315 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 316 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 317 | COPY_PHASE_STRIP = NO; 318 | ENABLE_STRICT_OBJC_MSGSEND = YES; 319 | GCC_C_LANGUAGE_STANDARD = gnu99; 320 | GCC_DYNAMIC_NO_PIC = NO; 321 | GCC_OPTIMIZATION_LEVEL = 0; 322 | GCC_PREPROCESSOR_DEFINITIONS = ( 323 | "DEBUG=1", 324 | "$(inherited)", 325 | ); 326 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 327 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 328 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 329 | GCC_WARN_UNDECLARED_SELECTOR = YES; 330 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 331 | GCC_WARN_UNUSED_FUNCTION = YES; 332 | GCC_WARN_UNUSED_VARIABLE = YES; 333 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 334 | METAL_ENABLE_DEBUG_INFO = YES; 335 | ONLY_ACTIVE_ARCH = YES; 336 | SDKROOT = iphoneos; 337 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 338 | TARGETED_DEVICE_FAMILY = "1,2"; 339 | }; 340 | name = Debug; 341 | }; 342 | 55A1D56F193FEFCC00994874 /* Release */ = { 343 | isa = XCBuildConfiguration; 344 | buildSettings = { 345 | ALWAYS_SEARCH_USER_PATHS = NO; 346 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 347 | CLANG_CXX_LIBRARY = "libc++"; 348 | CLANG_ENABLE_MODULES = YES; 349 | CLANG_ENABLE_OBJC_ARC = YES; 350 | CLANG_WARN_BOOL_CONVERSION = YES; 351 | CLANG_WARN_CONSTANT_CONVERSION = YES; 352 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 353 | CLANG_WARN_EMPTY_BODY = YES; 354 | CLANG_WARN_ENUM_CONVERSION = YES; 355 | CLANG_WARN_INT_CONVERSION = YES; 356 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 357 | CLANG_WARN_UNREACHABLE_CODE = YES; 358 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 359 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 360 | COPY_PHASE_STRIP = YES; 361 | ENABLE_NS_ASSERTIONS = NO; 362 | ENABLE_STRICT_OBJC_MSGSEND = YES; 363 | GCC_C_LANGUAGE_STANDARD = gnu99; 364 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 365 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 366 | GCC_WARN_UNDECLARED_SELECTOR = YES; 367 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 368 | GCC_WARN_UNUSED_FUNCTION = YES; 369 | GCC_WARN_UNUSED_VARIABLE = YES; 370 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 371 | METAL_ENABLE_DEBUG_INFO = NO; 372 | SDKROOT = iphoneos; 373 | TARGETED_DEVICE_FAMILY = "1,2"; 374 | VALIDATE_PRODUCT = YES; 375 | }; 376 | name = Release; 377 | }; 378 | 55A1D571193FEFCC00994874 /* Debug */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 382 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 383 | INFOPLIST_FILE = ICETutorial/Info.plist; 384 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 385 | PRODUCT_NAME = ICETutorial; 386 | }; 387 | name = Debug; 388 | }; 389 | 55A1D572193FEFCC00994874 /* Release */ = { 390 | isa = XCBuildConfiguration; 391 | buildSettings = { 392 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 393 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 394 | INFOPLIST_FILE = ICETutorial/Info.plist; 395 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 396 | PRODUCT_NAME = ICETutorial; 397 | }; 398 | name = Release; 399 | }; 400 | 55A1D574193FEFCC00994874 /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ICETutorialSwift.app/ICETutorialSwift"; 404 | FRAMEWORK_SEARCH_PATHS = ( 405 | "$(SDKROOT)/Developer/Library/Frameworks", 406 | "$(inherited)", 407 | ); 408 | GCC_PREPROCESSOR_DEFINITIONS = ( 409 | "DEBUG=1", 410 | "$(inherited)", 411 | ); 412 | INFOPLIST_FILE = ICETutorialSwiftTests/Info.plist; 413 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 414 | METAL_ENABLE_DEBUG_INFO = YES; 415 | PRODUCT_NAME = ICETutorialTests; 416 | TEST_HOST = "$(BUNDLE_LOADER)"; 417 | }; 418 | name = Debug; 419 | }; 420 | 55A1D575193FEFCC00994874 /* Release */ = { 421 | isa = XCBuildConfiguration; 422 | buildSettings = { 423 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/ICETutorialSwift.app/ICETutorialSwift"; 424 | FRAMEWORK_SEARCH_PATHS = ( 425 | "$(SDKROOT)/Developer/Library/Frameworks", 426 | "$(inherited)", 427 | ); 428 | INFOPLIST_FILE = ICETutorialSwiftTests/Info.plist; 429 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 430 | METAL_ENABLE_DEBUG_INFO = NO; 431 | PRODUCT_NAME = ICETutorialTests; 432 | TEST_HOST = "$(BUNDLE_LOADER)"; 433 | }; 434 | name = Release; 435 | }; 436 | /* End XCBuildConfiguration section */ 437 | 438 | /* Begin XCConfigurationList section */ 439 | 55A1D554193FEFCC00994874 /* Build configuration list for PBXProject "ICETutorial" */ = { 440 | isa = XCConfigurationList; 441 | buildConfigurations = ( 442 | 55A1D56E193FEFCC00994874 /* Debug */, 443 | 55A1D56F193FEFCC00994874 /* Release */, 444 | ); 445 | defaultConfigurationIsVisible = 0; 446 | defaultConfigurationName = Release; 447 | }; 448 | 55A1D570193FEFCC00994874 /* Build configuration list for PBXNativeTarget "ICETutorial" */ = { 449 | isa = XCConfigurationList; 450 | buildConfigurations = ( 451 | 55A1D571193FEFCC00994874 /* Debug */, 452 | 55A1D572193FEFCC00994874 /* Release */, 453 | ); 454 | defaultConfigurationIsVisible = 0; 455 | defaultConfigurationName = Release; 456 | }; 457 | 55A1D573193FEFCC00994874 /* Build configuration list for PBXNativeTarget "ICETutorialTests" */ = { 458 | isa = XCConfigurationList; 459 | buildConfigurations = ( 460 | 55A1D574193FEFCC00994874 /* Debug */, 461 | 55A1D575193FEFCC00994874 /* Release */, 462 | ); 463 | defaultConfigurationIsVisible = 0; 464 | defaultConfigurationName = Release; 465 | }; 466 | /* End XCConfigurationList section */ 467 | }; 468 | rootObject = 55A1D551193FEFCC00994874 /* Project object */; 469 | } 470 | -------------------------------------------------------------------------------- /ICETutorial/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 5/06/2014. 6 | // Copyright (c) 2014 Patrick Trillsam. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool { 17 | self.window = UIWindow(frame: UIScreen.mainScreen().bounds) 18 | // Override point for customization after application launch. 19 | self.window!.backgroundColor = UIColor.whiteColor() 20 | 21 | // Init the pages texts, and pictures. 22 | var layer1: ICETutorialPage = ICETutorialPage(title: "Picture 1", subTitle: "Champs-Elysées by night", pictureName: "tutorial_background_00@2x.jpg", duration: 3.0) 23 | var layer2: ICETutorialPage = ICETutorialPage(title: "Picture 2", subTitle: "The Eiffel Tower with\n cloudy weather", pictureName: "tutorial_background_01@2x.jpg", duration: 3.0) 24 | var layer3: ICETutorialPage = ICETutorialPage(title: "Picture 3", subTitle: "An other famous street of Paris", pictureName: "tutorial_background_02@2x.jpg", duration: 3.0) 25 | var layer4: ICETutorialPage = ICETutorialPage(title: "Picture 4", subTitle: "The Eiffel Tower with a better weather", pictureName: "tutorial_background_03@2x.jpg", duration: 3.0) 26 | var layer5: ICETutorialPage = ICETutorialPage(title: "Picture 5", subTitle: "The Louvre's Museum Pyramide", pictureName: "tutorial_background_04@2x.jpg", duration: 3.0) 27 | 28 | // Set the common style for SubTitles and Description (can be overrided on each page). 29 | var titleStyle: ICETutorialLabelStyle = ICETutorialLabelStyle() 30 | titleStyle.font = UIFont(name: "Helvetica-Bold", size: 17.0) 31 | titleStyle.color = UIColor.whiteColor() 32 | titleStyle.linesNumber = 1 33 | titleStyle.offsset = 180 34 | 35 | var subStyle: ICETutorialLabelStyle = ICETutorialLabelStyle() 36 | subStyle.font = UIFont(name: "Helvetica", size: 15.0) 37 | subStyle.color = UIColor.whiteColor() 38 | subStyle.linesNumber = 1 39 | subStyle.offsset = 150 40 | 41 | 42 | var listPages: ICETutorialPage[] = [layer1, layer2, layer3, layer4, layer5] 43 | 44 | var controller: ICETutorialController = ICETutorialController(pages: listPages) 45 | controller.commonPageTitleStyle = titleStyle 46 | controller.commonPageSubTitleStyle = subStyle 47 | controller.startScrolling() 48 | 49 | self.window!.rootViewController = controller 50 | self.window!.makeKeyAndVisible() 51 | return true 52 | } 53 | 54 | func applicationWillResignActive(application: UIApplication) { 55 | // 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. 56 | // 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. 57 | } 58 | 59 | func applicationDidEnterBackground(application: UIApplication) { 60 | // 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. 61 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 62 | } 63 | 64 | func applicationWillEnterForeground(application: UIApplication) { 65 | // 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. 66 | } 67 | 68 | func applicationDidBecomeActive(application: UIApplication) { 69 | // 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. 70 | } 71 | 72 | func applicationWillTerminate(application: UIApplication) { 73 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 74 | } 75 | 76 | 77 | } 78 | 79 | -------------------------------------------------------------------------------- /ICETutorial/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" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "29x29", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "29x29", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "40x40", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "40x40", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "76x76", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "76x76", 46 | "scale" : "2x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } -------------------------------------------------------------------------------- /ICETutorial/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "orientation" : "portrait", 20 | "idiom" : "ipad", 21 | "extent" : "full-screen", 22 | "minimum-system-version" : "7.0", 23 | "scale" : "1x" 24 | }, 25 | { 26 | "orientation" : "landscape", 27 | "idiom" : "ipad", 28 | "extent" : "full-screen", 29 | "minimum-system-version" : "7.0", 30 | "scale" : "1x" 31 | }, 32 | { 33 | "orientation" : "portrait", 34 | "idiom" : "ipad", 35 | "extent" : "full-screen", 36 | "minimum-system-version" : "7.0", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "orientation" : "landscape", 41 | "idiom" : "ipad", 42 | "extent" : "full-screen", 43 | "minimum-system-version" : "7.0", 44 | "scale" : "2x" 45 | } 46 | ], 47 | "info" : { 48 | "version" : 1, 49 | "author" : "xcode" 50 | } 51 | } -------------------------------------------------------------------------------- /ICETutorial/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | Patrick-Trillsam.${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 | UIRequiredDeviceCapabilities 26 | 27 | armv7 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ICETutorial/Libraries/ICETutorialController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialController.swift 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 5/06/2014. 6 | // Copyright (c) 2014 Patrick Trillsam. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | enum ScrollingState : Int { 13 | case Auto 14 | case Manual 15 | case Looping 16 | } 17 | 18 | class ICETutorialController : UIViewController, UIScrollViewDelegate { 19 | 20 | var frontLayerView: UIImageView! 21 | var backLayerView: UIImageView! 22 | var scrollView: UIScrollView! 23 | var pageControl: UIPageControl! 24 | var leftButton: UIButton! 25 | var rightButton: UIButton! 26 | 27 | var overlayLogo: UILabel! 28 | 29 | var currentPageIndex: NSInteger! 30 | var nextPageIndex: NSInteger? 31 | var currentState: ScrollingState? 32 | var windowSize: CGSize? 33 | var pages: ICETutorialPage[]! 34 | var autoScrollEnabled: Bool! 35 | var commonPageTitleStyle: ICETutorialLabelStyle! 36 | var commonPageSubTitleStyle: ICETutorialLabelStyle! 37 | 38 | init(pages: ICETutorialPage[]) { 39 | super.init(nibName: nil, bundle: nil) 40 | 41 | self.autoScrollEnabled = true 42 | self.currentPageIndex = 0 43 | // Auto-scrollDuration 44 | self.pages = pages 45 | 46 | self.frontLayerView = UIImageView() 47 | self.backLayerView = UIImageView() 48 | self.scrollView = UIScrollView() 49 | 50 | self.overlayLogo = UILabel() 51 | self.pageControl = UIPageControl() 52 | self.leftButton = UIButton() 53 | self.rightButton = UIButton() 54 | } 55 | 56 | override func viewDidLoad() { 57 | super.viewDidLoad() 58 | self.view!.backgroundColor = UIColor.blackColor() 59 | 60 | self.setupView() 61 | 62 | // Overlays. 63 | self.setOverlayTexts() 64 | self.setOverlayTitle() 65 | 66 | // Preset the origin state. 67 | self.setOriginLayersState() 68 | } 69 | 70 | func setupView() { 71 | self.frontLayerView!.frame = self.view.bounds 72 | self.backLayerView!.frame = self.view.bounds 73 | 74 | // Decoration. 75 | var gradientView = UIImageView(frame: CGRectMake(0, 368, 320, 200)) 76 | gradientView.image = UIImage(named: "background-gradient.png") 77 | 78 | // Title. 79 | self.overlayLogo!.frame = CGRectMake(84, 116, 212, 50) 80 | self.overlayLogo!.textColor = UIColor.whiteColor() 81 | self.overlayLogo!.font = UIFont(name: "Helvetica-Bold", size: 32.0) 82 | 83 | // ScrollView configuration. 84 | self.scrollView!.frame = self.view.bounds 85 | self.scrollView!.delegate = self 86 | self.scrollView!.pagingEnabled = true 87 | self.scrollView!.contentSize = CGSizeMake(5 * 320, self.view.bounds.height) 88 | 89 | // PageControl. 90 | self.pageControl!.frame = CGRectMake(141, 453, 36, 32) 91 | self.pageControl!.numberOfPages = self.numberOfPages() 92 | self.pageControl!.currentPage = 0 93 | self.pageControl!.addTarget(self, action: "didClickOnPageControl:", forControlEvents: UIControlEvents.ValueChanged) 94 | 95 | // UIButtons. 96 | self.leftButton!.frame = CGRectMake(20, 494, 130, 36) 97 | self.rightButton!.frame = CGRectMake(172, 494, 130, 36) 98 | self.leftButton!.backgroundColor = UIColor.darkGrayColor() 99 | self.rightButton!.backgroundColor = UIColor.darkGrayColor() 100 | self.leftButton!.setTitle("Button 1", forState: UIControlState.Normal) 101 | self.rightButton!.setTitle("Button 2", forState: UIControlState.Normal) 102 | self.leftButton!.addTarget(self, action: "didClickOnButton1:", forControlEvents: UIControlEvents.TouchUpInside) 103 | self.rightButton!.addTarget(self, action: "didClickOnButton2:", forControlEvents: UIControlEvents.TouchUpInside) 104 | 105 | 106 | // Fetch on screen. 107 | self.view.addSubview(self.frontLayerView) 108 | self.view.addSubview(self.backLayerView) 109 | self.view.addSubview(gradientView) 110 | self.view.addSubview(self.scrollView) 111 | self.view.addSubview(self.overlayLogo) 112 | self.view.addSubview(self.pageControl) 113 | self.view.addSubview(self.leftButton) 114 | self.view.addSubview(self.rightButton) 115 | } 116 | 117 | func didClickOnButton1(sender: UIButton) { 118 | 119 | } 120 | 121 | func didClickOnButton2(sender: UIButton) { 122 | 123 | } 124 | 125 | func didClickOnPageControl(sender: UIPageControl) { 126 | self.stopScrolling() 127 | 128 | // Make the scrollView animation. 129 | self.scrollToNextPageIndex(sender.currentPage) 130 | } 131 | 132 | // Set the list of pages (ICETutorialPage). 133 | func setPages(pages: ICETutorialPage[] ) { 134 | self.pages = pages 135 | } 136 | 137 | func numberOfPages() -> Int { 138 | if (self.pages) { 139 | return self.pages!.count 140 | } 141 | return 0 142 | } 143 | 144 | func animateScrolling() { 145 | if (self.currentState == ScrollingState.Manual) { 146 | return; 147 | } 148 | 149 | // Jump to the next page... 150 | var nextPage: Int = self.currentPageIndex! + 1 151 | if (nextPage == self.numberOfPages()) { 152 | // ...stop the auto-scrolling or... 153 | if (!self.autoScrollEnabled) { 154 | self.currentState = ScrollingState.Manual 155 | return; 156 | } 157 | 158 | // ...jump to the first page. 159 | nextPage = 0 160 | self.currentState = ScrollingState.Looping 161 | 162 | // Set alpha on layers. 163 | self.setOriginLayerAlpha() 164 | self.setBackLayerPictureWithPageIndex(-1) 165 | } else { 166 | self.currentState = ScrollingState.Auto 167 | } 168 | 169 | // Make the scrollView animation. 170 | var nextPagePosition: Float = Float(nextPage) * 320 171 | self.scrollView!.setContentOffset(CGPointMake(nextPagePosition, 0), animated: true) 172 | 173 | // Set the PageControl on the right page. 174 | self.pageControl!.currentPage = nextPage 175 | 176 | // Call the next animation after X seconds. 177 | self.autoScrollToNextPage() 178 | } 179 | 180 | func autoScrollToNextPage() { 181 | let page: ICETutorialPage = self.pages[self.currentPageIndex!] 182 | 183 | if (self.autoScrollEnabled) { 184 | NSTimer.scheduledTimerWithTimeInterval(page.duration!, target: self, selector: Selector("animateScrolling"), userInfo: nil, repeats: false) 185 | } 186 | } 187 | 188 | func scrollToNextPageIndex(nextPageIndex: NSInteger) { 189 | // Make the scrollView animation. 190 | self.scrollView!.setContentOffset(CGPointMake(Float(nextPageIndex) * self.view.frame.size.width,0), animated: true) 191 | 192 | // Set the PageControl on the right page. 193 | self.pageControl!.currentPage = nextPageIndex 194 | } 195 | 196 | // Run it. 197 | func startScrolling() { 198 | self.autoScrollToNextPage() 199 | } 200 | 201 | // Manually stop the scrolling 202 | func stopScrolling() { 203 | self.currentState = ScrollingState.Manual 204 | } 205 | 206 | // State. 207 | func getCurrentState() -> ScrollingState { 208 | return self.currentState! 209 | } 210 | 211 | // Setup the Title Label. 212 | func setOverlayTitle() { 213 | self.overlayLogo!.text = "Welcome" 214 | } 215 | 216 | // Setup the Title/Subtitle style/text. 217 | func setOverlayTexts() { 218 | var index: Int = 0 219 | for page in self.pages! { 220 | if (page.title.text) { 221 | var title: UILabel = self.overlayLabelWithText(page.title.text!, style: page.title!, commonStyle: self.commonPageTitleStyle, index: index) 222 | self.scrollView!.addSubview(title) 223 | } 224 | if (page.subTitle.text) { 225 | var subTitle: UILabel = self.overlayLabelWithText(page.subTitle.text!, style: page.subTitle!, commonStyle: self.commonPageSubTitleStyle!, index: index) 226 | self.scrollView!.addSubview(subTitle) 227 | } 228 | index++ 229 | } 230 | } 231 | 232 | func overlayLabelWithText(text: NSString, style: ICETutorialLabelStyle, commonStyle: ICETutorialLabelStyle, index: NSInteger) -> UILabel { 233 | var position: CGFloat = (CGFloat)(index * 320) 234 | var positionY: CGFloat = (CGFloat)(540 - commonStyle.offsset) 235 | var overlayLabel: UILabel = UILabel() 236 | overlayLabel.frame = CGRectMake(position, positionY, 320, 34) 237 | 238 | // SubTitles. 239 | overlayLabel.setTranslatesAutoresizingMaskIntoConstraints(false) 240 | overlayLabel.numberOfLines = commonStyle.linesNumber 241 | overlayLabel.backgroundColor = UIColor.clearColor() 242 | overlayLabel.textAlignment = NSTextAlignment.Center 243 | 244 | // Datas and style. 245 | overlayLabel.text = text 246 | if (style.font) { 247 | overlayLabel.font = style.font 248 | } else { 249 | overlayLabel.font = commonStyle.font 250 | } 251 | if (style.color) { 252 | overlayLabel.textColor = style.color 253 | } else { 254 | overlayLabel.textColor = commonStyle.color 255 | } 256 | 257 | return overlayLabel 258 | } 259 | 260 | // Handle the background layer image switch. 261 | func setBackLayerPictureWithPageIndex(index: NSInteger) { 262 | self.setBackgroundImage(self.backLayerView!, pageIndex: index + 1) 263 | } 264 | 265 | // Handle the front layer image switch. 266 | func setFrontLayerPictureWithPageIndex(index: NSInteger) { 267 | self.setBackgroundImage(self.frontLayerView!, pageIndex: index) 268 | } 269 | 270 | // Handle page image's loading 271 | func setBackgroundImage(imageView: UIImageView, pageIndex: NSInteger) { 272 | if (pageIndex >= self.pages!.count) { 273 | imageView.image = nil 274 | return 275 | } 276 | 277 | let page: ICETutorialPage = self.pages[pageIndex] 278 | imageView.image = UIImage(named: page.pictureName!) 279 | } 280 | 281 | // Setup layer's alpha. 282 | func setOriginLayerAlpha() { 283 | self.frontLayerView!.alpha = 1 284 | self.backLayerView!.alpha = 0 285 | } 286 | 287 | // Preset the origin state. 288 | func setOriginLayersState() { 289 | self.currentState = ScrollingState.Auto 290 | self.backLayerView!.backgroundColor = UIColor.blackColor() 291 | self.frontLayerView!.backgroundColor = UIColor.blackColor() 292 | self.setLayersPicturesWithIndex(0) 293 | } 294 | 295 | // Setup the layers with the page index. 296 | func setLayersPicturesWithIndex(index: NSInteger) { 297 | self.currentPageIndex = index 298 | self.setOriginLayerAlpha() 299 | self.setFrontLayerPictureWithPageIndex(index) 300 | self.setBackLayerPictureWithPageIndex(index) 301 | } 302 | 303 | // Animate the fade-in/out (Cross-disolve) with the scrollView translation. 304 | func disolveBackgroundWithContentOffset(offset: Float) { 305 | if (self.currentState == ScrollingState.Looping) { 306 | // Jump from the last page to the first. 307 | self.scrollingToFirstPageWithOffset(offset) 308 | } else { 309 | // Or just scroll to the next/previous page. 310 | self.scrollingToNextPageWithOffset(offset) 311 | } 312 | } 313 | 314 | // Handle alpha on layers when the auto-scrolling is looping to the first page. 315 | func scrollingToFirstPageWithOffset(offset: Float) { 316 | // Compute the scrolling percentage on all the page. 317 | let offsetX: Float = (offset * 320) 318 | let numberOfPage: Float = 5 319 | let offsetY: Float = (320 * numberOfPage) 320 | let finalOffset: Float = offsetX / offsetY 321 | 322 | // Scrolling finished... 323 | if (offset == 0) { 324 | self.setOriginLayersState() 325 | return 326 | } 327 | 328 | // Invert alpha for the back picture. 329 | var backLayerAlpha: Float = (1 - offset) 330 | var frontLayerAlpha: Float = offset 331 | 332 | // Set alpha. 333 | self.backLayerView!.alpha = backLayerAlpha 334 | self.frontLayerView!.alpha = frontLayerAlpha 335 | } 336 | 337 | // Handle alpha on layers when we are scrolling to the next/previous page. 338 | func scrollingToNextPageWithOffset(offset: Float) { 339 | // Current page index in scrolling. 340 | var page: Int = Int(offset) 341 | 342 | // Keep only the float value. 343 | var alphaValue: Float = offset - Float(Int(offset)); 344 | 345 | // This is only when you scroll to the right on the first page. 346 | // That will fade-in black the first picture. 347 | if (alphaValue < 0 && self.currentPageIndex == 0) { 348 | self.backLayerView!.image = nil 349 | self.frontLayerView!.alpha = (1 + alphaValue) 350 | return 351 | } 352 | 353 | // Switch pictures, and imageView alpha. 354 | if (page != self.currentPageIndex || 355 | (page == self.currentPageIndex && 0.0 < offset && offset < 1.0)) { 356 | self.setLayersPicturesWithIndex(page) 357 | } 358 | 359 | // Invert alpha for the front picture. 360 | var backLayerAlpha: Float = alphaValue 361 | var frontLayerAlpha: Float = (1 - alphaValue) 362 | 363 | // Set alpha. 364 | self.backLayerView!.alpha = backLayerAlpha 365 | self.frontLayerView!.alpha = frontLayerAlpha 366 | } 367 | 368 | func scrollViewDidScroll(scrollView: UIScrollView!) { 369 | // Get scrolling position, and nextPageindex. 370 | var scrollingPosition: Float = self.scrollView!.contentOffset.x / 320.0 371 | var nextPageIndex: Int = Int(scrollingPosition) 372 | 373 | // If we are looping, we reset the indexPage. 374 | if (self.currentState == ScrollingState.Looping) { 375 | nextPageIndex = 0 376 | } 377 | 378 | // If we are going to the next page, let's call the delegate. 379 | if (nextPageIndex != self.nextPageIndex) { 380 | // DELEGATE 381 | self.nextPageIndex = nextPageIndex 382 | } 383 | 384 | // Delegate when we reach the end. 385 | if (self.nextPageIndex == self.numberOfPages() - 1) { 386 | // DELEGATE 387 | } 388 | 389 | // Animate. 390 | self.disolveBackgroundWithContentOffset(scrollingPosition) 391 | } 392 | 393 | func scrollViewWillBeginDragging(scrollView: UIScrollView!) { 394 | // At the first user interaction, we disable the auto scrolling. 395 | if (self.scrollView!.tracking) { 396 | self.stopScrolling() 397 | } 398 | } 399 | 400 | func scrollViewDidEndDecelerating(scrollView: UIScrollView!) { 401 | // Update the page index. 402 | self.pageControl!.currentPage = self.currentPageIndex!; 403 | } 404 | } -------------------------------------------------------------------------------- /ICETutorial/Libraries/ICETutorialPage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialPage.swift 3 | // ICETutorial 4 | // 5 | // Created by Patrick Trillsam on 5/06/2014. 6 | // Copyright (c) 2014 Patrick Trillsam. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | class ICETutorialLabelStyle : NSObject { 13 | 14 | var text: String? 15 | var font: UIFont? 16 | var color: UIColor? 17 | var linesNumber: Int = 0 18 | var offsset: Int = 0 19 | 20 | init() { 21 | super.init() 22 | } 23 | 24 | init(text: String) { 25 | self.text = text 26 | } 27 | 28 | init(text: String, font: UIFont, color: UIColor) { 29 | self.text = text 30 | self.font = font 31 | self.color = color 32 | } 33 | } 34 | 35 | 36 | class ICETutorialPage : NSObject { 37 | 38 | var title: ICETutorialLabelStyle! 39 | var subTitle: ICETutorialLabelStyle! 40 | var pictureName: String? 41 | var duration: NSTimeInterval? 42 | 43 | init(title: String, subTitle: NSString, pictureName: String, duration: NSTimeInterval) { 44 | self.title = ICETutorialLabelStyle(text: title) 45 | self.subTitle = ICETutorialLabelStyle(text: subTitle) 46 | self.pictureName = pictureName 47 | self.duration = duration 48 | } 49 | 50 | func setSubTitleStyle(style: ICETutorialLabelStyle) { 51 | self.subTitle = style 52 | } 53 | 54 | func setTitleStyle(style: ICETutorialLabelStyle) { 55 | self.title = style 56 | } 57 | } -------------------------------------------------------------------------------- /ICETutorialTests/ICETutorialTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ICETutorialTests.swift 3 | // ICETutorialTests 4 | // 5 | // Created by Patrick Trillsam on 5/06/2014. 6 | // Copyright (c) 2014 Patrick Trillsam. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class ICETutorialTests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | // Put setup code here. This method is called before the invocation of each test method in the class. 16 | } 17 | 18 | override func tearDown() { 19 | // Put teardown code here. This method is called after the invocation of each test method in the class. 20 | super.tearDown() 21 | } 22 | 23 | func testExample() { 24 | // This is an example of a functional test case. 25 | XCTAssert(true, "Pass") 26 | } 27 | 28 | func testPerformanceExample() { 29 | // This is an example of a performance test case. 30 | self.measureBlock() { 31 | // Put the code you want to measure the time of here. 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /ICETutorialTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | Patrick-Trillsam.${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 | ICETutorialSwift 2 | ================ 3 | 4 | ### Welcome to ICETutorial (Swfit edition). 5 | This small project is an implementation of the newly tutorial introduced by the Path 3.X app, ported to Swift. 6 | Very simple and efficient tutorial, composed with N full-screen pictures that you can swipe for switching to the next/previous page. 7 | 8 | Here are the features : 9 | * Compose your own tutorial with N pictures 10 | * Fixed incrusted title (can be easily replaced by an UIImageView, or just removed) 11 | * Scrolling sub-titles for page, with associated descriptions (change the texts, font, color...) 12 | * Auto-scrolling (enable/disable, loop, setup duration for each pages) 13 | * Cross fade between next/previous background 14 | * Full delegate support available (for scrolling and button interactions) 15 | 16 | ![ICETutorial](https://github.com/icepat/ICETutorial/blob/master/screen_shot.jpg?raw=true) 17 | 18 | ### Setting-up the ICETutorial 19 | The code is commented, and I guess, easy to read/understand/modify. 20 | All the available settings for the scrolling are located in the header : ICETutorial.h : 21 | 22 | **Pages configuration :** 23 | ```swift 24 | // Init the pages texts, and pictures. 25 | let layer1: ICETutorialPage = ICETutorialPage(title: "Picture 1", subTitle: "Champs-Elysées by night", pictureName: "tutorial_background_00@2x.jpg", duration: 3.0) 26 | let layer2: ICETutorialPage = ICETutorialPage(title: "Picture 2", subTitle: "The Eiffel Tower with\n cloudy weather", pictureName: "tutorial_background_01@2x.jpg", duration: 3.0) 27 | let layer3: ICETutorialPage = ICETutorialPage(title: "Picture 3", subTitle: "An other famous street of Paris", pictureName: "tutorial_background_02@2x.jpg", duration: 3.0) 28 | let layer4: ICETutorialPage = ICETutorialPage(title: "Picture 4", subTitle: "The Eiffel Tower with a better weather", pictureName: "tutorial_background_03@2x.jpg", duration: 3.0) 29 | let layer5: ICETutorialPage = ICETutorialPage(title: "Picture 5", subTitle: "The Louvre's Museum Pyramide", pictureName: "tutorial_background_04@2x.jpg", duration: 3.0) 30 | [...] 31 | ``` 32 | 33 | **Common styles for SubTitles and Descriptions :** 34 | ```swift 35 | // Set the common style for SubTitles and Description (can be overrided on each page). 36 | let titleStyle: ICETutorialLabelStyle = ICETutorialLabelStyle() 37 | titleStyle.font = UIFont(name: "Helvetica-Bold", size: 17.0) 38 | titleStyle.color = UIColor.whiteColor() 39 | titleStyle.linesNumber = 1 40 | titleStyle.offsset = 180 41 | 42 | let subStyle: ICETutorialLabelStyle = ICETutorialLabelStyle() 43 | subStyle.font = UIFont(name: "Helvetica", size: 15.0) 44 | subStyle.color = UIColor.whiteColor() 45 | subStyle.linesNumber = 1 46 | subStyle.offsset = 150 47 | 48 | // Load into an array. 49 | let listPages: [ICETutorialPage] = [layer1, layer2, layer3, layer4, layer5] 50 | 51 | ``` 52 | 53 | **Init and load :** 54 | ```swift 55 | // Load the ICETutorialController. 56 | let controller: ICETutorialController = ICETutorialController(pages: listPages) 57 | 58 | // Set the common styles, and start scrolling (auto scroll, and looping enabled by default) 59 | controller.commonPageTitleStyle = titleStyle 60 | controller.commonPageSubTitleStyle = subStyle 61 | controller.startScrolling() 62 | ``` 63 | 64 | **The title is located in the ICETutorialController.swift :** 65 | ```swift 66 | // Setup the Title Label. 67 | func setOverlayTitle() { 68 | self.overlayLogo!.text = "Welcome" 69 | } 70 | ``` 71 | 72 | **Delegate implementation :** 73 | ```swift 74 | #pragma mark - ICETutorialController delegate 75 | - (void)tutorialController:(ICETutorialController *)tutorialController scrollingFromPageIndex:(NSUInteger)fromIndex toPageIndex:(NSUInteger)toIndex { 76 | NSLog(@"Scrolling from %lu to %lu", (unsigned long)fromIndex, (unsigned long)toIndex); 77 | } 78 | 79 | - (void)tutorialControllerDidReachLastPage:(ICETutorialController *)tutorialController { 80 | NSLog(@"Tutorial reached the last page."); 81 | } 82 | 83 | - (void)tutorialController:(ICETutorialController *)tutorialController didClickOnLeftButton:(UIButton *)sender { 84 | NSLog(@"Button 1 pressed."); 85 | } 86 | 87 | - (void)tutorialController:(ICETutorialController *)tutorialController didClickOnRightButton:(UIButton *)sender { 88 | NSLog(@"Button 2 pressed."); 89 | NSLog(@"Auto-scrolling stopped."); 90 | 91 | [self.viewController stopScrolling]; 92 | } 93 | ``` 94 | 95 | Checkout the others projects available on my account [@Icepat](https://github.com/icepat/) : 96 | 97 | [ICETutorial](https://github.com/icepat/ICETutorial) 98 | 99 | A nice tutorial like the one introduced in the Path 3.X App 100 | 101 | [ICETutorialSwift](https://github.com/icepat/ICETutorialSwift) 102 | 103 | A nice tutorial like the one introduced in the Path 3.X App (in Swift) 104 | 105 | 106 | Questions or ideas : patrick.trillsam@gmail.com. 107 | 108 | 109 | ###License : 110 | 111 | The MIT License 112 | 113 | Copyright (c) 2015 Patrick Trillsam - ICETutorial 114 | 115 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 116 | 117 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 118 | 119 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 120 | -------------------------------------------------------------------------------- /Resources/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/Default-568h@2x.png -------------------------------------------------------------------------------- /Resources/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/Default.png -------------------------------------------------------------------------------- /Resources/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/Default@2x.png -------------------------------------------------------------------------------- /Resources/background-gradient.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/background-gradient.png -------------------------------------------------------------------------------- /Resources/background-gradient@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/background-gradient@2x.png -------------------------------------------------------------------------------- /Resources/button-background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/button-background.png -------------------------------------------------------------------------------- /Resources/button-background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/button-background@2x.png -------------------------------------------------------------------------------- /Resources/tutorial_background_00@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/tutorial_background_00@2x.jpg -------------------------------------------------------------------------------- /Resources/tutorial_background_01@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/tutorial_background_01@2x.jpg -------------------------------------------------------------------------------- /Resources/tutorial_background_02@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/tutorial_background_02@2x.jpg -------------------------------------------------------------------------------- /Resources/tutorial_background_03@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/tutorial_background_03@2x.jpg -------------------------------------------------------------------------------- /Resources/tutorial_background_04@2x.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/icepat/ICETutorialSwift/163497ed8f9f25788d58ac6e245fd8c616f5f9b4/Resources/tutorial_background_04@2x.jpg --------------------------------------------------------------------------------