diff --git a/Demo-Swift/ICETutorial.xcodeproj/project.pbxproj b/Demo-Swift/ICETutorial.xcodeproj/project.pbxproj new file mode 100644 index 0000000..58d7c2d --- /dev/null +++ b/Demo-Swift/ICETutorial.xcodeproj/project.pbxproj @@ -0,0 +1,474 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + CB5149E61AF106DB009C5CBF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5149E51AF106DB009C5CBF /* AppDelegate.swift */; }; + CB5149E91AF106DB009C5CBF /* ICETutorial.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = CB5149E71AF106DB009C5CBF /* ICETutorial.xcdatamodeld */; }; + CB5149EB1AF106DB009C5CBF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5149EA1AF106DB009C5CBF /* ViewController.swift */; }; + CB5149EE1AF106DB009C5CBF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = CB5149EC1AF106DB009C5CBF /* Main.storyboard */; }; + CB5149F01AF106DB009C5CBF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CB5149EF1AF106DB009C5CBF /* Images.xcassets */; }; + CB5149F31AF106DB009C5CBF /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = CB5149F11AF106DB009C5CBF /* LaunchScreen.xib */; }; + CB5149FF1AF106DB009C5CBF /* ICETutorialTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = CB5149FE1AF106DB009C5CBF /* ICETutorialTests.swift */; }; + CB514A0F1AF10752009C5CBF /* ICETutorialController.m in Sources */ = {isa = PBXBuildFile; fileRef = CB514A0A1AF10752009C5CBF /* ICETutorialController.m */; }; + CB514A101AF10752009C5CBF /* ICETutorialPage.m in Sources */ = {isa = PBXBuildFile; fileRef = CB514A0C1AF10752009C5CBF /* ICETutorialPage.m */; }; + CB514A111AF10752009C5CBF /* ICETutorialStyle.m in Sources */ = {isa = PBXBuildFile; fileRef = CB514A0E1AF10752009C5CBF /* ICETutorialStyle.m */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + CB5149F91AF106DB009C5CBF /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = CB5149D81AF106DB009C5CBF /* Project object */; + proxyType = 1; + remoteGlobalIDString = CB5149DF1AF106DB009C5CBF; + remoteInfo = ICETutorial; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + CB5149E01AF106DB009C5CBF /* ICETutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ICETutorial.app; sourceTree = BUILT_PRODUCTS_DIR; }; + CB5149E41AF106DB009C5CBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CB5149E51AF106DB009C5CBF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + CB5149E81AF106DB009C5CBF /* ICETutorial.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = ICETutorial.xcdatamodel; sourceTree = ""; }; + CB5149EA1AF106DB009C5CBF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; + CB5149ED1AF106DB009C5CBF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + CB5149EF1AF106DB009C5CBF /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; + CB5149F21AF106DB009C5CBF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; + CB5149F81AF106DB009C5CBF /* ICETutorialTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ICETutorialTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + CB5149FD1AF106DB009C5CBF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + CB5149FE1AF106DB009C5CBF /* ICETutorialTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ICETutorialTests.swift; sourceTree = ""; }; + CB514A081AF10751009C5CBF /* ICETutorial-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ICETutorial-Bridging-Header.h"; sourceTree = ""; }; + CB514A091AF10752009C5CBF /* ICETutorialController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICETutorialController.h; path = Libraries/ICETutorialController.h; sourceTree = SOURCE_ROOT; }; + CB514A0A1AF10752009C5CBF /* ICETutorialController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ICETutorialController.m; path = Libraries/ICETutorialController.m; sourceTree = SOURCE_ROOT; }; + CB514A0B1AF10752009C5CBF /* ICETutorialPage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICETutorialPage.h; path = Libraries/ICETutorialPage.h; sourceTree = SOURCE_ROOT; }; + CB514A0C1AF10752009C5CBF /* ICETutorialPage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ICETutorialPage.m; path = Libraries/ICETutorialPage.m; sourceTree = SOURCE_ROOT; }; + CB514A0D1AF10752009C5CBF /* ICETutorialStyle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ICETutorialStyle.h; path = Libraries/ICETutorialStyle.h; sourceTree = SOURCE_ROOT; }; + CB514A0E1AF10752009C5CBF /* ICETutorialStyle.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ICETutorialStyle.m; path = Libraries/ICETutorialStyle.m; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + CB5149DD1AF106DB009C5CBF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CB5149F51AF106DB009C5CBF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + CB5149D71AF106DB009C5CBF = { + isa = PBXGroup; + children = ( + CB5149E21AF106DB009C5CBF /* ICETutorial */, + CB5149FB1AF106DB009C5CBF /* ICETutorialTests */, + CB5149E11AF106DB009C5CBF /* Products */, + ); + sourceTree = ""; + }; + CB5149E11AF106DB009C5CBF /* Products */ = { + isa = PBXGroup; + children = ( + CB5149E01AF106DB009C5CBF /* ICETutorial.app */, + CB5149F81AF106DB009C5CBF /* ICETutorialTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + CB5149E21AF106DB009C5CBF /* ICETutorial */ = { + isa = PBXGroup; + children = ( + CB514A121AF1075A009C5CBF /* Library */, + CB5149E51AF106DB009C5CBF /* AppDelegate.swift */, + CB5149EA1AF106DB009C5CBF /* ViewController.swift */, + CB5149EC1AF106DB009C5CBF /* Main.storyboard */, + CB5149EF1AF106DB009C5CBF /* Images.xcassets */, + CB5149F11AF106DB009C5CBF /* LaunchScreen.xib */, + CB5149E71AF106DB009C5CBF /* ICETutorial.xcdatamodeld */, + CB5149E31AF106DB009C5CBF /* Supporting Files */, + CB514A081AF10751009C5CBF /* ICETutorial-Bridging-Header.h */, + ); + path = ICETutorial; + sourceTree = ""; + }; + CB5149E31AF106DB009C5CBF /* Supporting Files */ = { + isa = PBXGroup; + children = ( + CB5149E41AF106DB009C5CBF /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + CB5149FB1AF106DB009C5CBF /* ICETutorialTests */ = { + isa = PBXGroup; + children = ( + CB5149FE1AF106DB009C5CBF /* ICETutorialTests.swift */, + CB5149FC1AF106DB009C5CBF /* Supporting Files */, + ); + path = ICETutorialTests; + sourceTree = ""; + }; + CB5149FC1AF106DB009C5CBF /* Supporting Files */ = { + isa = PBXGroup; + children = ( + CB5149FD1AF106DB009C5CBF /* Info.plist */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + CB514A121AF1075A009C5CBF /* Library */ = { + isa = PBXGroup; + children = ( + CB514A091AF10752009C5CBF /* ICETutorialController.h */, + CB514A0A1AF10752009C5CBF /* ICETutorialController.m */, + CB514A0B1AF10752009C5CBF /* ICETutorialPage.h */, + CB514A0C1AF10752009C5CBF /* ICETutorialPage.m */, + CB514A0D1AF10752009C5CBF /* ICETutorialStyle.h */, + CB514A0E1AF10752009C5CBF /* ICETutorialStyle.m */, + ); + name = Library; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + CB5149DF1AF106DB009C5CBF /* ICETutorial */ = { + isa = PBXNativeTarget; + buildConfigurationList = CB514A021AF106DB009C5CBF /* Build configuration list for PBXNativeTarget "ICETutorial" */; + buildPhases = ( + CB5149DC1AF106DB009C5CBF /* Sources */, + CB5149DD1AF106DB009C5CBF /* Frameworks */, + CB5149DE1AF106DB009C5CBF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = ICETutorial; + productName = ICETutorial; + productReference = CB5149E01AF106DB009C5CBF /* ICETutorial.app */; + productType = "com.apple.product-type.application"; + }; + CB5149F71AF106DB009C5CBF /* ICETutorialTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = CB514A051AF106DB009C5CBF /* Build configuration list for PBXNativeTarget "ICETutorialTests" */; + buildPhases = ( + CB5149F41AF106DB009C5CBF /* Sources */, + CB5149F51AF106DB009C5CBF /* Frameworks */, + CB5149F61AF106DB009C5CBF /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + CB5149FA1AF106DB009C5CBF /* PBXTargetDependency */, + ); + name = ICETutorialTests; + productName = ICETutorialTests; + productReference = CB5149F81AF106DB009C5CBF /* ICETutorialTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + CB5149D81AF106DB009C5CBF /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0630; + ORGANIZATIONNAME = HuCharlie; + TargetAttributes = { + CB5149DF1AF106DB009C5CBF = { + CreatedOnToolsVersion = 6.3.1; + }; + CB5149F71AF106DB009C5CBF = { + CreatedOnToolsVersion = 6.3.1; + TestTargetID = CB5149DF1AF106DB009C5CBF; + }; + }; + }; + buildConfigurationList = CB5149DB1AF106DB009C5CBF /* Build configuration list for PBXProject "ICETutorial" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = CB5149D71AF106DB009C5CBF; + productRefGroup = CB5149E11AF106DB009C5CBF /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + CB5149DF1AF106DB009C5CBF /* ICETutorial */, + CB5149F71AF106DB009C5CBF /* ICETutorialTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + CB5149DE1AF106DB009C5CBF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CB5149EE1AF106DB009C5CBF /* Main.storyboard in Resources */, + CB5149F31AF106DB009C5CBF /* LaunchScreen.xib in Resources */, + CB5149F01AF106DB009C5CBF /* Images.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CB5149F61AF106DB009C5CBF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + CB5149DC1AF106DB009C5CBF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CB5149EB1AF106DB009C5CBF /* ViewController.swift in Sources */, + CB514A111AF10752009C5CBF /* ICETutorialStyle.m in Sources */, + CB5149E61AF106DB009C5CBF /* AppDelegate.swift in Sources */, + CB514A101AF10752009C5CBF /* ICETutorialPage.m in Sources */, + CB5149E91AF106DB009C5CBF /* ICETutorial.xcdatamodeld in Sources */, + CB514A0F1AF10752009C5CBF /* ICETutorialController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + CB5149F41AF106DB009C5CBF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + CB5149FF1AF106DB009C5CBF /* ICETutorialTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + CB5149FA1AF106DB009C5CBF /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = CB5149DF1AF106DB009C5CBF /* ICETutorial */; + targetProxy = CB5149F91AF106DB009C5CBF /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + CB5149EC1AF106DB009C5CBF /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + CB5149ED1AF106DB009C5CBF /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + CB5149F11AF106DB009C5CBF /* LaunchScreen.xib */ = { + isa = PBXVariantGroup; + children = ( + CB5149F21AF106DB009C5CBF /* Base */, + ); + name = LaunchScreen.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + CB514A001AF106DB009C5CBF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + CB514A011AF106DB009C5CBF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 8.3; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + CB514A031AF106DB009C5CBF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + INFOPLIST_FILE = ICETutorial/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "ICETutorial/ICETutorial-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + CB514A041AF106DB009C5CBF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + INFOPLIST_FILE = ICETutorial/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "ICETutorial/ICETutorial-Bridging-Header.h"; + }; + name = Release; + }; + CB514A061AF106DB009C5CBF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + INFOPLIST_FILE = ICETutorialTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ICETutorial.app/ICETutorial"; + }; + name = Debug; + }; + CB514A071AF106DB009C5CBF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + FRAMEWORK_SEARCH_PATHS = ( + "$(SDKROOT)/Developer/Library/Frameworks", + "$(inherited)", + ); + INFOPLIST_FILE = ICETutorialTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_NAME = "$(TARGET_NAME)"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/ICETutorial.app/ICETutorial"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + CB5149DB1AF106DB009C5CBF /* Build configuration list for PBXProject "ICETutorial" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB514A001AF106DB009C5CBF /* Debug */, + CB514A011AF106DB009C5CBF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + CB514A021AF106DB009C5CBF /* Build configuration list for PBXNativeTarget "ICETutorial" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB514A031AF106DB009C5CBF /* Debug */, + CB514A041AF106DB009C5CBF /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; + CB514A051AF106DB009C5CBF /* Build configuration list for PBXNativeTarget "ICETutorialTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + CB514A061AF106DB009C5CBF /* Debug */, + CB514A071AF106DB009C5CBF /* Release */, + ); + defaultConfigurationIsVisible = 0; + }; +/* End XCConfigurationList section */ + +/* Begin XCVersionGroup section */ + CB5149E71AF106DB009C5CBF /* ICETutorial.xcdatamodeld */ = { + isa = XCVersionGroup; + children = ( + CB5149E81AF106DB009C5CBF /* ICETutorial.xcdatamodel */, + ); + currentVersion = CB5149E81AF106DB009C5CBF /* ICETutorial.xcdatamodel */; + path = ICETutorial.xcdatamodeld; + sourceTree = ""; + versionGroupType = wrapper.xcdatamodel; + }; +/* End XCVersionGroup section */ + }; + rootObject = CB5149D81AF106DB009C5CBF /* Project object */; +} diff --git a/ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Demo-Swift/ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata old mode 100755 new mode 100644 similarity index 100% rename from ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to Demo-Swift/ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Demo-Swift/ICETutorial.xcodeproj/xcuserdata/Charlie.xcuserdatad/xcschemes/xcschememanagement.plist b/Demo-Swift/ICETutorial.xcodeproj/xcuserdata/Charlie.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..b32c900 --- /dev/null +++ b/Demo-Swift/ICETutorial.xcodeproj/xcuserdata/Charlie.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + ICETutorial.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + CB5149DF1AF106DB009C5CBF + + primary + + + CB5149F71AF106DB009C5CBF + + primary + + + + + diff --git a/Demo-Swift/ICETutorial/AppDelegate.swift b/Demo-Swift/ICETutorial/AppDelegate.swift new file mode 100644 index 0000000..087aaaa --- /dev/null +++ b/Demo-Swift/ICETutorial/AppDelegate.swift @@ -0,0 +1,189 @@ +// +// AppDelegate.swift +// ICETutorial-2 +// +// Created by HuCharlie on 4/29/15. +// Copyright (c) 2015 HuCharlie. All rights reserved. +// + +import UIKit +import CoreData + +@UIApplicationMain +class AppDelegate: UIResponder, UIApplicationDelegate, ICETutorialControllerDelegate{ + + var window: UIWindow? + var viewController:ICETutorialController? + + + func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + + + // Init tutorial. + let tutorialLayers:NSArray = picGallerySetup()as NSArray + self.viewController = ICETutorialController(pages: tutorialLayers as [AnyObject], delegate: self) + + var titleStyle:ICETutorialLabelStyle = ICETutorialLabelStyle(font: UIFont(name: "Helvetica-Bold", size: 27.0 as CGFloat), textColor: UIColor.whiteColor(), linesNumber: 2, offset: 180) + + ICETutorialStyle.sharedInstance().titleStyle = titleStyle + ICETutorialStyle.sharedInstance().subTitleColor = UIColor.whiteColor() + ICETutorialStyle.sharedInstance().subTitleOffset = 150 + + // Run it. + + self.viewController!.startScrolling() + self.window?.rootViewController = self.viewController + self.window?.makeKeyAndVisible() + + + return true + } + + // image setup + func picGallerySetup() -> NSArray { + + let layer1:ICETutorialPage = ICETutorialPage(title: "Picture 1", subTitle: "Champs-Elysées by night", pictureName: "tutorial_background_00", duration: 3.0)as ICETutorialPage + + let layer2:ICETutorialPage = ICETutorialPage(title: "Picture 1", subTitle: "Champs-Elysées by night", pictureName: "tutorial_background_01", duration: 3.0)as ICETutorialPage + + let layer3:ICETutorialPage = ICETutorialPage(title: "Picture 1", subTitle: "Champs-Elysées by night", pictureName: "tutorial_background_02", duration: 3.0)as ICETutorialPage + + let layer4:ICETutorialPage = ICETutorialPage(title: "Picture 1", subTitle: "Champs-Elysées by night", pictureName: "tutorial_background_03", duration: 3.0)as ICETutorialPage + + let layer5:ICETutorialPage = ICETutorialPage(title: "Picture 1", subTitle: "Champs-Elysées by night", pictureName: "tutorial_background_04", duration: 3.0)as ICETutorialPage + + let tutorialLayers:NSArray = [layer1,layer2,layer3,layer4,layer5] + + + return tutorialLayers + + } + + //icetutorial delegate + + func tutorialController(tutorialController: ICETutorialController!, didClickOnLeftButton sender: UIButton!) { + + + } + + func tutorialController(tutorialController: ICETutorialController!, didClickOnRightButton sender: UIButton!) { + + + } + + func tutorialController(tutorialController: ICETutorialController!, scrollingFromPageIndex fromIndex: UInt, toPageIndex toIndex: UInt) { + + + } + + func tutorialControllerDidReachLastPage(tutorialController: ICETutorialController!) { + + + } + + + + + + + + + + + + + + + + + + + func applicationWillResignActive(application: UIApplication) { + // 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. + // 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. + } + + func applicationDidEnterBackground(application: UIApplication) { + // 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. + // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. + } + + func applicationWillEnterForeground(application: UIApplication) { + // 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. + } + + func applicationDidBecomeActive(application: UIApplication) { + // 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. + } + + func applicationWillTerminate(application: UIApplication) { + // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. + // Saves changes in the application's managed object context before the application terminates. + self.saveContext() + } + + // MARK: - Core Data stack + + lazy var applicationDocumentsDirectory: NSURL = { + // The directory the application uses to store the Core Data store file. This code uses a directory named "TJ-University.ICETutorial_2" in the application's documents Application Support directory. + let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) + return urls[urls.count-1] as! NSURL + }() + + lazy var managedObjectModel: NSManagedObjectModel = { + // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model. + let modelURL = NSBundle.mainBundle().URLForResource("ICETutorial_2", withExtension: "momd")! + return NSManagedObjectModel(contentsOfURL: modelURL)! + }() + + lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = { + // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. + // Create the coordinator and store + var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) + let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("ICETutorial_2.sqlite") + var error: NSError? = nil + var failureReason = "There was an error creating or loading the application's saved data." + if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil, error: &error) == nil { + coordinator = nil + // Report any error we got. + var dict = [String: AnyObject]() + dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" + dict[NSLocalizedFailureReasonErrorKey] = failureReason + dict[NSUnderlyingErrorKey] = error + error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) + // Replace this with code to handle the error appropriately. + // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + NSLog("Unresolved error \(error), \(error!.userInfo)") + abort() + } + + return coordinator + }() + + lazy var managedObjectContext: NSManagedObjectContext? = { + // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail. + let coordinator = self.persistentStoreCoordinator + if coordinator == nil { + return nil + } + var managedObjectContext = NSManagedObjectContext() + managedObjectContext.persistentStoreCoordinator = coordinator + return managedObjectContext + }() + + // MARK: - Core Data Saving support + + func saveContext () { + if let moc = self.managedObjectContext { + var error: NSError? = nil + if moc.hasChanges && !moc.save(&error) { + // Replace this implementation with code to handle the error appropriately. + // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. + NSLog("Unresolved error \(error), \(error!.userInfo)") + abort() + } + } + } + +} + diff --git a/Demo-Swift/ICETutorial/Base.lproj/LaunchScreen.xib b/Demo-Swift/ICETutorial/Base.lproj/LaunchScreen.xib new file mode 100644 index 0000000..a2cf4a3 --- /dev/null +++ b/Demo-Swift/ICETutorial/Base.lproj/LaunchScreen.xib @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo-Swift/ICETutorial/Base.lproj/Main.storyboard b/Demo-Swift/ICETutorial/Base.lproj/Main.storyboard new file mode 100644 index 0000000..52ea29e --- /dev/null +++ b/Demo-Swift/ICETutorial/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Demo-Swift/ICETutorial/ICETutorial-Bridging-Header.h b/Demo-Swift/ICETutorial/ICETutorial-Bridging-Header.h new file mode 100644 index 0000000..76343d5 --- /dev/null +++ b/Demo-Swift/ICETutorial/ICETutorial-Bridging-Header.h @@ -0,0 +1,7 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "ICETutorialPage.h" +#import "ICETutorialStyle.h" +#import "ICETutorialController.h" diff --git a/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/WorkspaceSettings.xcsettings b/Demo-Swift/ICETutorial/ICETutorial.xcdatamodeld/.xccurrentversion old mode 100755 new mode 100644 similarity index 56% rename from ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/WorkspaceSettings.xcsettings rename to Demo-Swift/ICETutorial/ICETutorial.xcdatamodeld/.xccurrentversion index bfffcfe..dc13d4b --- a/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/WorkspaceSettings.xcsettings +++ b/Demo-Swift/ICETutorial/ICETutorial.xcdatamodeld/.xccurrentversion @@ -2,9 +2,7 @@ - HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges - - SnapshotAutomaticallyBeforeSignificantChanges - + _XCCurrentVersionName + ICETutorial.xcdatamodel diff --git a/Demo-Swift/ICETutorial/ICETutorial.xcdatamodeld/ICETutorial.xcdatamodel/contents b/Demo-Swift/ICETutorial/ICETutorial.xcdatamodeld/ICETutorial.xcdatamodel/contents new file mode 100644 index 0000000..193f33c --- /dev/null +++ b/Demo-Swift/ICETutorial/ICETutorial.xcdatamodeld/ICETutorial.xcdatamodel/contents @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Demo-Swift/ICETutorial/Images.xcassets/AppIcon.appiconset/Contents.json b/Demo-Swift/ICETutorial/Images.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..118c98f --- /dev/null +++ b/Demo-Swift/ICETutorial/Images.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,38 @@ +{ + "images" : [ + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "29x29", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "40x40", + "scale" : "3x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "60x60", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Demo-Swift/ICETutorial/Images.xcassets/background-gradient.imageset/Contents.json b/Demo-Swift/ICETutorial/Images.xcassets/background-gradient.imageset/Contents.json new file mode 100644 index 0000000..101b0e2 --- /dev/null +++ b/Demo-Swift/ICETutorial/Images.xcassets/background-gradient.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "background-gradient.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "background-gradient@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Resources/background-gradient.png b/Demo-Swift/ICETutorial/Images.xcassets/background-gradient.imageset/background-gradient.png old mode 100755 new mode 100644 similarity index 100% rename from Resources/background-gradient.png rename to Demo-Swift/ICETutorial/Images.xcassets/background-gradient.imageset/background-gradient.png diff --git a/Resources/background-gradient@2x.png b/Demo-Swift/ICETutorial/Images.xcassets/background-gradient.imageset/background-gradient@2x.png old mode 100755 new mode 100644 similarity index 100% rename from Resources/background-gradient@2x.png rename to Demo-Swift/ICETutorial/Images.xcassets/background-gradient.imageset/background-gradient@2x.png diff --git a/Demo-Swift/ICETutorial/Images.xcassets/button-background.imageset/Contents.json b/Demo-Swift/ICETutorial/Images.xcassets/button-background.imageset/Contents.json new file mode 100644 index 0000000..05f35ae --- /dev/null +++ b/Demo-Swift/ICETutorial/Images.xcassets/button-background.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x", + "filename" : "button-background.png" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "button-background@2x.png" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Resources/button-background.png b/Demo-Swift/ICETutorial/Images.xcassets/button-background.imageset/button-background.png old mode 100755 new mode 100644 similarity index 100% rename from Resources/button-background.png rename to Demo-Swift/ICETutorial/Images.xcassets/button-background.imageset/button-background.png diff --git a/Resources/button-background@2x.png b/Demo-Swift/ICETutorial/Images.xcassets/button-background.imageset/button-background@2x.png old mode 100755 new mode 100644 similarity index 100% rename from Resources/button-background@2x.png rename to Demo-Swift/ICETutorial/Images.xcassets/button-background.imageset/button-background@2x.png diff --git a/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_00.imageset/Contents.json b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_00.imageset/Contents.json new file mode 100644 index 0000000..b10d168 --- /dev/null +++ b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_00.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "tutorial_background_00@2x.jpg" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Resources/tutorial_background_00@2x.jpg b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_00.imageset/tutorial_background_00@2x.jpg old mode 100755 new mode 100644 similarity index 100% rename from Resources/tutorial_background_00@2x.jpg rename to Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_00.imageset/tutorial_background_00@2x.jpg diff --git a/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_01.imageset/Contents.json b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_01.imageset/Contents.json new file mode 100644 index 0000000..fca4322 --- /dev/null +++ b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_01.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "tutorial_background_01@2x.jpg" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Resources/tutorial_background_01@2x.jpg b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_01.imageset/tutorial_background_01@2x.jpg old mode 100755 new mode 100644 similarity index 100% rename from Resources/tutorial_background_01@2x.jpg rename to Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_01.imageset/tutorial_background_01@2x.jpg diff --git a/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_02.imageset/Contents.json b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_02.imageset/Contents.json new file mode 100644 index 0000000..c92af0e --- /dev/null +++ b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_02.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "tutorial_background_02@2x.jpg" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Resources/tutorial_background_02@2x.jpg b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_02.imageset/tutorial_background_02@2x.jpg old mode 100755 new mode 100644 similarity index 100% rename from Resources/tutorial_background_02@2x.jpg rename to Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_02.imageset/tutorial_background_02@2x.jpg diff --git a/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_03.imageset/Contents.json b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_03.imageset/Contents.json new file mode 100644 index 0000000..b7568b6 --- /dev/null +++ b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_03.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "tutorial_background_03@2x.jpg" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Resources/tutorial_background_03@2x.jpg b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_03.imageset/tutorial_background_03@2x.jpg old mode 100755 new mode 100644 similarity index 100% rename from Resources/tutorial_background_03@2x.jpg rename to Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_03.imageset/tutorial_background_03@2x.jpg diff --git a/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_04.imageset/Contents.json b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_04.imageset/Contents.json new file mode 100644 index 0000000..24c3bc7 --- /dev/null +++ b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_04.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x", + "filename" : "tutorial_background_04@2x.jpg" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Resources/tutorial_background_04@2x.jpg b/Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_04.imageset/tutorial_background_04@2x.jpg old mode 100755 new mode 100644 similarity index 100% rename from Resources/tutorial_background_04@2x.jpg rename to Demo-Swift/ICETutorial/Images.xcassets/tutorial_background_04.imageset/tutorial_background_04@2x.jpg diff --git a/Demo-Swift/ICETutorial/Info.plist b/Demo-Swift/ICETutorial/Info.plist new file mode 100644 index 0000000..910444f --- /dev/null +++ b/Demo-Swift/ICETutorial/Info.plist @@ -0,0 +1,40 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + TJ-University.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/Demo-Swift/ICETutorial/ViewController.swift b/Demo-Swift/ICETutorial/ViewController.swift new file mode 100644 index 0000000..7bd45ea --- /dev/null +++ b/Demo-Swift/ICETutorial/ViewController.swift @@ -0,0 +1,25 @@ +// +// ViewController.swift +// ICETutorial +// +// Created by HuCharlie on 4/29/15. +// Copyright (c) 2015 HuCharlie. All rights reserved. +// + +import UIKit + +class ViewController: UIViewController { + + override func viewDidLoad() { + super.viewDidLoad() + // Do any additional setup after loading the view, typically from a nib. + } + + override func didReceiveMemoryWarning() { + super.didReceiveMemoryWarning() + // Dispose of any resources that can be recreated. + } + + +} + diff --git a/Demo-Swift/ICETutorialTests/ICETutorialTests.swift b/Demo-Swift/ICETutorialTests/ICETutorialTests.swift new file mode 100644 index 0000000..1ad7b43 --- /dev/null +++ b/Demo-Swift/ICETutorialTests/ICETutorialTests.swift @@ -0,0 +1,36 @@ +// +// ICETutorialTests.swift +// ICETutorialTests +// +// Created by HuCharlie on 4/29/15. +// Copyright (c) 2015 HuCharlie. All rights reserved. +// + +import UIKit +import XCTest + +class ICETutorialTests: XCTestCase { + + override func setUp() { + super.setUp() + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDown() { + // Put teardown code here. This method is called after the invocation of each test method in the class. + super.tearDown() + } + + func testExample() { + // This is an example of a functional test case. + XCTAssert(true, "Pass") + } + + func testPerformanceExample() { + // This is an example of a performance test case. + self.measureBlock() { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/Demo-Swift/ICETutorialTests/Info.plist b/Demo-Swift/ICETutorialTests/Info.plist new file mode 100644 index 0000000..242262c --- /dev/null +++ b/Demo-Swift/ICETutorialTests/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + TJ-University.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + BNDL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + + diff --git a/ICETutorial/Libraries/ICETutorialController.h b/Demo-Swift/Libraries/ICETutorialController.h similarity index 92% rename from ICETutorial/Libraries/ICETutorialController.h rename to Demo-Swift/Libraries/ICETutorialController.h index 2a4544b..f99ecd7 100755 --- a/ICETutorial/Libraries/ICETutorialController.h +++ b/Demo-Swift/Libraries/ICETutorialController.h @@ -16,7 +16,7 @@ #define TUTORIAL_TITLE_LINES_NUMBER 1 #define TUTORIAL_TITLE_OFFSET 180 #define TUTORIAL_SUB_TITLE_FONT [UIFont fontWithName:@"Helvetica" size:15.0f] -#define TUTORIAL_SUB_TITLE_LINES_NUMBER 2 +#define TUTORIAL_SUB_TITLE_LINES_NUMBER 3 #define TUTORIAL_SUB_TITLE_OFFSET 150 // Scrolling state. @@ -33,6 +33,7 @@ typedef void (^ButtonBlock)(UIButton *button); @property (nonatomic, assign) BOOL autoScrollEnabled; @property (nonatomic, weak) id delegate; +@property (nonatomic, assign) NSInteger currentPageIndex; // Inits. - (instancetype)initWithPages:(NSArray *)pages; @@ -49,6 +50,7 @@ typedef void (^ButtonBlock)(UIButton *button); // State. - (ScrollingState)getCurrentState; +- (void)scrollToNextPageIndex:(NSUInteger)nextPageIndex; @end diff --git a/ICETutorial/Libraries/ICETutorialController.m b/Demo-Swift/Libraries/ICETutorialController.m similarity index 83% rename from ICETutorial/Libraries/ICETutorialController.m rename to Demo-Swift/Libraries/ICETutorialController.m index 1efb63c..5a730fb 100755 --- a/ICETutorial/Libraries/ICETutorialController.m +++ b/Demo-Swift/Libraries/ICETutorialController.m @@ -20,7 +20,6 @@ @interface ICETutorialController () @property (nonatomic, assign) ScrollingState currentState; @property (nonatomic, strong) NSArray *pages; -@property (nonatomic, assign) NSInteger currentPageIndex; @property (nonatomic, assign) NSInteger nextPageIndex; @end @@ -81,13 +80,13 @@ - (void)setupView { [self.scrollView setDelegate:self]; [self.scrollView setPagingEnabled:YES]; [self.scrollView setContentSize:CGSizeMake([self numberOfPages] * self.view.frame.size.width, - self.scrollView.contentSize.height)]; - + self.scrollView.contentSize.height)]; + // Title. [self.overlayTitle setTextColor:[UIColor whiteColor]]; - [self.overlayTitle setFont:[UIFont fontWithName:@"Helvetica-Bold" size:32.0]]; + [self.overlayTitle setFont:[UIFont fontWithName:@"Nexa Bold" size:32.0]]; [self.overlayTitle setTextAlignment:NSTextAlignmentCenter]; - + // PageControl configuration. [self.pageControl setNumberOfPages:[self numberOfPages]]; [self.pageControl setCurrentPage:0]; @@ -95,18 +94,29 @@ - (void)setupView { action:@selector(didClickOnPageControl:) forControlEvents:UIControlEventValueChanged]; + UIColor *customOrange = [UIColor colorWithRed:(244/255.0f) green:(138/255.0f) blue:(103/255.0f) alpha:1.0]; + // UIButtons. - [self.leftButton setBackgroundColor:[UIColor darkGrayColor]]; - [self.rightButton setBackgroundColor:[UIColor darkGrayColor]]; - [self.leftButton setTitle:@"Button 1" forState:UIControlStateNormal]; - [self.rightButton setTitle:@"Button 2" forState:UIControlStateNormal]; + [self.leftButton setBackgroundColor:customOrange]; + [self.leftButton.layer setCornerRadius:6.0]; + [self.leftButton setContentVerticalAlignment:UIControlContentVerticalAlignmentFill]; + [self.leftButton setTitle:NSLocalizedString(@"Next", nil) forState:UIControlStateNormal]; + [self.leftButton setShowsTouchWhenHighlighted:YES]; + [self.leftButton.titleLabel setFont:[UIFont fontWithName:@"Nexa Light" size:17.0]]; [self.leftButton addTarget:self action:@selector(didClickOnButton1:) forControlEvents:UIControlEventTouchUpInside]; + + [self.rightButton setBackgroundColor:customOrange]; + [self.rightButton.layer setCornerRadius:6.0]; + [self.rightButton setContentVerticalAlignment:UIControlContentVerticalAlignmentFill]; + [self.rightButton setTitle:NSLocalizedString(@"LoginViewController_btnLogin", nil) forState:UIControlStateNormal]; + [self.rightButton setShowsTouchWhenHighlighted:YES]; + [self.rightButton.titleLabel setFont:[UIFont fontWithName:@"Nexa Light" size:17.0]]; [self.rightButton addTarget:self action:@selector(didClickOnButton2:) forControlEvents:UIControlEventTouchUpInside]; - + [self.view addSubview:self.frontLayerView]; [self.view addSubview:self.backLayerView]; [self.view addSubview:self.gradientView]; @@ -122,15 +132,24 @@ - (void)setupView { #pragma mark - Constraints management. - (void)addAllConstraints { [self.frontLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; - [self.backLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; + [self.backLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; NSDictionary *views = NSDictionaryOfVariableBindings(_overlayTitle, _leftButton, _rightButton, _pageControl, _gradientView); NSMutableArray *constraints = [NSMutableArray array]; // Overlay title. [self.overlayTitle setTranslatesAutoresizingMaskIntoConstraints:NO]; - [constraints addObject:@"V:|-116-[_overlayTitle(==50)]"]; - [constraints addObject:@"H:|-54-[_overlayTitle(==212)]-|"]; + [constraints addObject:@"V:|-85-[_overlayTitle(==50)]"]; + // [constraints addObject:@"H:|-0-[_overlayTitle(>=212)]-0-|"]; + + [self.view addConstraint: + [NSLayoutConstraint constraintWithItem:_overlayTitle + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; // Buttons. [self.leftButton setTranslatesAutoresizingMaskIntoConstraints:NO]; @@ -138,16 +157,24 @@ - (void)addAllConstraints { [constraints addObject:@"V:[_leftButton(==36)]-20-|"]; [constraints addObject:@"V:[_rightButton(==36)]-20-|"]; [constraints addObject:@"H:|-20-[_leftButton(==_rightButton)]-20-[_rightButton(>=130)]-20-|"]; - + // PageControl. [self.pageControl setTranslatesAutoresizingMaskIntoConstraints:NO]; [constraints addObject:@"V:[_pageControl(==32)]-60-|"]; - [constraints addObject:@"H:|-140-[_pageControl(==40)]"]; - + // [constraints addObject:@"H:|[_pageControl(==40)]|"]; + + [self.view addConstraint: + [NSLayoutConstraint constraintWithItem:_pageControl + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; // GradientView. [self.gradientView setTranslatesAutoresizingMaskIntoConstraints:NO]; [constraints addObject:@"V:[_gradientView(==200)]-0-|"]; - [constraints addObject:@"H:|-0-[_gradientView(==320)]-0-|"]; + [constraints addObject:@"H:|-0-[_gradientView(>=320)]-0-|"]; // Set constraints. for (NSString *string in constraints) { @@ -173,7 +200,7 @@ - (IBAction)didClickOnButton2:(id)sender { - (IBAction)didClickOnPageControl:(UIPageControl *)sender { [self stopScrolling]; - + // Make the scrollView animation. [self scrollToNextPageIndex:sender.currentPage]; } @@ -228,7 +255,7 @@ - (void)animateScrolling { // Call the next animation after X seconds. - (void)autoScrollToNextPage { ICETutorialPage *page = self.pages[self.currentPageIndex]; - + if (self.autoScrollEnabled) { [self performSelector:@selector(animateScrolling) withObject:nil @@ -240,7 +267,7 @@ - (void)scrollToNextPageIndex:(NSUInteger)nextPageIndex { // Make the scrollView animation. [self.scrollView setContentOffset:CGPointMake(nextPageIndex * self.view.frame.size.width,0) animated:YES]; - + // Set the PageControl on the right page. [self.pageControl setCurrentPage:nextPageIndex]; } @@ -266,12 +293,12 @@ - (ScrollingState)getCurrentState { // Setup the Title Label. - (void)setOverlayTitle { // ...or change by an UIImageView if you need it. - [self.overlayTitle setText:@"Welcome"]; + [self.overlayTitle setText:NSLocalizedString(@"Welcome", nil)]; } // Setup the Title/Subtitle style/text. - (void)setOverlayTexts { - int index = 0; + int index = 0; for (ICETutorialPage *page in self.pages) { // SubTitles. if ([[[page title] text] length]) { @@ -294,21 +321,21 @@ - (void)overlayLabelWithStyle:(ICETutorialLabelStyle *)style commonStyle:(ICETutorialLabelStyle *)commonStyle index:(NSUInteger)index { // SubTitles. - UILabel *overlayLabel = [[UILabel alloc] initWithFrame:CGRectMake((index * self.view.frame.size.width), + UILabel *overlayLabel = [[UILabel alloc] initWithFrame:CGRectMake((index * self.view.frame.size.width) + 10, self.view.frame.size.height - [commonStyle offset], - self.view.frame.size.width, - TUTORIAL_LABEL_HEIGHT)]; + self.view.frame.size.width - 20, + TUTORIAL_LABEL_HEIGHT + 10)]; [overlayLabel setNumberOfLines:[commonStyle linesNumber]]; [overlayLabel setBackgroundColor:[UIColor clearColor]]; - [overlayLabel setTextAlignment:NSTextAlignmentCenter]; - + [overlayLabel setTextAlignment:NSTextAlignmentCenter]; + // Datas and style. [overlayLabel setText:[style text]]; [style font] ? [overlayLabel setFont:[style font]] : - [overlayLabel setFont:[commonStyle font]]; + [overlayLabel setFont:[commonStyle font]]; [style textColor] ? [overlayLabel setTextColor:[style textColor]] : - [overlayLabel setTextColor:[commonStyle textColor]]; - + [overlayLabel setTextColor:[commonStyle textColor]]; + [self.scrollView addSubview:overlayLabel]; } @@ -328,7 +355,7 @@ - (void)setBackgroundImage:(UIImageView *)imageView withIndex:(NSInteger)index { if (index >= [self.pages count]) { [imageView setImage:nil]; return; - } + } [imageView setImage:[UIImage imageNamed:[self.pages[index] pictureName]]]; } @@ -405,7 +432,7 @@ - (void)scrollingToNextPageWithOffset:(float)offset { // Switch pictures, and imageView alpha. if (nextPage != self.currentPageIndex || - ((nextPage == self.currentPageIndex) && (0.0 < offset) && (offset < 1.0))) + ((nextPage == self.currentPageIndex) && (0.0 < offset) && (offset < 1.0))) [self setLayersPicturesWithIndex:nextPage]; // Invert alpha for the front picture. @@ -443,7 +470,7 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { [self.delegate tutorialControllerDidReachLastPage:self]; } } - + // Animate. [self disolveBackgroundWithContentOffset:scrollingPosition]; } diff --git a/ICETutorial/Libraries/ICETutorialPage.h b/Demo-Swift/Libraries/ICETutorialPage.h similarity index 100% rename from ICETutorial/Libraries/ICETutorialPage.h rename to Demo-Swift/Libraries/ICETutorialPage.h diff --git a/ICETutorial/Libraries/ICETutorialPage.m b/Demo-Swift/Libraries/ICETutorialPage.m similarity index 100% rename from ICETutorial/Libraries/ICETutorialPage.m rename to Demo-Swift/Libraries/ICETutorialPage.m diff --git a/ICETutorial/Libraries/ICETutorialStyle.h b/Demo-Swift/Libraries/ICETutorialStyle.h similarity index 100% rename from ICETutorial/Libraries/ICETutorialStyle.h rename to Demo-Swift/Libraries/ICETutorialStyle.h diff --git a/ICETutorial/Libraries/ICETutorialStyle.m b/Demo-Swift/Libraries/ICETutorialStyle.m similarity index 100% rename from ICETutorial/Libraries/ICETutorialStyle.m rename to Demo-Swift/Libraries/ICETutorialStyle.m diff --git a/ICETutorial.podspec b/Demo/ICETutorial.podspec similarity index 100% rename from ICETutorial.podspec rename to Demo/ICETutorial.podspec diff --git a/ICETutorial.xcodeproj/project.pbxproj b/Demo/ICETutorial.xcodeproj/project.pbxproj similarity index 100% rename from ICETutorial.xcodeproj/project.pbxproj rename to Demo/ICETutorial.xcodeproj/project.pbxproj diff --git a/Demo/ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Demo/ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100755 index 0000000..d502c37 --- /dev/null +++ b/Demo/ICETutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/xcschememanagement.plist b/Demo/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/xcschememanagement.plist similarity index 100% rename from ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/xcschememanagement.plist rename to Demo/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/xcschememanagement.plist b/Demo/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/xcschememanagement.plist similarity index 100% rename from ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/xcschememanagement.plist rename to Demo/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcschemes/xcschememanagement.plist b/Demo/ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcschemes/xcschememanagement.plist similarity index 100% rename from ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcschemes/xcschememanagement.plist rename to Demo/ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/ICETutorial/AppDelegate.h b/Demo/ICETutorial/AppDelegate.h similarity index 100% rename from ICETutorial/AppDelegate.h rename to Demo/ICETutorial/AppDelegate.h diff --git a/ICETutorial/AppDelegate.m b/Demo/ICETutorial/AppDelegate.m similarity index 100% rename from ICETutorial/AppDelegate.m rename to Demo/ICETutorial/AppDelegate.m diff --git a/ICETutorial/ICETutorial-Info.plist b/Demo/ICETutorial/ICETutorial-Info.plist similarity index 100% rename from ICETutorial/ICETutorial-Info.plist rename to Demo/ICETutorial/ICETutorial-Info.plist diff --git a/ICETutorial/ICETutorial-Prefix.pch b/Demo/ICETutorial/ICETutorial-Prefix.pch similarity index 100% rename from ICETutorial/ICETutorial-Prefix.pch rename to Demo/ICETutorial/ICETutorial-Prefix.pch diff --git a/Demo/ICETutorial/Libraries/ICETutorialController.h b/Demo/ICETutorial/Libraries/ICETutorialController.h new file mode 100755 index 0000000..f99ecd7 --- /dev/null +++ b/Demo/ICETutorial/Libraries/ICETutorialController.h @@ -0,0 +1,64 @@ +// +// ICETutorialController.h +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +@import UIKit; +#import "ICETutorialPage.h" +#import "ICETutorialStyle.h" + +#define TUTORIAL_LABEL_TEXT_COLOR [UIColor whiteColor] +#define TUTORIAL_LABEL_HEIGHT 45 +#define TUTORIAL_TITLE_FONT [UIFont fontWithName:@"Helvetica-Bold" size:17.0f] +#define TUTORIAL_TITLE_LINES_NUMBER 1 +#define TUTORIAL_TITLE_OFFSET 180 +#define TUTORIAL_SUB_TITLE_FONT [UIFont fontWithName:@"Helvetica" size:15.0f] +#define TUTORIAL_SUB_TITLE_LINES_NUMBER 3 +#define TUTORIAL_SUB_TITLE_OFFSET 150 + +// Scrolling state. +typedef NS_OPTIONS(NSUInteger, ScrollingState) { + ScrollingStateAuto = 1 << 0, + ScrollingStateManual = 1 << 1, + ScrollingStateLooping = 1 << 2, +}; + +typedef void (^ButtonBlock)(UIButton *button); + +@protocol ICETutorialControllerDelegate; +@interface ICETutorialController : UIViewController + +@property (nonatomic, assign) BOOL autoScrollEnabled; +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign) NSInteger currentPageIndex; + +// Inits. +- (instancetype)initWithPages:(NSArray *)pages; +- (instancetype)initWithPages:(NSArray *)pages + delegate:(id)delegate; + +// Pages management. +- (void)setPages:(NSArray*)pages; +- (NSUInteger)numberOfPages; + +// Scrolling. +- (void)startScrolling; +- (void)stopScrolling; + +// State. +- (ScrollingState)getCurrentState; +- (void)scrollToNextPageIndex:(NSUInteger)nextPageIndex; + +@end + +@protocol ICETutorialControllerDelegate + +@optional +- (void)tutorialController:(ICETutorialController *)tutorialController scrollingFromPageIndex:(NSUInteger)fromIndex toPageIndex:(NSUInteger)toIndex; +- (void)tutorialControllerDidReachLastPage:(ICETutorialController *)tutorialController; +- (void)tutorialController:(ICETutorialController *)tutorialController didClickOnLeftButton:(UIButton *)sender; +- (void)tutorialController:(ICETutorialController *)tutorialController didClickOnRightButton:(UIButton *)sender; +@end diff --git a/Demo/ICETutorial/Libraries/ICETutorialController.m b/Demo/ICETutorial/Libraries/ICETutorialController.m new file mode 100755 index 0000000..5a730fb --- /dev/null +++ b/Demo/ICETutorial/Libraries/ICETutorialController.m @@ -0,0 +1,490 @@ +// +// ICETutorialController.m +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +#import "ICETutorialController.h" + +@interface ICETutorialController () +@property (nonatomic, strong, readonly) UIImageView *frontLayerView; +@property (nonatomic, strong, readonly) UIImageView *backLayerView; +@property (nonatomic, strong, readonly) UIImageView *gradientView; +@property (nonatomic, strong, readonly) UIScrollView *scrollView; +@property (nonatomic, strong, readonly) UILabel *overlayTitle; +@property (nonatomic, strong, readonly) UIPageControl *pageControl; +@property (nonatomic, strong, readonly) UIButton *leftButton; +@property (nonatomic, strong, readonly) UIButton *rightButton; + +@property (nonatomic, assign) ScrollingState currentState; +@property (nonatomic, strong) NSArray *pages; +@property (nonatomic, assign) NSInteger nextPageIndex; + +@end + +@implementation ICETutorialController + +- (instancetype)initWithPages:(NSArray *)pages { + self = [self init]; + if (self) { + _autoScrollEnabled = YES; + _pages = pages; + + _frontLayerView = [[UIImageView alloc] init]; + _backLayerView = [[UIImageView alloc] init]; + _gradientView = [[UIImageView alloc] init]; + _scrollView = [[UIScrollView alloc] init]; + + _overlayTitle = [[UILabel alloc] init]; + _pageControl = [[UIPageControl alloc] init]; + _leftButton = [[UIButton alloc] init]; + _rightButton = [[UIButton alloc] init]; + } + return self; +} + +- (instancetype)initWithPages:(NSArray *)pages + delegate:(id)delegate { + self = [self initWithPages:pages]; + if (self) { + _delegate = delegate; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self.view setBackgroundColor:[UIColor blackColor]]; + + [self setupView]; + + // Overlays. + [self setOverlayTexts]; + [self setOverlayTitle]; + + // Preset the origin state. + [self setOriginLayersState]; +} + +- (void)setupView { + [self.frontLayerView setFrame:self.view.bounds]; + [self.backLayerView setFrame:self.view.bounds]; + + // Decoration. + [self.gradientView setImage:[UIImage imageNamed:@"background-gradient.png"]]; + + // ScrollView configuration. + [self.scrollView setFrame:self.view.bounds]; + [self.scrollView setDelegate:self]; + [self.scrollView setPagingEnabled:YES]; + [self.scrollView setContentSize:CGSizeMake([self numberOfPages] * self.view.frame.size.width, + self.scrollView.contentSize.height)]; + + // Title. + [self.overlayTitle setTextColor:[UIColor whiteColor]]; + [self.overlayTitle setFont:[UIFont fontWithName:@"Nexa Bold" size:32.0]]; + [self.overlayTitle setTextAlignment:NSTextAlignmentCenter]; + + // PageControl configuration. + [self.pageControl setNumberOfPages:[self numberOfPages]]; + [self.pageControl setCurrentPage:0]; + [self.pageControl addTarget:self + action:@selector(didClickOnPageControl:) + forControlEvents:UIControlEventValueChanged]; + + UIColor *customOrange = [UIColor colorWithRed:(244/255.0f) green:(138/255.0f) blue:(103/255.0f) alpha:1.0]; + + // UIButtons. + [self.leftButton setBackgroundColor:customOrange]; + [self.leftButton.layer setCornerRadius:6.0]; + [self.leftButton setContentVerticalAlignment:UIControlContentVerticalAlignmentFill]; + [self.leftButton setTitle:NSLocalizedString(@"Next", nil) forState:UIControlStateNormal]; + [self.leftButton setShowsTouchWhenHighlighted:YES]; + [self.leftButton.titleLabel setFont:[UIFont fontWithName:@"Nexa Light" size:17.0]]; + [self.leftButton addTarget:self + action:@selector(didClickOnButton1:) + forControlEvents:UIControlEventTouchUpInside]; + + [self.rightButton setBackgroundColor:customOrange]; + [self.rightButton.layer setCornerRadius:6.0]; + [self.rightButton setContentVerticalAlignment:UIControlContentVerticalAlignmentFill]; + [self.rightButton setTitle:NSLocalizedString(@"LoginViewController_btnLogin", nil) forState:UIControlStateNormal]; + [self.rightButton setShowsTouchWhenHighlighted:YES]; + [self.rightButton.titleLabel setFont:[UIFont fontWithName:@"Nexa Light" size:17.0]]; + [self.rightButton addTarget:self + action:@selector(didClickOnButton2:) + forControlEvents:UIControlEventTouchUpInside]; + + [self.view addSubview:self.frontLayerView]; + [self.view addSubview:self.backLayerView]; + [self.view addSubview:self.gradientView]; + [self.view addSubview:self.scrollView]; + [self.view addSubview:self.overlayTitle]; + [self.view addSubview:self.pageControl]; + [self.view addSubview:self.leftButton]; + [self.view addSubview:self.rightButton]; + + [self addAllConstraints]; +} + +#pragma mark - Constraints management. +- (void)addAllConstraints { + [self.frontLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; + [self.backLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_overlayTitle, _leftButton, _rightButton, _pageControl, _gradientView); + NSMutableArray *constraints = [NSMutableArray array]; + + // Overlay title. + [self.overlayTitle setTranslatesAutoresizingMaskIntoConstraints:NO]; + [constraints addObject:@"V:|-85-[_overlayTitle(==50)]"]; + // [constraints addObject:@"H:|-0-[_overlayTitle(>=212)]-0-|"]; + + [self.view addConstraint: + [NSLayoutConstraint constraintWithItem:_overlayTitle + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + + // Buttons. + [self.leftButton setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self.rightButton setTranslatesAutoresizingMaskIntoConstraints:NO]; + [constraints addObject:@"V:[_leftButton(==36)]-20-|"]; + [constraints addObject:@"V:[_rightButton(==36)]-20-|"]; + [constraints addObject:@"H:|-20-[_leftButton(==_rightButton)]-20-[_rightButton(>=130)]-20-|"]; + + // PageControl. + [self.pageControl setTranslatesAutoresizingMaskIntoConstraints:NO]; + [constraints addObject:@"V:[_pageControl(==32)]-60-|"]; + // [constraints addObject:@"H:|[_pageControl(==40)]|"]; + + [self.view addConstraint: + [NSLayoutConstraint constraintWithItem:_pageControl + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + // GradientView. + [self.gradientView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [constraints addObject:@"V:[_gradientView(==200)]-0-|"]; + [constraints addObject:@"H:|-0-[_gradientView(>=320)]-0-|"]; + + // Set constraints. + for (NSString *string in constraints) { + [self.view addConstraints:[NSLayoutConstraint + constraintsWithVisualFormat:string + options:0 metrics:nil + views:views]]; + } +} + +#pragma mark - Actions +- (IBAction)didClickOnButton1:(id)sender { + if ([self.delegate respondsToSelector:@selector(tutorialController:didClickOnLeftButton:)]) { + [self.delegate tutorialController:self didClickOnLeftButton:sender]; + } +} + +- (IBAction)didClickOnButton2:(id)sender { + if ([self.delegate respondsToSelector:@selector(tutorialController:didClickOnRightButton:)]) { + [self.delegate tutorialController:self didClickOnRightButton:sender]; + } +} + +- (IBAction)didClickOnPageControl:(UIPageControl *)sender { + [self stopScrolling]; + + // Make the scrollView animation. + [self scrollToNextPageIndex:sender.currentPage]; +} + +#pragma mark - Pages +// Set the list of pages (ICETutorialPage). +- (void)setPages:(NSArray *)pages { + _pages = pages; +} + +- (NSUInteger)numberOfPages { + if (self.pages) { + return [self.pages count]; + } + + return 0; +} + +#pragma mark - Animations +- (void)animateScrolling { + if (self.currentState & ScrollingStateManual) { + return; + } + + // Jump to the next page... + NSInteger nextPage = self.currentPageIndex + 1; + if (nextPage == [self numberOfPages]) { + // ...stop the auto-scrolling or... + if (!self.autoScrollEnabled) { + self.currentState = ScrollingStateManual; + return; + } + + // ...jump to the first page. + nextPage = 0; + self.currentState = ScrollingStateLooping; + + // Set alpha on layers. + [self setOriginLayerAlpha]; + [self setBackLayerPictureWithPageIndex:-1]; + } else { + self.currentState = ScrollingStateAuto; + } + + // Make the scrollView animation. + [self scrollToNextPageIndex:nextPage]; + + // Call the next animation after X seconds. + [self autoScrollToNextPage]; +} + +// Call the next animation after X seconds. +- (void)autoScrollToNextPage { + ICETutorialPage *page = self.pages[self.currentPageIndex]; + + if (self.autoScrollEnabled) { + [self performSelector:@selector(animateScrolling) + withObject:nil + afterDelay:page.duration]; + } +} + +- (void)scrollToNextPageIndex:(NSUInteger)nextPageIndex { + // Make the scrollView animation. + [self.scrollView setContentOffset:CGPointMake(nextPageIndex * self.view.frame.size.width,0) + animated:YES]; + + // Set the PageControl on the right page. + [self.pageControl setCurrentPage:nextPageIndex]; +} + +#pragma mark - Scrolling management +// Run it. +- (void)startScrolling { + [self autoScrollToNextPage]; +} + +// Manually stop the scrolling +- (void)stopScrolling { + self.currentState = ScrollingStateManual; +} + +#pragma mark - State management +// State. +- (ScrollingState)getCurrentState { + return self.currentState; +} + +#pragma mark - Overlay management +// Setup the Title Label. +- (void)setOverlayTitle { + // ...or change by an UIImageView if you need it. + [self.overlayTitle setText:NSLocalizedString(@"Welcome", nil)]; +} + +// Setup the Title/Subtitle style/text. +- (void)setOverlayTexts { + int index = 0; + for (ICETutorialPage *page in self.pages) { + // SubTitles. + if ([[[page title] text] length]) { + [self overlayLabelWithStyle:[page title] + commonStyle:[[ICETutorialStyle sharedInstance] titleStyle] + index:index]; + } + // Description. + if ([[[page subTitle] text] length]) { + [self overlayLabelWithStyle:[page subTitle] + commonStyle:[[ICETutorialStyle sharedInstance] subTitleStyle] + index:index]; + } + + index++; + } +} + +- (void)overlayLabelWithStyle:(ICETutorialLabelStyle *)style + commonStyle:(ICETutorialLabelStyle *)commonStyle + index:(NSUInteger)index { + // SubTitles. + UILabel *overlayLabel = [[UILabel alloc] initWithFrame:CGRectMake((index * self.view.frame.size.width) + 10, + self.view.frame.size.height - [commonStyle offset], + self.view.frame.size.width - 20, + TUTORIAL_LABEL_HEIGHT + 10)]; + [overlayLabel setNumberOfLines:[commonStyle linesNumber]]; + [overlayLabel setBackgroundColor:[UIColor clearColor]]; + [overlayLabel setTextAlignment:NSTextAlignmentCenter]; + + // Datas and style. + [overlayLabel setText:[style text]]; + [style font] ? [overlayLabel setFont:[style font]] : + [overlayLabel setFont:[commonStyle font]]; + [style textColor] ? [overlayLabel setTextColor:[style textColor]] : + [overlayLabel setTextColor:[commonStyle textColor]]; + + [self.scrollView addSubview:overlayLabel]; +} + +#pragma mark - Layers management +// Handle the background layer image switch. +- (void)setBackLayerPictureWithPageIndex:(NSInteger)index { + [self setBackgroundImage:self.backLayerView withIndex:index + 1]; +} + +// Handle the front layer image switch. +- (void)setFrontLayerPictureWithPageIndex:(NSInteger)index { + [self setBackgroundImage:self.frontLayerView withIndex:index]; +} + +// Handle page image's loading +- (void)setBackgroundImage:(UIImageView *)imageView withIndex:(NSInteger)index { + if (index >= [self.pages count]) { + [imageView setImage:nil]; + return; + } + + [imageView setImage:[UIImage imageNamed:[self.pages[index] pictureName]]]; +} + +// Setup lapyer's alpha. +- (void)setOriginLayerAlpha { + [self.frontLayerView setAlpha:1]; + [self.backLayerView setAlpha:0]; +} + +// Preset the origin state. +- (void)setOriginLayersState { + self.currentState = ScrollingStateAuto; + [self.backLayerView setBackgroundColor:[UIColor blackColor]]; + [self.frontLayerView setBackgroundColor:[UIColor blackColor]]; + [self setLayersPicturesWithIndex:0]; +} + +// Setup the layers with the page index. +- (void)setLayersPicturesWithIndex:(NSInteger)index { + self.currentPageIndex = index; + [self setOriginLayerAlpha]; + [self setFrontLayerPictureWithPageIndex:index]; + [self setBackLayerPictureWithPageIndex:index]; +} + +// Animate the fade-in/out (Cross-disolve) with the scrollView translation. +- (void)disolveBackgroundWithContentOffset:(float)offset { + if (self.currentState & ScrollingStateLooping){ + // Jump from the last page to the first. + [self scrollingToFirstPageWithOffset:offset]; + } else { + // Or just scroll to the next/previous page. + [self scrollingToNextPageWithOffset:offset]; + } +} + +// Handle alpha on layers when the auto-scrolling is looping to the first page. +- (void)scrollingToFirstPageWithOffset:(float)offset { + // Compute the scrolling percentage on all the page. + offset = (offset * self.view.frame.size.width) / (self.view.frame.size.width * [self numberOfPages]); + + // Scrolling finished... + if (!offset){ + // ...reset to the origin state. + [self setOriginLayersState]; + return; + } + + // Invert alpha for the back picture. + float backLayerAlpha = (1 - offset); + float frontLayerAlpha = offset; + + // Set alpha. + [self.backLayerView setAlpha:backLayerAlpha]; + [self.frontLayerView setAlpha:frontLayerAlpha]; +} + +// Handle alpha on layers when we are scrolling to the next/previous page. +- (void)scrollingToNextPageWithOffset:(float)offset { + // Current page index in scrolling. + NSInteger nextPage = (int)offset; + + // Keep only the float value. + float alphaValue = offset - nextPage; + + // This is only when you scroll to the right on the first page. + // That will fade-in black the first picture. + if (alphaValue < 0 && self.currentPageIndex == 0){ + [self.backLayerView setImage:nil]; + [self.frontLayerView setAlpha:(1 + alphaValue)]; + return; + } + + // Switch pictures, and imageView alpha. + if (nextPage != self.currentPageIndex || + ((nextPage == self.currentPageIndex) && (0.0 < offset) && (offset < 1.0))) + [self setLayersPicturesWithIndex:nextPage]; + + // Invert alpha for the front picture. + float backLayerAlpha = alphaValue; + float frontLayerAlpha = (1 - alphaValue); + + // Set alpha. + [self.backLayerView setAlpha:backLayerAlpha]; + [self.frontLayerView setAlpha:frontLayerAlpha]; +} + +#pragma mark - ScrollView delegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + // Get scrolling position, and nextPageindex. + float scrollingPosition = scrollView.contentOffset.x / self.view.frame.size.width; + int nextPageIndex = (int)scrollingPosition; + + // If we are looping, we reset the indexPage. + if (self.currentState & ScrollingStateLooping) { + nextPageIndex = 0; + } + + // If we are going to the next page, let's call the delegate. + if (nextPageIndex != self.nextPageIndex) { + if ([self.delegate respondsToSelector:@selector(tutorialController:scrollingFromPageIndex:toPageIndex:)]) { + [self.delegate tutorialController:self scrollingFromPageIndex:self.currentPageIndex toPageIndex:nextPageIndex]; + } + + self.nextPageIndex = nextPageIndex; + } + + // Delegate when we reach the end. + if (self.nextPageIndex == [self numberOfPages] - 1) { + if ([self.delegate respondsToSelector:@selector(tutorialControllerDidReachLastPage:)]) { + [self.delegate tutorialControllerDidReachLastPage:self]; + } + } + + // Animate. + [self disolveBackgroundWithContentOffset:scrollingPosition]; +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + // At the first user interaction, we disable the auto scrolling. + if (self.scrollView.isTracking) { + [self stopScrolling]; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + // Update the page index. + [self.pageControl setCurrentPage:self.currentPageIndex]; +} + +@end diff --git a/Demo/ICETutorial/Libraries/ICETutorialPage.h b/Demo/ICETutorial/Libraries/ICETutorialPage.h new file mode 100755 index 0000000..656bd25 --- /dev/null +++ b/Demo/ICETutorial/Libraries/ICETutorialPage.h @@ -0,0 +1,45 @@ +// +// ICETutorialPage.h +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +@import Foundation; +@import UIKit; + +@interface ICETutorialLabelStyle : NSObject + +@property (nonatomic, retain) NSString *text; +@property (nonatomic, retain) UIFont *font; +@property (nonatomic, retain) UIColor *textColor; +@property (nonatomic, assign) NSUInteger linesNumber; +@property (nonatomic, assign) NSUInteger offset; + +// Init. +- (instancetype)initWithText:(NSString *)text; +- (instancetype)initWithFont:(UIFont *)font + textColor:(UIColor *)color + linesNumber:(NSUInteger)linesNumber + offset:(NSUInteger)offset; +@end + +@interface ICETutorialPage : NSObject + +@property (nonatomic, retain) ICETutorialLabelStyle *title; +@property (nonatomic, retain) ICETutorialLabelStyle *subTitle; +@property (nonatomic, retain) NSString *pictureName; +@property (nonatomic, assign) NSTimeInterval duration; + +// Init. +- (instancetype)initWithTitle:(NSString *)title + subTitle:(NSString *)subTitle + pictureName:(NSString *)pictureName + duration:(NSTimeInterval)duration; + +- (void)setTitleStyle:(ICETutorialLabelStyle *)style; +- (void)setSubTitleStyle:(ICETutorialLabelStyle *)style; + +@end + diff --git a/Demo/ICETutorial/Libraries/ICETutorialPage.m b/Demo/ICETutorial/Libraries/ICETutorialPage.m new file mode 100755 index 0000000..ae1c001 --- /dev/null +++ b/Demo/ICETutorial/Libraries/ICETutorialPage.m @@ -0,0 +1,65 @@ +// +// ICETutorialPage.m +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +#import "ICETutorialPage.h" + +@implementation ICETutorialLabelStyle + +// Init. +- (instancetype)initWithText:(NSString *)text { + self = [super init]; + if (self){ + _text = text; + } + return self; +} + +- (instancetype)initWithFont:(UIFont *)font + textColor:(UIColor *)color + linesNumber:(NSUInteger)linesNumber + offset:(NSUInteger)offset { + self = [self init]; + if (self){ + _font = font; + _textColor = color; + _linesNumber = linesNumber; + _offset = offset; + } + return self; +} + +@end + +@implementation ICETutorialPage + +// Init. +- (instancetype)initWithTitle:(NSString *)title + subTitle:(NSString *)subTitle + pictureName:(NSString *)pictureName + duration:(NSTimeInterval)duration { + self = [super init]; + if (self){ + _title = [[ICETutorialLabelStyle alloc] initWithText:title]; + _subTitle = [[ICETutorialLabelStyle alloc] initWithText:subTitle]; + _pictureName = pictureName; + _duration = duration; + } + return self; +} + +- (void)setTitleStyle:(ICETutorialLabelStyle *)style { + [self.title setFont:style.font]; + [self.title setTextColor:style.textColor]; +} + +- (void)setSubTitleStyle:(ICETutorialLabelStyle *)style { + [self.subTitle setFont:style.font]; + [self.subTitle setTextColor:style.textColor]; +} + +@end diff --git a/Demo/ICETutorial/Libraries/ICETutorialStyle.h b/Demo/ICETutorial/Libraries/ICETutorialStyle.h new file mode 100644 index 0000000..0124455 --- /dev/null +++ b/Demo/ICETutorial/Libraries/ICETutorialStyle.h @@ -0,0 +1,28 @@ +// +// ICETutorialStyle.h +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +@import Foundation; +#import "ICETutorialPage.h" + +@interface ICETutorialStyle : NSObject + +@property (nonatomic, strong) UIFont *titleFont; +@property (nonatomic, strong) UIColor *titleColor; +@property (nonatomic, assign) NSUInteger titleLinesNumber; +@property (nonatomic, assign) NSUInteger titleOffset; +@property (nonatomic, strong) UIFont *subTitleFont; +@property (nonatomic, strong) UIColor *subTitleColor; +@property (nonatomic, assign) NSUInteger subTitleLinesNumber; +@property (nonatomic, assign) NSUInteger subTitleOffset; + +@property (nonatomic, strong) ICETutorialLabelStyle *titleStyle; +@property (nonatomic, strong) ICETutorialLabelStyle *subTitleStyle; + ++ (instancetype)sharedInstance; + +@end diff --git a/Demo/ICETutorial/Libraries/ICETutorialStyle.m b/Demo/ICETutorial/Libraries/ICETutorialStyle.m new file mode 100644 index 0000000..586a975 --- /dev/null +++ b/Demo/ICETutorial/Libraries/ICETutorialStyle.m @@ -0,0 +1,103 @@ +// +// ICETutorialStyle.m +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +#import "ICETutorialStyle.h" +#import "ICETutorialController.h" + +@implementation ICETutorialStyle + ++ (instancetype)sharedInstance { + static ICETutorialStyle *sharedInstance = nil; + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + sharedInstance = [[ICETutorialStyle alloc] init]; + }); + return sharedInstance; +} + +#pragma mark - Properties +- (UIFont *)titleFont { + if (_titleFont) { + return _titleFont; + } + return TUTORIAL_TITLE_FONT; +} + +- (UIColor *)titleColor { + if (_titleColor) { + return _titleColor; + } + return TUTORIAL_LABEL_TEXT_COLOR; +} + +- (NSUInteger)titleLinesNumber { + if (_titleLinesNumber != NSNotFound) { + return _titleLinesNumber; + } + return TUTORIAL_TITLE_LINES_NUMBER; +} + +- (NSUInteger)titleOffset { + if (_titleOffset != NSNotFound) { + return _titleOffset; + } + return TUTORIAL_TITLE_OFFSET; +} + +- (UIFont *)subTitleFont { + if (_subTitleFont) { + return _subTitleFont; + } + return TUTORIAL_SUB_TITLE_FONT; +} + +- (UIColor *)subTitleColor { + if (_subTitleColor) { + return _subTitleColor; + } + return TUTORIAL_LABEL_TEXT_COLOR; +} + +- (NSUInteger)subTitleLinesNumber { + if (_titleLinesNumber != NSNotFound) { + return _titleLinesNumber; + } + return TUTORIAL_SUB_TITLE_LINES_NUMBER; +} + +- (NSUInteger)subTitleOffset { + if (_subTitleOffset != NSNotFound) { + return _subTitleOffset; + } + return TUTORIAL_SUB_TITLE_OFFSET; +} + +#pragma mark - Styles +- (ICETutorialLabelStyle *)titleStyle { + if (_titleStyle) { + return _titleStyle; + } + + return [[ICETutorialLabelStyle alloc] initWithFont:self.titleFont + textColor:self.titleColor + linesNumber:self.titleLinesNumber + offset:self.titleOffset]; +} + +- (ICETutorialLabelStyle *)subTitleStyle { + if (_subTitleStyle) { + return _subTitleStyle; + } + + return [[ICETutorialLabelStyle alloc] initWithFont:self.subTitleFont + textColor:self.subTitleColor + linesNumber:self.subTitleLinesNumber + offset:self.subTitleOffset]; +} + +@end diff --git a/ICETutorial/en.lproj/InfoPlist.strings b/Demo/ICETutorial/en.lproj/InfoPlist.strings similarity index 100% rename from ICETutorial/en.lproj/InfoPlist.strings rename to Demo/ICETutorial/en.lproj/InfoPlist.strings diff --git a/ICETutorial/main.m b/Demo/ICETutorial/main.m similarity index 100% rename from ICETutorial/main.m rename to Demo/ICETutorial/main.m diff --git a/Demo/LICENSE b/Demo/LICENSE new file mode 100755 index 0000000..77cbbcf --- /dev/null +++ b/Demo/LICENSE @@ -0,0 +1,9 @@ +The MIT License + +Copyright (c) 2013 Patrick Trillsam - ICETutorial + +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: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +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. \ No newline at end of file diff --git a/Podfile b/Demo/Podfile similarity index 100% rename from Podfile rename to Demo/Podfile diff --git a/Demo/README.md b/Demo/README.md new file mode 100755 index 0000000..b5fc26d --- /dev/null +++ b/Demo/README.md @@ -0,0 +1,114 @@ +ICETutorial +=========== + +### Welcome to ICETutorial. +This small project is an implementation of the newly tutorial introduced by the Path 3.X app. +Very simple and efficient tutorial, composed with N full-screen pictures that you can swipe for switching to the next/previous page. + +Here are the features : +* Compose your own tutorial with N pictures +* Fixed incrusted title (can be easily replaced by an UIImageView, or just removed) +* Scrolling sub-titles for page, with associated descriptions (change the texts, font, color...) +* Auto-scrolling (enable/disable, loop, setup duration) +* Cross fade between next/previous background +* Easy to use block access to button's events. + +![ICETutorial](https://github.com/icepat/ICETutorial/blob/master/screen_shot.jpg?raw=true) + +### Installation + +With [CocoaPods](http://cocoapods.org/), add this line to your Podfile. + + pod 'ICETutorial', '~> 1.1.1' + +Or add the files manually into your project. + +### Setting-up the ICETutorial +The code is commented, and I guess, easy to read/understand/modify. +All the available settings for the scrolling are located in the header : ICETutorial.h : + +**Texts and pictures :** +```objective-c + // Init the pages texts, and pictures. + ICETutorialPage *layer1 = [[ICETutorialPage alloc] initWithSubTitle:@"Picture 1" + description:@"Champs-Elysées by night" + pictureName:@"tutorial_background_00@2x.jpg"]; + ICETutorialPage *layer2 = [[ICETutorialPage alloc] initWithSubTitle:@"Picture 2" + description:@"The Eiffel Tower with\n cloudy weather" + pictureName:@"tutorial_background_01@2x.jpg"]; + [...] +``` + +**Common styles for SubTitles and Descriptions :** +```objective-c + // Set the common style for SubTitles and Description (can be overrided on each page). + ICETutorialLabelStyle *subStyle = [[ICETutorialLabelStyle alloc] init]; + [subStyle setFont:TUTORIAL_SUB_TITLE_FONT]; + [subStyle setTextColor:TUTORIAL_LABEL_TEXT_COLOR]; + [subStyle setLinesNumber:TUTORIAL_SUB_TITLE_LINES_NUMBER]; + [subStyle setOffset:TUTORIAL_SUB_TITLE_OFFSET]; + + ICETutorialLabelStyle *descStyle = [[ICETutorialLabelStyle alloc] init]; + [descStyle setFont:TUTORIAL_DESC_FONT]; + [descStyle setTextColor:TUTORIAL_LABEL_TEXT_COLOR]; + [descStyle setLinesNumber:TUTORIAL_DESC_LINES_NUMBER]; + [descStyle setOffset:TUTORIAL_DESC_OFFSET]; + + // Load into an array. + NSArray *tutorialLayers = @[layer1,layer2,layer3,layer4,layer5]; + +``` + +**Init and load :** +```objective-c + self.viewController = [[ICETutorialController alloc] initWithNibName:@"ICETutorialController_iPhone" + bundle:nil + andPages:tutorialLayers]; + + // Set the common styles, and start scrolling (auto scroll, and looping enabled by default) + [self.viewController setCommonPageSubTitleStyle:subStyle]; + [self.viewController setCommonPageDescriptionStyle:descStyle]; + + // Set button 1 action. + [self.viewController setButton1Block:^(UIButton *button){ + NSLog(@"Button 1 pressed."); + }]; + + // Set button 2 action, stop the scrolling. + __unsafe_unretained typeof(self) weakSelf = self; + [self.viewController setButton2Block:^(UIButton *button){ + NSLog(@"Button 2 pressed."); + NSLog(@"Auto-scrolling stopped."); + + [weakSelf.viewController stopScrolling]; + }]; + + // Run it. + [self.viewController startScrolling]; +``` + +**The title is located in the ICETutorial.m :** +```objective-c +// Setup the Title Label. +- (void)setOverlayTitle{ + // ...or change by an UIImageView if you need it. + [_overlayTitle setText:@"Welcome"]; +} +``` + +Checkout the others projects available on my account [@Icepat](https://github.com/icepat/). + +Questions or ideas : patrick.trillsam@gmail.com. + + +###License : + +The MIT License + +Copyright (c) 2013 Patrick Trillsam - ICETutorial + +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: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +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. diff --git a/Resources/Default-568h@2x.png b/Demo/Resources/Default-568h@2x.png similarity index 100% rename from Resources/Default-568h@2x.png rename to Demo/Resources/Default-568h@2x.png diff --git a/Resources/Default.png b/Demo/Resources/Default.png similarity index 100% rename from Resources/Default.png rename to Demo/Resources/Default.png diff --git a/Resources/Default@2x.png b/Demo/Resources/Default@2x.png similarity index 100% rename from Resources/Default@2x.png rename to Demo/Resources/Default@2x.png diff --git a/Demo/Resources/background-gradient.png b/Demo/Resources/background-gradient.png new file mode 100755 index 0000000..b4dc7d6 Binary files /dev/null and b/Demo/Resources/background-gradient.png differ diff --git a/Demo/Resources/background-gradient@2x.png b/Demo/Resources/background-gradient@2x.png new file mode 100755 index 0000000..0cd727d Binary files /dev/null and b/Demo/Resources/background-gradient@2x.png differ diff --git a/Demo/Resources/button-background.png b/Demo/Resources/button-background.png new file mode 100755 index 0000000..a8286f2 Binary files /dev/null and b/Demo/Resources/button-background.png differ diff --git a/Demo/Resources/button-background@2x.png b/Demo/Resources/button-background@2x.png new file mode 100755 index 0000000..9d8b78a Binary files /dev/null and b/Demo/Resources/button-background@2x.png differ diff --git a/Demo/Resources/tutorial_background_00@2x.jpg b/Demo/Resources/tutorial_background_00@2x.jpg new file mode 100755 index 0000000..8e3ddfd Binary files /dev/null and b/Demo/Resources/tutorial_background_00@2x.jpg differ diff --git a/Demo/Resources/tutorial_background_01@2x.jpg b/Demo/Resources/tutorial_background_01@2x.jpg new file mode 100755 index 0000000..af7685d Binary files /dev/null and b/Demo/Resources/tutorial_background_01@2x.jpg differ diff --git a/Demo/Resources/tutorial_background_02@2x.jpg b/Demo/Resources/tutorial_background_02@2x.jpg new file mode 100755 index 0000000..163449c Binary files /dev/null and b/Demo/Resources/tutorial_background_02@2x.jpg differ diff --git a/Demo/Resources/tutorial_background_03@2x.jpg b/Demo/Resources/tutorial_background_03@2x.jpg new file mode 100755 index 0000000..96606c3 Binary files /dev/null and b/Demo/Resources/tutorial_background_03@2x.jpg differ diff --git a/Demo/Resources/tutorial_background_04@2x.jpg b/Demo/Resources/tutorial_background_04@2x.jpg new file mode 100755 index 0000000..b77ad03 Binary files /dev/null and b/Demo/Resources/tutorial_background_04@2x.jpg differ diff --git a/Demo/screen_shot.jpg b/Demo/screen_shot.jpg new file mode 100755 index 0000000..759e137 Binary files /dev/null and b/Demo/screen_shot.jpg differ diff --git a/ICETutorial-Library/ICETutorialController.h b/ICETutorial-Library/ICETutorialController.h new file mode 100755 index 0000000..f99ecd7 --- /dev/null +++ b/ICETutorial-Library/ICETutorialController.h @@ -0,0 +1,64 @@ +// +// ICETutorialController.h +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +@import UIKit; +#import "ICETutorialPage.h" +#import "ICETutorialStyle.h" + +#define TUTORIAL_LABEL_TEXT_COLOR [UIColor whiteColor] +#define TUTORIAL_LABEL_HEIGHT 45 +#define TUTORIAL_TITLE_FONT [UIFont fontWithName:@"Helvetica-Bold" size:17.0f] +#define TUTORIAL_TITLE_LINES_NUMBER 1 +#define TUTORIAL_TITLE_OFFSET 180 +#define TUTORIAL_SUB_TITLE_FONT [UIFont fontWithName:@"Helvetica" size:15.0f] +#define TUTORIAL_SUB_TITLE_LINES_NUMBER 3 +#define TUTORIAL_SUB_TITLE_OFFSET 150 + +// Scrolling state. +typedef NS_OPTIONS(NSUInteger, ScrollingState) { + ScrollingStateAuto = 1 << 0, + ScrollingStateManual = 1 << 1, + ScrollingStateLooping = 1 << 2, +}; + +typedef void (^ButtonBlock)(UIButton *button); + +@protocol ICETutorialControllerDelegate; +@interface ICETutorialController : UIViewController + +@property (nonatomic, assign) BOOL autoScrollEnabled; +@property (nonatomic, weak) id delegate; +@property (nonatomic, assign) NSInteger currentPageIndex; + +// Inits. +- (instancetype)initWithPages:(NSArray *)pages; +- (instancetype)initWithPages:(NSArray *)pages + delegate:(id)delegate; + +// Pages management. +- (void)setPages:(NSArray*)pages; +- (NSUInteger)numberOfPages; + +// Scrolling. +- (void)startScrolling; +- (void)stopScrolling; + +// State. +- (ScrollingState)getCurrentState; +- (void)scrollToNextPageIndex:(NSUInteger)nextPageIndex; + +@end + +@protocol ICETutorialControllerDelegate + +@optional +- (void)tutorialController:(ICETutorialController *)tutorialController scrollingFromPageIndex:(NSUInteger)fromIndex toPageIndex:(NSUInteger)toIndex; +- (void)tutorialControllerDidReachLastPage:(ICETutorialController *)tutorialController; +- (void)tutorialController:(ICETutorialController *)tutorialController didClickOnLeftButton:(UIButton *)sender; +- (void)tutorialController:(ICETutorialController *)tutorialController didClickOnRightButton:(UIButton *)sender; +@end diff --git a/ICETutorial-Library/ICETutorialController.m b/ICETutorial-Library/ICETutorialController.m new file mode 100755 index 0000000..5a730fb --- /dev/null +++ b/ICETutorial-Library/ICETutorialController.m @@ -0,0 +1,490 @@ +// +// ICETutorialController.m +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +#import "ICETutorialController.h" + +@interface ICETutorialController () +@property (nonatomic, strong, readonly) UIImageView *frontLayerView; +@property (nonatomic, strong, readonly) UIImageView *backLayerView; +@property (nonatomic, strong, readonly) UIImageView *gradientView; +@property (nonatomic, strong, readonly) UIScrollView *scrollView; +@property (nonatomic, strong, readonly) UILabel *overlayTitle; +@property (nonatomic, strong, readonly) UIPageControl *pageControl; +@property (nonatomic, strong, readonly) UIButton *leftButton; +@property (nonatomic, strong, readonly) UIButton *rightButton; + +@property (nonatomic, assign) ScrollingState currentState; +@property (nonatomic, strong) NSArray *pages; +@property (nonatomic, assign) NSInteger nextPageIndex; + +@end + +@implementation ICETutorialController + +- (instancetype)initWithPages:(NSArray *)pages { + self = [self init]; + if (self) { + _autoScrollEnabled = YES; + _pages = pages; + + _frontLayerView = [[UIImageView alloc] init]; + _backLayerView = [[UIImageView alloc] init]; + _gradientView = [[UIImageView alloc] init]; + _scrollView = [[UIScrollView alloc] init]; + + _overlayTitle = [[UILabel alloc] init]; + _pageControl = [[UIPageControl alloc] init]; + _leftButton = [[UIButton alloc] init]; + _rightButton = [[UIButton alloc] init]; + } + return self; +} + +- (instancetype)initWithPages:(NSArray *)pages + delegate:(id)delegate { + self = [self initWithPages:pages]; + if (self) { + _delegate = delegate; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + [self.view setBackgroundColor:[UIColor blackColor]]; + + [self setupView]; + + // Overlays. + [self setOverlayTexts]; + [self setOverlayTitle]; + + // Preset the origin state. + [self setOriginLayersState]; +} + +- (void)setupView { + [self.frontLayerView setFrame:self.view.bounds]; + [self.backLayerView setFrame:self.view.bounds]; + + // Decoration. + [self.gradientView setImage:[UIImage imageNamed:@"background-gradient.png"]]; + + // ScrollView configuration. + [self.scrollView setFrame:self.view.bounds]; + [self.scrollView setDelegate:self]; + [self.scrollView setPagingEnabled:YES]; + [self.scrollView setContentSize:CGSizeMake([self numberOfPages] * self.view.frame.size.width, + self.scrollView.contentSize.height)]; + + // Title. + [self.overlayTitle setTextColor:[UIColor whiteColor]]; + [self.overlayTitle setFont:[UIFont fontWithName:@"Nexa Bold" size:32.0]]; + [self.overlayTitle setTextAlignment:NSTextAlignmentCenter]; + + // PageControl configuration. + [self.pageControl setNumberOfPages:[self numberOfPages]]; + [self.pageControl setCurrentPage:0]; + [self.pageControl addTarget:self + action:@selector(didClickOnPageControl:) + forControlEvents:UIControlEventValueChanged]; + + UIColor *customOrange = [UIColor colorWithRed:(244/255.0f) green:(138/255.0f) blue:(103/255.0f) alpha:1.0]; + + // UIButtons. + [self.leftButton setBackgroundColor:customOrange]; + [self.leftButton.layer setCornerRadius:6.0]; + [self.leftButton setContentVerticalAlignment:UIControlContentVerticalAlignmentFill]; + [self.leftButton setTitle:NSLocalizedString(@"Next", nil) forState:UIControlStateNormal]; + [self.leftButton setShowsTouchWhenHighlighted:YES]; + [self.leftButton.titleLabel setFont:[UIFont fontWithName:@"Nexa Light" size:17.0]]; + [self.leftButton addTarget:self + action:@selector(didClickOnButton1:) + forControlEvents:UIControlEventTouchUpInside]; + + [self.rightButton setBackgroundColor:customOrange]; + [self.rightButton.layer setCornerRadius:6.0]; + [self.rightButton setContentVerticalAlignment:UIControlContentVerticalAlignmentFill]; + [self.rightButton setTitle:NSLocalizedString(@"LoginViewController_btnLogin", nil) forState:UIControlStateNormal]; + [self.rightButton setShowsTouchWhenHighlighted:YES]; + [self.rightButton.titleLabel setFont:[UIFont fontWithName:@"Nexa Light" size:17.0]]; + [self.rightButton addTarget:self + action:@selector(didClickOnButton2:) + forControlEvents:UIControlEventTouchUpInside]; + + [self.view addSubview:self.frontLayerView]; + [self.view addSubview:self.backLayerView]; + [self.view addSubview:self.gradientView]; + [self.view addSubview:self.scrollView]; + [self.view addSubview:self.overlayTitle]; + [self.view addSubview:self.pageControl]; + [self.view addSubview:self.leftButton]; + [self.view addSubview:self.rightButton]; + + [self addAllConstraints]; +} + +#pragma mark - Constraints management. +- (void)addAllConstraints { + [self.frontLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; + [self.backLayerView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight]; + + NSDictionary *views = NSDictionaryOfVariableBindings(_overlayTitle, _leftButton, _rightButton, _pageControl, _gradientView); + NSMutableArray *constraints = [NSMutableArray array]; + + // Overlay title. + [self.overlayTitle setTranslatesAutoresizingMaskIntoConstraints:NO]; + [constraints addObject:@"V:|-85-[_overlayTitle(==50)]"]; + // [constraints addObject:@"H:|-0-[_overlayTitle(>=212)]-0-|"]; + + [self.view addConstraint: + [NSLayoutConstraint constraintWithItem:_overlayTitle + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + + // Buttons. + [self.leftButton setTranslatesAutoresizingMaskIntoConstraints:NO]; + [self.rightButton setTranslatesAutoresizingMaskIntoConstraints:NO]; + [constraints addObject:@"V:[_leftButton(==36)]-20-|"]; + [constraints addObject:@"V:[_rightButton(==36)]-20-|"]; + [constraints addObject:@"H:|-20-[_leftButton(==_rightButton)]-20-[_rightButton(>=130)]-20-|"]; + + // PageControl. + [self.pageControl setTranslatesAutoresizingMaskIntoConstraints:NO]; + [constraints addObject:@"V:[_pageControl(==32)]-60-|"]; + // [constraints addObject:@"H:|[_pageControl(==40)]|"]; + + [self.view addConstraint: + [NSLayoutConstraint constraintWithItem:_pageControl + attribute:NSLayoutAttributeCenterX + relatedBy:NSLayoutRelationEqual + toItem:self.view + attribute:NSLayoutAttributeCenterX + multiplier:1 + constant:0]]; + // GradientView. + [self.gradientView setTranslatesAutoresizingMaskIntoConstraints:NO]; + [constraints addObject:@"V:[_gradientView(==200)]-0-|"]; + [constraints addObject:@"H:|-0-[_gradientView(>=320)]-0-|"]; + + // Set constraints. + for (NSString *string in constraints) { + [self.view addConstraints:[NSLayoutConstraint + constraintsWithVisualFormat:string + options:0 metrics:nil + views:views]]; + } +} + +#pragma mark - Actions +- (IBAction)didClickOnButton1:(id)sender { + if ([self.delegate respondsToSelector:@selector(tutorialController:didClickOnLeftButton:)]) { + [self.delegate tutorialController:self didClickOnLeftButton:sender]; + } +} + +- (IBAction)didClickOnButton2:(id)sender { + if ([self.delegate respondsToSelector:@selector(tutorialController:didClickOnRightButton:)]) { + [self.delegate tutorialController:self didClickOnRightButton:sender]; + } +} + +- (IBAction)didClickOnPageControl:(UIPageControl *)sender { + [self stopScrolling]; + + // Make the scrollView animation. + [self scrollToNextPageIndex:sender.currentPage]; +} + +#pragma mark - Pages +// Set the list of pages (ICETutorialPage). +- (void)setPages:(NSArray *)pages { + _pages = pages; +} + +- (NSUInteger)numberOfPages { + if (self.pages) { + return [self.pages count]; + } + + return 0; +} + +#pragma mark - Animations +- (void)animateScrolling { + if (self.currentState & ScrollingStateManual) { + return; + } + + // Jump to the next page... + NSInteger nextPage = self.currentPageIndex + 1; + if (nextPage == [self numberOfPages]) { + // ...stop the auto-scrolling or... + if (!self.autoScrollEnabled) { + self.currentState = ScrollingStateManual; + return; + } + + // ...jump to the first page. + nextPage = 0; + self.currentState = ScrollingStateLooping; + + // Set alpha on layers. + [self setOriginLayerAlpha]; + [self setBackLayerPictureWithPageIndex:-1]; + } else { + self.currentState = ScrollingStateAuto; + } + + // Make the scrollView animation. + [self scrollToNextPageIndex:nextPage]; + + // Call the next animation after X seconds. + [self autoScrollToNextPage]; +} + +// Call the next animation after X seconds. +- (void)autoScrollToNextPage { + ICETutorialPage *page = self.pages[self.currentPageIndex]; + + if (self.autoScrollEnabled) { + [self performSelector:@selector(animateScrolling) + withObject:nil + afterDelay:page.duration]; + } +} + +- (void)scrollToNextPageIndex:(NSUInteger)nextPageIndex { + // Make the scrollView animation. + [self.scrollView setContentOffset:CGPointMake(nextPageIndex * self.view.frame.size.width,0) + animated:YES]; + + // Set the PageControl on the right page. + [self.pageControl setCurrentPage:nextPageIndex]; +} + +#pragma mark - Scrolling management +// Run it. +- (void)startScrolling { + [self autoScrollToNextPage]; +} + +// Manually stop the scrolling +- (void)stopScrolling { + self.currentState = ScrollingStateManual; +} + +#pragma mark - State management +// State. +- (ScrollingState)getCurrentState { + return self.currentState; +} + +#pragma mark - Overlay management +// Setup the Title Label. +- (void)setOverlayTitle { + // ...or change by an UIImageView if you need it. + [self.overlayTitle setText:NSLocalizedString(@"Welcome", nil)]; +} + +// Setup the Title/Subtitle style/text. +- (void)setOverlayTexts { + int index = 0; + for (ICETutorialPage *page in self.pages) { + // SubTitles. + if ([[[page title] text] length]) { + [self overlayLabelWithStyle:[page title] + commonStyle:[[ICETutorialStyle sharedInstance] titleStyle] + index:index]; + } + // Description. + if ([[[page subTitle] text] length]) { + [self overlayLabelWithStyle:[page subTitle] + commonStyle:[[ICETutorialStyle sharedInstance] subTitleStyle] + index:index]; + } + + index++; + } +} + +- (void)overlayLabelWithStyle:(ICETutorialLabelStyle *)style + commonStyle:(ICETutorialLabelStyle *)commonStyle + index:(NSUInteger)index { + // SubTitles. + UILabel *overlayLabel = [[UILabel alloc] initWithFrame:CGRectMake((index * self.view.frame.size.width) + 10, + self.view.frame.size.height - [commonStyle offset], + self.view.frame.size.width - 20, + TUTORIAL_LABEL_HEIGHT + 10)]; + [overlayLabel setNumberOfLines:[commonStyle linesNumber]]; + [overlayLabel setBackgroundColor:[UIColor clearColor]]; + [overlayLabel setTextAlignment:NSTextAlignmentCenter]; + + // Datas and style. + [overlayLabel setText:[style text]]; + [style font] ? [overlayLabel setFont:[style font]] : + [overlayLabel setFont:[commonStyle font]]; + [style textColor] ? [overlayLabel setTextColor:[style textColor]] : + [overlayLabel setTextColor:[commonStyle textColor]]; + + [self.scrollView addSubview:overlayLabel]; +} + +#pragma mark - Layers management +// Handle the background layer image switch. +- (void)setBackLayerPictureWithPageIndex:(NSInteger)index { + [self setBackgroundImage:self.backLayerView withIndex:index + 1]; +} + +// Handle the front layer image switch. +- (void)setFrontLayerPictureWithPageIndex:(NSInteger)index { + [self setBackgroundImage:self.frontLayerView withIndex:index]; +} + +// Handle page image's loading +- (void)setBackgroundImage:(UIImageView *)imageView withIndex:(NSInteger)index { + if (index >= [self.pages count]) { + [imageView setImage:nil]; + return; + } + + [imageView setImage:[UIImage imageNamed:[self.pages[index] pictureName]]]; +} + +// Setup lapyer's alpha. +- (void)setOriginLayerAlpha { + [self.frontLayerView setAlpha:1]; + [self.backLayerView setAlpha:0]; +} + +// Preset the origin state. +- (void)setOriginLayersState { + self.currentState = ScrollingStateAuto; + [self.backLayerView setBackgroundColor:[UIColor blackColor]]; + [self.frontLayerView setBackgroundColor:[UIColor blackColor]]; + [self setLayersPicturesWithIndex:0]; +} + +// Setup the layers with the page index. +- (void)setLayersPicturesWithIndex:(NSInteger)index { + self.currentPageIndex = index; + [self setOriginLayerAlpha]; + [self setFrontLayerPictureWithPageIndex:index]; + [self setBackLayerPictureWithPageIndex:index]; +} + +// Animate the fade-in/out (Cross-disolve) with the scrollView translation. +- (void)disolveBackgroundWithContentOffset:(float)offset { + if (self.currentState & ScrollingStateLooping){ + // Jump from the last page to the first. + [self scrollingToFirstPageWithOffset:offset]; + } else { + // Or just scroll to the next/previous page. + [self scrollingToNextPageWithOffset:offset]; + } +} + +// Handle alpha on layers when the auto-scrolling is looping to the first page. +- (void)scrollingToFirstPageWithOffset:(float)offset { + // Compute the scrolling percentage on all the page. + offset = (offset * self.view.frame.size.width) / (self.view.frame.size.width * [self numberOfPages]); + + // Scrolling finished... + if (!offset){ + // ...reset to the origin state. + [self setOriginLayersState]; + return; + } + + // Invert alpha for the back picture. + float backLayerAlpha = (1 - offset); + float frontLayerAlpha = offset; + + // Set alpha. + [self.backLayerView setAlpha:backLayerAlpha]; + [self.frontLayerView setAlpha:frontLayerAlpha]; +} + +// Handle alpha on layers when we are scrolling to the next/previous page. +- (void)scrollingToNextPageWithOffset:(float)offset { + // Current page index in scrolling. + NSInteger nextPage = (int)offset; + + // Keep only the float value. + float alphaValue = offset - nextPage; + + // This is only when you scroll to the right on the first page. + // That will fade-in black the first picture. + if (alphaValue < 0 && self.currentPageIndex == 0){ + [self.backLayerView setImage:nil]; + [self.frontLayerView setAlpha:(1 + alphaValue)]; + return; + } + + // Switch pictures, and imageView alpha. + if (nextPage != self.currentPageIndex || + ((nextPage == self.currentPageIndex) && (0.0 < offset) && (offset < 1.0))) + [self setLayersPicturesWithIndex:nextPage]; + + // Invert alpha for the front picture. + float backLayerAlpha = alphaValue; + float frontLayerAlpha = (1 - alphaValue); + + // Set alpha. + [self.backLayerView setAlpha:backLayerAlpha]; + [self.frontLayerView setAlpha:frontLayerAlpha]; +} + +#pragma mark - ScrollView delegate +- (void)scrollViewDidScroll:(UIScrollView *)scrollView { + // Get scrolling position, and nextPageindex. + float scrollingPosition = scrollView.contentOffset.x / self.view.frame.size.width; + int nextPageIndex = (int)scrollingPosition; + + // If we are looping, we reset the indexPage. + if (self.currentState & ScrollingStateLooping) { + nextPageIndex = 0; + } + + // If we are going to the next page, let's call the delegate. + if (nextPageIndex != self.nextPageIndex) { + if ([self.delegate respondsToSelector:@selector(tutorialController:scrollingFromPageIndex:toPageIndex:)]) { + [self.delegate tutorialController:self scrollingFromPageIndex:self.currentPageIndex toPageIndex:nextPageIndex]; + } + + self.nextPageIndex = nextPageIndex; + } + + // Delegate when we reach the end. + if (self.nextPageIndex == [self numberOfPages] - 1) { + if ([self.delegate respondsToSelector:@selector(tutorialControllerDidReachLastPage:)]) { + [self.delegate tutorialControllerDidReachLastPage:self]; + } + } + + // Animate. + [self disolveBackgroundWithContentOffset:scrollingPosition]; +} + +- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { + // At the first user interaction, we disable the auto scrolling. + if (self.scrollView.isTracking) { + [self stopScrolling]; + } +} + +- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { + // Update the page index. + [self.pageControl setCurrentPage:self.currentPageIndex]; +} + +@end diff --git a/ICETutorial-Library/ICETutorialPage.h b/ICETutorial-Library/ICETutorialPage.h new file mode 100755 index 0000000..656bd25 --- /dev/null +++ b/ICETutorial-Library/ICETutorialPage.h @@ -0,0 +1,45 @@ +// +// ICETutorialPage.h +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +@import Foundation; +@import UIKit; + +@interface ICETutorialLabelStyle : NSObject + +@property (nonatomic, retain) NSString *text; +@property (nonatomic, retain) UIFont *font; +@property (nonatomic, retain) UIColor *textColor; +@property (nonatomic, assign) NSUInteger linesNumber; +@property (nonatomic, assign) NSUInteger offset; + +// Init. +- (instancetype)initWithText:(NSString *)text; +- (instancetype)initWithFont:(UIFont *)font + textColor:(UIColor *)color + linesNumber:(NSUInteger)linesNumber + offset:(NSUInteger)offset; +@end + +@interface ICETutorialPage : NSObject + +@property (nonatomic, retain) ICETutorialLabelStyle *title; +@property (nonatomic, retain) ICETutorialLabelStyle *subTitle; +@property (nonatomic, retain) NSString *pictureName; +@property (nonatomic, assign) NSTimeInterval duration; + +// Init. +- (instancetype)initWithTitle:(NSString *)title + subTitle:(NSString *)subTitle + pictureName:(NSString *)pictureName + duration:(NSTimeInterval)duration; + +- (void)setTitleStyle:(ICETutorialLabelStyle *)style; +- (void)setSubTitleStyle:(ICETutorialLabelStyle *)style; + +@end + diff --git a/ICETutorial-Library/ICETutorialPage.m b/ICETutorial-Library/ICETutorialPage.m new file mode 100755 index 0000000..ae1c001 --- /dev/null +++ b/ICETutorial-Library/ICETutorialPage.m @@ -0,0 +1,65 @@ +// +// ICETutorialPage.m +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +#import "ICETutorialPage.h" + +@implementation ICETutorialLabelStyle + +// Init. +- (instancetype)initWithText:(NSString *)text { + self = [super init]; + if (self){ + _text = text; + } + return self; +} + +- (instancetype)initWithFont:(UIFont *)font + textColor:(UIColor *)color + linesNumber:(NSUInteger)linesNumber + offset:(NSUInteger)offset { + self = [self init]; + if (self){ + _font = font; + _textColor = color; + _linesNumber = linesNumber; + _offset = offset; + } + return self; +} + +@end + +@implementation ICETutorialPage + +// Init. +- (instancetype)initWithTitle:(NSString *)title + subTitle:(NSString *)subTitle + pictureName:(NSString *)pictureName + duration:(NSTimeInterval)duration { + self = [super init]; + if (self){ + _title = [[ICETutorialLabelStyle alloc] initWithText:title]; + _subTitle = [[ICETutorialLabelStyle alloc] initWithText:subTitle]; + _pictureName = pictureName; + _duration = duration; + } + return self; +} + +- (void)setTitleStyle:(ICETutorialLabelStyle *)style { + [self.title setFont:style.font]; + [self.title setTextColor:style.textColor]; +} + +- (void)setSubTitleStyle:(ICETutorialLabelStyle *)style { + [self.subTitle setFont:style.font]; + [self.subTitle setTextColor:style.textColor]; +} + +@end diff --git a/ICETutorial-Library/ICETutorialStyle.h b/ICETutorial-Library/ICETutorialStyle.h new file mode 100644 index 0000000..0124455 --- /dev/null +++ b/ICETutorial-Library/ICETutorialStyle.h @@ -0,0 +1,28 @@ +// +// ICETutorialStyle.h +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +@import Foundation; +#import "ICETutorialPage.h" + +@interface ICETutorialStyle : NSObject + +@property (nonatomic, strong) UIFont *titleFont; +@property (nonatomic, strong) UIColor *titleColor; +@property (nonatomic, assign) NSUInteger titleLinesNumber; +@property (nonatomic, assign) NSUInteger titleOffset; +@property (nonatomic, strong) UIFont *subTitleFont; +@property (nonatomic, strong) UIColor *subTitleColor; +@property (nonatomic, assign) NSUInteger subTitleLinesNumber; +@property (nonatomic, assign) NSUInteger subTitleOffset; + +@property (nonatomic, strong) ICETutorialLabelStyle *titleStyle; +@property (nonatomic, strong) ICETutorialLabelStyle *subTitleStyle; + ++ (instancetype)sharedInstance; + +@end diff --git a/ICETutorial-Library/ICETutorialStyle.m b/ICETutorial-Library/ICETutorialStyle.m new file mode 100644 index 0000000..586a975 --- /dev/null +++ b/ICETutorial-Library/ICETutorialStyle.m @@ -0,0 +1,103 @@ +// +// ICETutorialStyle.m +// ICETutorial +// +// Created by Patrick Trillsam on 25/03/13. +// Copyright (c) 2014 https://github.com/icepat/ICETutorial. All rights reserved. +// + +#import "ICETutorialStyle.h" +#import "ICETutorialController.h" + +@implementation ICETutorialStyle + ++ (instancetype)sharedInstance { + static ICETutorialStyle *sharedInstance = nil; + static dispatch_once_t onceToken = 0; + dispatch_once(&onceToken, ^{ + sharedInstance = [[ICETutorialStyle alloc] init]; + }); + return sharedInstance; +} + +#pragma mark - Properties +- (UIFont *)titleFont { + if (_titleFont) { + return _titleFont; + } + return TUTORIAL_TITLE_FONT; +} + +- (UIColor *)titleColor { + if (_titleColor) { + return _titleColor; + } + return TUTORIAL_LABEL_TEXT_COLOR; +} + +- (NSUInteger)titleLinesNumber { + if (_titleLinesNumber != NSNotFound) { + return _titleLinesNumber; + } + return TUTORIAL_TITLE_LINES_NUMBER; +} + +- (NSUInteger)titleOffset { + if (_titleOffset != NSNotFound) { + return _titleOffset; + } + return TUTORIAL_TITLE_OFFSET; +} + +- (UIFont *)subTitleFont { + if (_subTitleFont) { + return _subTitleFont; + } + return TUTORIAL_SUB_TITLE_FONT; +} + +- (UIColor *)subTitleColor { + if (_subTitleColor) { + return _subTitleColor; + } + return TUTORIAL_LABEL_TEXT_COLOR; +} + +- (NSUInteger)subTitleLinesNumber { + if (_titleLinesNumber != NSNotFound) { + return _titleLinesNumber; + } + return TUTORIAL_SUB_TITLE_LINES_NUMBER; +} + +- (NSUInteger)subTitleOffset { + if (_subTitleOffset != NSNotFound) { + return _subTitleOffset; + } + return TUTORIAL_SUB_TITLE_OFFSET; +} + +#pragma mark - Styles +- (ICETutorialLabelStyle *)titleStyle { + if (_titleStyle) { + return _titleStyle; + } + + return [[ICETutorialLabelStyle alloc] initWithFont:self.titleFont + textColor:self.titleColor + linesNumber:self.titleLinesNumber + offset:self.titleOffset]; +} + +- (ICETutorialLabelStyle *)subTitleStyle { + if (_subTitleStyle) { + return _subTitleStyle; + } + + return [[ICETutorialLabelStyle alloc] initWithFont:self.subTitleFont + textColor:self.subTitleColor + linesNumber:self.subTitleLinesNumber + offset:self.subTitleOffset]; +} + +@end diff --git a/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/UserInterfaceState.xcuserstate b/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100755 index e2f6b5e..0000000 Binary files a/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepat-dev.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ diff --git a/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepatdev.xcuserdatad/UserInterfaceState.xcuserstate b/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepatdev.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100755 index d436888..0000000 Binary files a/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/icepatdev.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ diff --git a/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/UserInterfaceState.xcuserstate b/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100755 index 7dd1e90..0000000 Binary files a/ICETutorial.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/UserInterfaceState.xcuserstate and /dev/null differ diff --git a/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist b/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist deleted file mode 100755 index 05301bc..0000000 --- a/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/tutorial.xcscheme b/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/tutorial.xcscheme deleted file mode 100755 index 6a7079d..0000000 --- a/ICETutorial.xcodeproj/xcuserdata/icepat-dev.xcuserdatad/xcschemes/tutorial.xcscheme +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist b/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist deleted file mode 100755 index 05301bc..0000000 --- a/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/ICETutorial.xcscheme b/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/ICETutorial.xcscheme deleted file mode 100755 index 6a7079d..0000000 --- a/ICETutorial.xcodeproj/xcuserdata/icepatdev.xcuserdatad/xcschemes/ICETutorial.xcscheme +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist b/ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist deleted file mode 100755 index e8baae4..0000000 --- a/ICETutorial.xcodeproj/xcuserdata/patrick.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - -