├── .gitignore ├── .mention-bot ├── .swift-version ├── .travis.yml ├── CONTRIBUTING.md ├── Cartfile ├── Cartfile.resolved ├── Example ├── Parallax │ ├── .swift-version │ ├── Images │ │ └── Parallax-v2.gif │ ├── Parallax.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ └── contents.xcworkspacedata │ ├── Parallax.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Parallax │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ └── LaunchScreen.xib │ │ ├── Info.plist │ │ ├── Resources │ │ │ └── Images.xcassets │ │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ │ ├── Bus.imageset │ │ │ │ ├── Bus.png │ │ │ │ ├── Bus@2x.png │ │ │ │ └── Contents.json │ │ │ │ ├── Clouds.imageset │ │ │ │ ├── Clouds.png │ │ │ │ ├── Clouds@2x.png │ │ │ │ └── Contents.json │ │ │ │ ├── Hills.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Hills.png │ │ │ │ └── Hills@2x.png │ │ │ │ ├── Houses.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Houses.png │ │ │ │ └── Houses@2x.png │ │ │ │ ├── Mountains.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Mountains.png │ │ │ │ └── Mountains@2x.png │ │ │ │ ├── Roadlines.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Roadlines.png │ │ │ │ └── Roadlines@2x.png │ │ │ │ ├── Sun.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Sun.png │ │ │ │ └── Sun@2x.png │ │ │ │ ├── Trees.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Trees.png │ │ │ │ └── Trees@2x.png │ │ │ │ └── Truck.imageset │ │ │ │ ├── Contents.json │ │ │ │ ├── Truck.png │ │ │ │ └── Truck@2x.png │ │ └── ViewController.swift │ ├── Podfile │ └── Podfile.lock └── Tutorial │ ├── .swift-version │ ├── Podfile │ ├── Podfile.lock │ ├── Tutorial.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata │ ├── Tutorial.xcworkspace │ └── contents.xcworkspacedata │ └── Tutorial │ ├── AppDelegate.swift │ ├── Base.lproj │ └── LaunchScreen.xib │ ├── Info.plist │ └── Resources │ └── Images.xcassets │ ├── AppIcon.appiconset │ └── Contents.json │ ├── Cloud1.imageset │ ├── Cloud1.png │ ├── Cloud1@2x.png │ └── Contents.json │ ├── Cloud2.imageset │ ├── Cloud2.png │ ├── Cloud2@2x.png │ └── Contents.json │ └── HyperLogo.imageset │ ├── Contents.json │ ├── HyperLogo.png │ └── HyperLogo@2x.png ├── Images └── logo.png ├── LICENSE.md ├── Pod ├── Pod.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── Tests.xcscheme ├── Pod.xcworkspace │ └── contents.xcworkspacedata ├── Podfile ├── Podfile.lock └── Tests │ ├── Info.plist │ └── Specs │ ├── Animations │ ├── DissolveAnimationSpec.swift │ ├── PopAnimationSpec.swift │ └── TransitionAnimationSpec.swift │ ├── ContentSpec.swift │ ├── Extensions │ └── CGPointExtensionSpec.swift │ ├── Helpers │ └── SpecHelper.swift │ └── PositionSpec.swift ├── Presentation.podspec ├── Presentation.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── Presentation-iOS.xcscheme ├── README.md ├── Source ├── Animations │ ├── Animatable.swift │ ├── DissolveAnimation.swift │ ├── PopAnimation.swift │ └── TransitionAnimation.swift ├── Content.swift ├── Extensions │ └── CGPointExtension.swift ├── Position.swift ├── PresentationController.swift └── SlideController.swift └── SupportFiles └── Info.plist /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | Icon 6 | ._* 7 | .Spotlight-V100 8 | .Trashes 9 | 10 | # Xcode 11 | # 12 | build/ 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | *.xccheckout 23 | *.moved-aside 24 | DerivedData 25 | *.hmap 26 | *.ipa 27 | *.xcuserstate 28 | 29 | # CocoaPods 30 | Pods 31 | 32 | # Carthage 33 | Carthage 34 | -------------------------------------------------------------------------------- /.mention-bot: -------------------------------------------------------------------------------- 1 | { 2 | "maxReviewers": 2, 3 | "requiredOrgs": ["hyperoslo"] 4 | } 5 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | osx_image: xcode9 2 | language: objective-c 3 | xcode_sdk: iphonesimulator10.0 4 | 5 | before_install: 6 | - brew update 7 | - if brew outdated | grep -qx carthage; then brew upgrade carthage; fi 8 | - travis_wait 35 carthage bootstrap --platform iOS 9 | 10 | script: 11 | - set -o pipefail 12 | - travis_retry xcodebuild clean build -project Presentation.xcodeproj -scheme "Presentation-iOS" -destination "platform=iOS Simulator,name=iPhone 6" | xcpretty 13 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | GitHub Issues is for reporting bugs, discussing features and general feedback in **Presentation**. Be sure to check our [documentation](http://cocoadocs.org/docsets/Presentation), [FAQ](https://github.com/hyperoslo/Presentation/wiki/FAQ) and [past issues](https://github.com/hyperoslo/Presentation/issues?state=closed) before opening any new issues. 2 | 3 | If you are posting about a crash in your application, a stack trace is helpful, but additional context, in the form of code and explanation, is necessary to be of any use. 4 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "hyperoslo/Pages" 2 | -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "hyperoslo/Pages" "2.0.2" 2 | -------------------------------------------------------------------------------- /Example/Parallax/.swift-version: -------------------------------------------------------------------------------- 1 | 4.0 2 | -------------------------------------------------------------------------------- /Example/Parallax/Images/Parallax-v2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Images/Parallax-v2.gif -------------------------------------------------------------------------------- /Example/Parallax/Parallax.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D563C9FC1AF6DD6400E2F7C8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D563C9FB1AF6DD6400E2F7C8 /* AppDelegate.swift */; }; 11 | D563C9FE1AF6DD6400E2F7C8 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D563C9FD1AF6DD6400E2F7C8 /* ViewController.swift */; }; 12 | D563CA061AF6DD6400E2F7C8 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = D563CA041AF6DD6400E2F7C8 /* LaunchScreen.xib */; }; 13 | D563CA1D1AF6DDDE00E2F7C8 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D563CA1C1AF6DDDE00E2F7C8 /* Images.xcassets */; }; 14 | E7318465F6A830D05292B962 /* Pods_Parallax.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E1532DD8D091D918635DC91 /* Pods_Parallax.framework */; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXFileReference section */ 18 | 19AAEC28E205728CA1917A3B /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | 1E1532DD8D091D918635DC91 /* Pods_Parallax.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Parallax.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | B02370FC71897A4E6AA7FCA5 /* Pods-Parallax.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Parallax.release.xcconfig"; path = "Pods/Target Support Files/Pods-Parallax/Pods-Parallax.release.xcconfig"; sourceTree = ""; }; 21 | BA94E5A460EF187F5933E2AC /* Pods-Parallax.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Parallax.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Parallax/Pods-Parallax.debug.xcconfig"; sourceTree = ""; }; 22 | D563C9F61AF6DD6400E2F7C8 /* Parallax.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Parallax.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | D563C9FA1AF6DD6400E2F7C8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | D563C9FB1AF6DD6400E2F7C8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 25 | D563C9FD1AF6DD6400E2F7C8 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 26 | D563CA051AF6DD6400E2F7C8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 27 | D563CA1C1AF6DDDE00E2F7C8 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | D563C9F31AF6DD6400E2F7C8 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | E7318465F6A830D05292B962 /* Pods_Parallax.framework in Frameworks */, 36 | ); 37 | runOnlyForDeploymentPostprocessing = 0; 38 | }; 39 | /* End PBXFrameworksBuildPhase section */ 40 | 41 | /* Begin PBXGroup section */ 42 | 9986D36FFC77968FAACA4B7A /* Pods */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | BA94E5A460EF187F5933E2AC /* Pods-Parallax.debug.xcconfig */, 46 | B02370FC71897A4E6AA7FCA5 /* Pods-Parallax.release.xcconfig */, 47 | ); 48 | name = Pods; 49 | sourceTree = ""; 50 | }; 51 | BDEF999980885BB6D44186A5 /* Frameworks */ = { 52 | isa = PBXGroup; 53 | children = ( 54 | 19AAEC28E205728CA1917A3B /* Pods.framework */, 55 | 1E1532DD8D091D918635DC91 /* Pods_Parallax.framework */, 56 | ); 57 | name = Frameworks; 58 | sourceTree = ""; 59 | }; 60 | D563C9ED1AF6DD6400E2F7C8 = { 61 | isa = PBXGroup; 62 | children = ( 63 | D563C9F81AF6DD6400E2F7C8 /* Parallax */, 64 | D563C9F71AF6DD6400E2F7C8 /* Products */, 65 | BDEF999980885BB6D44186A5 /* Frameworks */, 66 | 9986D36FFC77968FAACA4B7A /* Pods */, 67 | ); 68 | sourceTree = ""; 69 | }; 70 | D563C9F71AF6DD6400E2F7C8 /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | D563C9F61AF6DD6400E2F7C8 /* Parallax.app */, 74 | ); 75 | name = Products; 76 | sourceTree = ""; 77 | }; 78 | D563C9F81AF6DD6400E2F7C8 /* Parallax */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | D563CA1B1AF6DDBC00E2F7C8 /* Resources */, 82 | D563C9FB1AF6DD6400E2F7C8 /* AppDelegate.swift */, 83 | D563C9FD1AF6DD6400E2F7C8 /* ViewController.swift */, 84 | D563CA041AF6DD6400E2F7C8 /* LaunchScreen.xib */, 85 | D563C9F91AF6DD6400E2F7C8 /* Supporting Files */, 86 | ); 87 | path = Parallax; 88 | sourceTree = ""; 89 | }; 90 | D563C9F91AF6DD6400E2F7C8 /* Supporting Files */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | D563C9FA1AF6DD6400E2F7C8 /* Info.plist */, 94 | ); 95 | name = "Supporting Files"; 96 | sourceTree = ""; 97 | }; 98 | D563CA1B1AF6DDBC00E2F7C8 /* Resources */ = { 99 | isa = PBXGroup; 100 | children = ( 101 | D563CA1C1AF6DDDE00E2F7C8 /* Images.xcassets */, 102 | ); 103 | path = Resources; 104 | sourceTree = ""; 105 | }; 106 | /* End PBXGroup section */ 107 | 108 | /* Begin PBXNativeTarget section */ 109 | D563C9F51AF6DD6400E2F7C8 /* Parallax */ = { 110 | isa = PBXNativeTarget; 111 | buildConfigurationList = D563CA151AF6DD6400E2F7C8 /* Build configuration list for PBXNativeTarget "Parallax" */; 112 | buildPhases = ( 113 | 054B3C6F8F43EC5DC1BF3DD7 /* [CP] Check Pods Manifest.lock */, 114 | D563C9F21AF6DD6400E2F7C8 /* Sources */, 115 | D563C9F31AF6DD6400E2F7C8 /* Frameworks */, 116 | D563C9F41AF6DD6400E2F7C8 /* Resources */, 117 | 8DE34F6FB4EAD7F36307575D /* [CP] Embed Pods Frameworks */, 118 | 513D09C629696FF9539C0C6E /* [CP] Copy Pods Resources */, 119 | ); 120 | buildRules = ( 121 | ); 122 | dependencies = ( 123 | ); 124 | name = Parallax; 125 | productName = Parallax; 126 | productReference = D563C9F61AF6DD6400E2F7C8 /* Parallax.app */; 127 | productType = "com.apple.product-type.application"; 128 | }; 129 | /* End PBXNativeTarget section */ 130 | 131 | /* Begin PBXProject section */ 132 | D563C9EE1AF6DD6400E2F7C8 /* Project object */ = { 133 | isa = PBXProject; 134 | attributes = { 135 | LastSwiftUpdateCheck = 0700; 136 | LastUpgradeCheck = 0900; 137 | ORGANIZATIONNAME = Hyper; 138 | TargetAttributes = { 139 | D563C9F51AF6DD6400E2F7C8 = { 140 | CreatedOnToolsVersion = 6.3.1; 141 | LastSwiftMigration = 0900; 142 | }; 143 | }; 144 | }; 145 | buildConfigurationList = D563C9F11AF6DD6400E2F7C8 /* Build configuration list for PBXProject "Parallax" */; 146 | compatibilityVersion = "Xcode 3.2"; 147 | developmentRegion = English; 148 | hasScannedForEncodings = 0; 149 | knownRegions = ( 150 | en, 151 | Base, 152 | ); 153 | mainGroup = D563C9ED1AF6DD6400E2F7C8; 154 | productRefGroup = D563C9F71AF6DD6400E2F7C8 /* Products */; 155 | projectDirPath = ""; 156 | projectRoot = ""; 157 | targets = ( 158 | D563C9F51AF6DD6400E2F7C8 /* Parallax */, 159 | ); 160 | }; 161 | /* End PBXProject section */ 162 | 163 | /* Begin PBXResourcesBuildPhase section */ 164 | D563C9F41AF6DD6400E2F7C8 /* Resources */ = { 165 | isa = PBXResourcesBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | D563CA061AF6DD6400E2F7C8 /* LaunchScreen.xib in Resources */, 169 | D563CA1D1AF6DDDE00E2F7C8 /* Images.xcassets in Resources */, 170 | ); 171 | runOnlyForDeploymentPostprocessing = 0; 172 | }; 173 | /* End PBXResourcesBuildPhase section */ 174 | 175 | /* Begin PBXShellScriptBuildPhase section */ 176 | 054B3C6F8F43EC5DC1BF3DD7 /* [CP] Check Pods Manifest.lock */ = { 177 | isa = PBXShellScriptBuildPhase; 178 | buildActionMask = 2147483647; 179 | files = ( 180 | ); 181 | inputPaths = ( 182 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 183 | "${PODS_ROOT}/Manifest.lock", 184 | ); 185 | name = "[CP] Check Pods Manifest.lock"; 186 | outputPaths = ( 187 | "$(DERIVED_FILE_DIR)/Pods-Parallax-checkManifestLockResult.txt", 188 | ); 189 | runOnlyForDeploymentPostprocessing = 0; 190 | shellPath = /bin/sh; 191 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 192 | showEnvVarsInLog = 0; 193 | }; 194 | 513D09C629696FF9539C0C6E /* [CP] Copy Pods Resources */ = { 195 | isa = PBXShellScriptBuildPhase; 196 | buildActionMask = 2147483647; 197 | files = ( 198 | ); 199 | inputPaths = ( 200 | ); 201 | name = "[CP] Copy Pods Resources"; 202 | outputPaths = ( 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | shellPath = /bin/sh; 206 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Parallax/Pods-Parallax-resources.sh\"\n"; 207 | showEnvVarsInLog = 0; 208 | }; 209 | 8DE34F6FB4EAD7F36307575D /* [CP] Embed Pods Frameworks */ = { 210 | isa = PBXShellScriptBuildPhase; 211 | buildActionMask = 2147483647; 212 | files = ( 213 | ); 214 | inputPaths = ( 215 | "${SRCROOT}/Pods/Target Support Files/Pods-Parallax/Pods-Parallax-frameworks.sh", 216 | "${BUILT_PRODUCTS_DIR}/Hue/Hue.framework", 217 | "${BUILT_PRODUCTS_DIR}/Pages/Pages.framework", 218 | "${BUILT_PRODUCTS_DIR}/Presentation/Presentation.framework", 219 | ); 220 | name = "[CP] Embed Pods Frameworks"; 221 | outputPaths = ( 222 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Hue.framework", 223 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Pages.framework", 224 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Presentation.framework", 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | shellPath = /bin/sh; 228 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Parallax/Pods-Parallax-frameworks.sh\"\n"; 229 | showEnvVarsInLog = 0; 230 | }; 231 | /* End PBXShellScriptBuildPhase section */ 232 | 233 | /* Begin PBXSourcesBuildPhase section */ 234 | D563C9F21AF6DD6400E2F7C8 /* Sources */ = { 235 | isa = PBXSourcesBuildPhase; 236 | buildActionMask = 2147483647; 237 | files = ( 238 | D563C9FE1AF6DD6400E2F7C8 /* ViewController.swift in Sources */, 239 | D563C9FC1AF6DD6400E2F7C8 /* AppDelegate.swift in Sources */, 240 | ); 241 | runOnlyForDeploymentPostprocessing = 0; 242 | }; 243 | /* End PBXSourcesBuildPhase section */ 244 | 245 | /* Begin PBXVariantGroup section */ 246 | D563CA041AF6DD6400E2F7C8 /* LaunchScreen.xib */ = { 247 | isa = PBXVariantGroup; 248 | children = ( 249 | D563CA051AF6DD6400E2F7C8 /* Base */, 250 | ); 251 | name = LaunchScreen.xib; 252 | sourceTree = ""; 253 | }; 254 | /* End PBXVariantGroup section */ 255 | 256 | /* Begin XCBuildConfiguration section */ 257 | D563CA131AF6DD6400E2F7C8 /* Debug */ = { 258 | isa = XCBuildConfiguration; 259 | buildSettings = { 260 | ALWAYS_SEARCH_USER_PATHS = NO; 261 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 262 | CLANG_CXX_LIBRARY = "libc++"; 263 | CLANG_ENABLE_MODULES = YES; 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 266 | CLANG_WARN_BOOL_CONVERSION = YES; 267 | CLANG_WARN_COMMA = YES; 268 | CLANG_WARN_CONSTANT_CONVERSION = YES; 269 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 270 | CLANG_WARN_EMPTY_BODY = YES; 271 | CLANG_WARN_ENUM_CONVERSION = YES; 272 | CLANG_WARN_INFINITE_RECURSION = YES; 273 | CLANG_WARN_INT_CONVERSION = YES; 274 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 275 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 276 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 277 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 278 | CLANG_WARN_STRICT_PROTOTYPES = YES; 279 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 280 | CLANG_WARN_UNREACHABLE_CODE = YES; 281 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 282 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 283 | COPY_PHASE_STRIP = NO; 284 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 285 | ENABLE_STRICT_OBJC_MSGSEND = YES; 286 | ENABLE_TESTABILITY = YES; 287 | GCC_C_LANGUAGE_STANDARD = gnu99; 288 | GCC_DYNAMIC_NO_PIC = NO; 289 | GCC_NO_COMMON_BLOCKS = YES; 290 | GCC_OPTIMIZATION_LEVEL = 0; 291 | GCC_PREPROCESSOR_DEFINITIONS = ( 292 | "DEBUG=1", 293 | "$(inherited)", 294 | ); 295 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 296 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 297 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 298 | GCC_WARN_UNDECLARED_SELECTOR = YES; 299 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 300 | GCC_WARN_UNUSED_FUNCTION = YES; 301 | GCC_WARN_UNUSED_VARIABLE = YES; 302 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 303 | MTL_ENABLE_DEBUG_INFO = YES; 304 | ONLY_ACTIVE_ARCH = YES; 305 | SDKROOT = iphoneos; 306 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 307 | SWIFT_VERSION = 3.0; 308 | TARGETED_DEVICE_FAMILY = 2; 309 | }; 310 | name = Debug; 311 | }; 312 | D563CA141AF6DD6400E2F7C8 /* Release */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ALWAYS_SEARCH_USER_PATHS = NO; 316 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 317 | CLANG_CXX_LIBRARY = "libc++"; 318 | CLANG_ENABLE_MODULES = YES; 319 | CLANG_ENABLE_OBJC_ARC = YES; 320 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 321 | CLANG_WARN_BOOL_CONVERSION = YES; 322 | CLANG_WARN_COMMA = YES; 323 | CLANG_WARN_CONSTANT_CONVERSION = YES; 324 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 325 | CLANG_WARN_EMPTY_BODY = YES; 326 | CLANG_WARN_ENUM_CONVERSION = YES; 327 | CLANG_WARN_INFINITE_RECURSION = YES; 328 | CLANG_WARN_INT_CONVERSION = YES; 329 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 330 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 331 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 332 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 333 | CLANG_WARN_STRICT_PROTOTYPES = YES; 334 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 335 | CLANG_WARN_UNREACHABLE_CODE = YES; 336 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 337 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 338 | COPY_PHASE_STRIP = NO; 339 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 340 | ENABLE_NS_ASSERTIONS = NO; 341 | ENABLE_STRICT_OBJC_MSGSEND = YES; 342 | GCC_C_LANGUAGE_STANDARD = gnu99; 343 | GCC_NO_COMMON_BLOCKS = YES; 344 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 345 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 346 | GCC_WARN_UNDECLARED_SELECTOR = YES; 347 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 348 | GCC_WARN_UNUSED_FUNCTION = YES; 349 | GCC_WARN_UNUSED_VARIABLE = YES; 350 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 351 | MTL_ENABLE_DEBUG_INFO = NO; 352 | SDKROOT = iphoneos; 353 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 354 | SWIFT_VERSION = 3.0; 355 | TARGETED_DEVICE_FAMILY = 2; 356 | VALIDATE_PRODUCT = YES; 357 | }; 358 | name = Release; 359 | }; 360 | D563CA161AF6DD6400E2F7C8 /* Debug */ = { 361 | isa = XCBuildConfiguration; 362 | baseConfigurationReference = BA94E5A460EF187F5933E2AC /* Pods-Parallax.debug.xcconfig */; 363 | buildSettings = { 364 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 365 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 366 | INFOPLIST_FILE = Parallax/Info.plist; 367 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 368 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 369 | PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.$(PRODUCT_NAME:rfc1034identifier)"; 370 | PRODUCT_NAME = "$(TARGET_NAME)"; 371 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 372 | SWIFT_VERSION = 4.0; 373 | TARGETED_DEVICE_FAMILY = "1,2"; 374 | }; 375 | name = Debug; 376 | }; 377 | D563CA171AF6DD6400E2F7C8 /* Release */ = { 378 | isa = XCBuildConfiguration; 379 | baseConfigurationReference = B02370FC71897A4E6AA7FCA5 /* Pods-Parallax.release.xcconfig */; 380 | buildSettings = { 381 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 382 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 383 | INFOPLIST_FILE = Parallax/Info.plist; 384 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 385 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 386 | PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.$(PRODUCT_NAME:rfc1034identifier)"; 387 | PRODUCT_NAME = "$(TARGET_NAME)"; 388 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 389 | SWIFT_VERSION = 4.0; 390 | TARGETED_DEVICE_FAMILY = "1,2"; 391 | }; 392 | name = Release; 393 | }; 394 | /* End XCBuildConfiguration section */ 395 | 396 | /* Begin XCConfigurationList section */ 397 | D563C9F11AF6DD6400E2F7C8 /* Build configuration list for PBXProject "Parallax" */ = { 398 | isa = XCConfigurationList; 399 | buildConfigurations = ( 400 | D563CA131AF6DD6400E2F7C8 /* Debug */, 401 | D563CA141AF6DD6400E2F7C8 /* Release */, 402 | ); 403 | defaultConfigurationIsVisible = 0; 404 | defaultConfigurationName = Release; 405 | }; 406 | D563CA151AF6DD6400E2F7C8 /* Build configuration list for PBXNativeTarget "Parallax" */ = { 407 | isa = XCConfigurationList; 408 | buildConfigurations = ( 409 | D563CA161AF6DD6400E2F7C8 /* Debug */, 410 | D563CA171AF6DD6400E2F7C8 /* Release */, 411 | ); 412 | defaultConfigurationIsVisible = 0; 413 | defaultConfigurationName = Release; 414 | }; 415 | /* End XCConfigurationList section */ 416 | }; 417 | rootObject = D563C9EE1AF6DD6400E2F7C8 /* Project object */; 418 | } 419 | -------------------------------------------------------------------------------- /Example/Parallax/Parallax.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Parallax/Parallax.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/Parallax/Parallax/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @UIApplicationMain 4 | class AppDelegate: UIResponder, UIApplicationDelegate { 5 | var window: UIWindow? 6 | 7 | private lazy var navigationController: UINavigationController = .init( 8 | rootViewController: self.presentationController 9 | ) 10 | private lazy var presentationController: ViewController = .init(pages: []) 11 | 12 | func application(_ application: UIApplication, 13 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 14 | UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default) 15 | UINavigationBar.appearance().barStyle = .default 16 | UINavigationBar.appearance().shadowImage = UIImage() 17 | UINavigationBar.appearance().isTranslucent = true 18 | 19 | window = UIWindow(frame: UIScreen.main.bounds) 20 | window?.rootViewController = navigationController 21 | window?.makeKeyAndVisible() 22 | 23 | return true 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 22 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations~ipad 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationPortraitUpsideDown 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "ipad", 5 | "size" : "29x29", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "ipad", 10 | "size" : "29x29", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "ipad", 15 | "size" : "40x40", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "40x40", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "76x76", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "76x76", 31 | "scale" : "2x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Bus.imageset/Bus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Bus.imageset/Bus.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Bus.imageset/Bus@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Bus.imageset/Bus@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Bus.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Bus.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Bus@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Clouds.imageset/Clouds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Clouds.imageset/Clouds.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Clouds.imageset/Clouds@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Clouds.imageset/Clouds@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Clouds.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Clouds.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Clouds@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Hills.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Hills.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Hills@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Hills.imageset/Hills.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Hills.imageset/Hills.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Hills.imageset/Hills@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Hills.imageset/Hills@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Houses.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Houses.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Houses@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Houses.imageset/Houses.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Houses.imageset/Houses.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Houses.imageset/Houses@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Houses.imageset/Houses@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Mountains.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Mountains.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Mountains@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Mountains.imageset/Mountains.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Mountains.imageset/Mountains.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Mountains.imageset/Mountains@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Mountains.imageset/Mountains@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Roadlines.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Roadlines.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Roadlines@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Roadlines.imageset/Roadlines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Roadlines.imageset/Roadlines.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Roadlines.imageset/Roadlines@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Roadlines.imageset/Roadlines@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Sun.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Sun.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Sun@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Sun.imageset/Sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Sun.imageset/Sun.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Sun.imageset/Sun@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Sun.imageset/Sun@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Trees.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Trees.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Trees@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Trees.imageset/Trees.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Trees.imageset/Trees.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Trees.imageset/Trees@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Trees.imageset/Trees@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Truck.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Truck.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Truck@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Truck.imageset/Truck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Truck.imageset/Truck.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/Resources/Images.xcassets/Truck.imageset/Truck@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Parallax/Parallax/Resources/Images.xcassets/Truck.imageset/Truck@2x.png -------------------------------------------------------------------------------- /Example/Parallax/Parallax/ViewController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Hue 3 | import Presentation 4 | 5 | class ViewController: PresentationController { 6 | private struct BackgroundImage { 7 | let name: String 8 | let left: CGFloat 9 | let top: CGFloat 10 | let speed: CGFloat 11 | 12 | init(name: String, left: CGFloat, top: CGFloat, speed: CGFloat) { 13 | self.name = name 14 | self.left = left 15 | self.top = top 16 | self.speed = speed 17 | } 18 | 19 | func positionAt(_ index: Int) -> Position? { 20 | var position: Position? 21 | 22 | if index == 0 || speed != 0.0 { 23 | let currentLeft = left + CGFloat(index) * speed 24 | position = Position(left: currentLeft, top: top) 25 | } 26 | 27 | return position 28 | } 29 | } 30 | 31 | private lazy var leftButton: UIBarButtonItem = { [unowned self] in 32 | let leftButton = UIBarButtonItem( 33 | title: "Previous", 34 | style: .plain, 35 | target: self, 36 | action: #selector(moveBack)) 37 | 38 | leftButton.setTitleTextAttributes( 39 | [NSAttributedStringKey.foregroundColor : UIColor.black], 40 | for: .normal 41 | ) 42 | 43 | return leftButton 44 | }() 45 | 46 | private lazy var rightButton: UIBarButtonItem = { [unowned self] in 47 | let rightButton = UIBarButtonItem( 48 | title: "Next", 49 | style: .plain, 50 | target: self, 51 | action: #selector(moveForward) 52 | ) 53 | 54 | rightButton.setTitleTextAttributes( 55 | [NSAttributedStringKey.foregroundColor : UIColor.black], 56 | for: .normal 57 | ) 58 | 59 | return rightButton 60 | }() 61 | 62 | override func viewDidLoad() { 63 | super.viewDidLoad() 64 | 65 | setNavigationTitle = false 66 | navigationItem.leftBarButtonItem = leftButton 67 | navigationItem.rightBarButtonItem = rightButton 68 | view.backgroundColor = UIColor(hex: "FFBC00") 69 | 70 | configureSlides() 71 | configureBackground() 72 | } 73 | 74 | // MARK: - Configuration 75 | 76 | private func configureSlides() { 77 | let ratio: CGFloat = UIDevice.current.userInterfaceIdiom == .pad ? 1 : 0.6 78 | let font = UIFont(name: "HelveticaNeue", size: 34.0 * ratio)! 79 | let color = UIColor(hex: "FFE8A9") 80 | let paragraphStyle = NSMutableParagraphStyle() 81 | paragraphStyle.alignment = NSTextAlignment.center 82 | 83 | let attributes = [ 84 | NSAttributedStringKey.font: font, 85 | NSAttributedStringKey.foregroundColor: color, 86 | NSAttributedStringKey.paragraphStyle: paragraphStyle 87 | ] 88 | 89 | let titles = [ 90 | "Parallax is a displacement or difference in the apparent position of an object viewed along two different lines of sight.", 91 | "It's measured by the angle or semi-angle of inclination between those two lines.", 92 | "The term is derived from the Greek word παράλλαξις (parallaxis), meaning 'alteration'.", 93 | "Nearby objects have a larger parallax than more distant objects when observed from different positions.", 94 | "http://en.wikipedia.org/wiki/Parallax"].map { title -> Content in 95 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: 550 * ratio, height: 200 * ratio)) 96 | label.numberOfLines = 5 97 | label.attributedText = NSAttributedString(string: title, attributes: attributes) 98 | let position = Position(left: 0.7, top: 0.35) 99 | 100 | return Content(view: label, position: position) 101 | } 102 | 103 | var slides = [SlideController]() 104 | 105 | for index in 0...4 { 106 | let controller = SlideController(contents: [titles[index]]) 107 | controller.add(animations: [Content.centerTransition(forSlideContent: titles[index])]) 108 | slides.append(controller) 109 | } 110 | 111 | add(slides) 112 | } 113 | 114 | private func configureBackground() { 115 | let backgroundImages = [ 116 | BackgroundImage(name: "Trees", left: 0.0, top: 0.743, speed: -0.3), 117 | BackgroundImage(name: "Bus", left: 0.02, top: 0.77, speed: 0.25), 118 | BackgroundImage(name: "Truck", left: 1.3, top: 0.73, speed: -1.5), 119 | BackgroundImage(name: "Roadlines", left: 0.0, top: 0.79, speed: -0.24), 120 | BackgroundImage(name: "Houses", left: 0.0, top: 0.627, speed: -0.16), 121 | BackgroundImage(name: "Hills", left: 0.0, top: 0.51, speed: -0.08), 122 | BackgroundImage(name: "Mountains", left: 0.0, top: 0.29, speed: 0.0), 123 | BackgroundImage(name: "Clouds", left: -0.415, top: 0.14, speed: 0.18), 124 | BackgroundImage(name: "Sun", left: 0.8, top: 0.07, speed: 0.0) 125 | ] 126 | 127 | var contents = [Content]() 128 | 129 | for backgroundImage in backgroundImages { 130 | let imageView = UIImageView(image: UIImage(named: backgroundImage.name)) 131 | if let position = backgroundImage.positionAt(0) { 132 | contents.append(Content(view: imageView, position: position, centered: false)) 133 | } 134 | } 135 | 136 | addToBackground(contents) 137 | 138 | for row in 1...4 { 139 | for (column, backgroundImage) in backgroundImages.enumerated() { 140 | if let position = backgroundImage.positionAt(row), let content = contents.at(column) { 141 | addAnimation(TransitionAnimation(content: content, destination: position, 142 | duration: 2.0, damping: 1.0), forPage: row) 143 | } 144 | } 145 | } 146 | 147 | let groundView = UIView(frame: CGRect(x: 0, y: 0, width: 1024, height: 60)) 148 | groundView.backgroundColor = UIColor(hex: "FFCD41") 149 | 150 | let groundContent = Content( 151 | view: groundView, 152 | position: Position(left: 0.0, bottom: 0.063), 153 | centered: false 154 | ) 155 | 156 | contents.append(groundContent) 157 | addToBackground([groundContent]) 158 | } 159 | } 160 | 161 | private extension Array { 162 | func at(_ index: Int?) -> Element? { 163 | var object: Element? 164 | if let index = index , index >= 0 && index < endIndex { 165 | object = self[index] 166 | } 167 | 168 | return object 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /Example/Parallax/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | platform :ios, '9.0' 4 | 5 | pod 'Presentation', path: '../../' 6 | pod 'Hue' 7 | 8 | target 'Parallax' 9 | -------------------------------------------------------------------------------- /Example/Parallax/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Hue (3.0.1) 3 | - Pages (2.0.2) 4 | - Presentation (4.1.0): 5 | - Pages (~> 2.0) 6 | 7 | DEPENDENCIES: 8 | - Hue 9 | - Presentation (from `../../`) 10 | 11 | EXTERNAL SOURCES: 12 | Presentation: 13 | :path: ../../ 14 | 15 | SPEC CHECKSUMS: 16 | Hue: 93e852fa6211ab35922ad8c293f51c43d6c79eb2 17 | Pages: 5564ac6035c48fef7a837049314f57507d263b11 18 | Presentation: b717a7e0bff6af8e028998269114a344d5c114e4 19 | 20 | PODFILE CHECKSUM: 979718cbe7e3509ed288250a31b6c6036f4f9943 21 | 22 | COCOAPODS: 1.4.0 23 | -------------------------------------------------------------------------------- /Example/Tutorial/.swift-version: -------------------------------------------------------------------------------- 1 | 4.0 2 | -------------------------------------------------------------------------------- /Example/Tutorial/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | 3 | use_frameworks! 4 | 5 | platform :ios, '9.0' 6 | 7 | pod 'Presentation', path: '../../' 8 | pod 'Hue' 9 | 10 | target 'Tutorial' 11 | -------------------------------------------------------------------------------- /Example/Tutorial/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Hue (3.0.1) 3 | - Pages (2.0.2) 4 | - Presentation (4.1.0): 5 | - Pages (~> 2.0) 6 | 7 | DEPENDENCIES: 8 | - Hue 9 | - Presentation (from `../../`) 10 | 11 | EXTERNAL SOURCES: 12 | Presentation: 13 | :path: ../../ 14 | 15 | SPEC CHECKSUMS: 16 | Hue: 93e852fa6211ab35922ad8c293f51c43d6c79eb2 17 | Pages: 5564ac6035c48fef7a837049314f57507d263b11 18 | Presentation: b717a7e0bff6af8e028998269114a344d5c114e4 19 | 20 | PODFILE CHECKSUM: fdf662532b7595886c0398895df5b6e99fbfa147 21 | 22 | COCOAPODS: 1.4.0 23 | -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2DCCF82811EB3F02E430E820 /* Pods_Tutorial.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E054AB64D7F047E189E0676 /* Pods_Tutorial.framework */; }; 11 | D59807741AF6A8AB004B6D3A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D598076E1AF6A8AB004B6D3A /* AppDelegate.swift */; }; 12 | D59807751AF6A8AB004B6D3A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = D598076F1AF6A8AB004B6D3A /* LaunchScreen.xib */; }; 13 | D59807771AF6A8AB004B6D3A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D59807731AF6A8AB004B6D3A /* Images.xcassets */; }; 14 | /* End PBXBuildFile section */ 15 | 16 | /* Begin PBXFileReference section */ 17 | 0E054AB64D7F047E189E0676 /* Pods_Tutorial.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tutorial.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 18 | 2CDA8E7FFA227995DDF8F400 /* Pods-Tutorial.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tutorial/Pods-Tutorial.debug.xcconfig"; sourceTree = ""; }; 19 | 6D4A68838D32D2494868CDBA /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | D54221861AF64A7000F4E9A8 /* Tutorial.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tutorial.app; sourceTree = BUILT_PRODUCTS_DIR; }; 21 | D598076E1AF6A8AB004B6D3A /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 22 | D59807701AF6A8AB004B6D3A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 23 | D59807711AF6A8AB004B6D3A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 24 | D59807731AF6A8AB004B6D3A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 25 | E96A7DBC0B2631A864975E3A /* Pods-Tutorial.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tutorial.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tutorial/Pods-Tutorial.release.xcconfig"; sourceTree = ""; }; 26 | /* End PBXFileReference section */ 27 | 28 | /* Begin PBXFrameworksBuildPhase section */ 29 | D54221831AF64A7000F4E9A8 /* Frameworks */ = { 30 | isa = PBXFrameworksBuildPhase; 31 | buildActionMask = 2147483647; 32 | files = ( 33 | 2DCCF82811EB3F02E430E820 /* Pods_Tutorial.framework in Frameworks */, 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXFrameworksBuildPhase section */ 38 | 39 | /* Begin PBXGroup section */ 40 | 10D1E0BB4671824DE641F785 /* Pods */ = { 41 | isa = PBXGroup; 42 | children = ( 43 | 2CDA8E7FFA227995DDF8F400 /* Pods-Tutorial.debug.xcconfig */, 44 | E96A7DBC0B2631A864975E3A /* Pods-Tutorial.release.xcconfig */, 45 | ); 46 | name = Pods; 47 | sourceTree = ""; 48 | }; 49 | 7BB385731A23BFD439DC4FDF /* Frameworks */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 6D4A68838D32D2494868CDBA /* Pods.framework */, 53 | 0E054AB64D7F047E189E0676 /* Pods_Tutorial.framework */, 54 | ); 55 | name = Frameworks; 56 | sourceTree = ""; 57 | }; 58 | D542217D1AF64A7000F4E9A8 = { 59 | isa = PBXGroup; 60 | children = ( 61 | D598076D1AF6A8AB004B6D3A /* Tutorial */, 62 | D54221871AF64A7000F4E9A8 /* Products */, 63 | 7BB385731A23BFD439DC4FDF /* Frameworks */, 64 | 10D1E0BB4671824DE641F785 /* Pods */, 65 | ); 66 | sourceTree = ""; 67 | }; 68 | D54221871AF64A7000F4E9A8 /* Products */ = { 69 | isa = PBXGroup; 70 | children = ( 71 | D54221861AF64A7000F4E9A8 /* Tutorial.app */, 72 | ); 73 | name = Products; 74 | sourceTree = ""; 75 | }; 76 | D598076D1AF6A8AB004B6D3A /* Tutorial */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | D598076E1AF6A8AB004B6D3A /* AppDelegate.swift */, 80 | D598076F1AF6A8AB004B6D3A /* LaunchScreen.xib */, 81 | D59807711AF6A8AB004B6D3A /* Info.plist */, 82 | D59807721AF6A8AB004B6D3A /* Resources */, 83 | ); 84 | path = Tutorial; 85 | sourceTree = ""; 86 | }; 87 | D59807721AF6A8AB004B6D3A /* Resources */ = { 88 | isa = PBXGroup; 89 | children = ( 90 | D59807731AF6A8AB004B6D3A /* Images.xcassets */, 91 | ); 92 | path = Resources; 93 | sourceTree = ""; 94 | }; 95 | /* End PBXGroup section */ 96 | 97 | /* Begin PBXNativeTarget section */ 98 | D54221851AF64A7000F4E9A8 /* Tutorial */ = { 99 | isa = PBXNativeTarget; 100 | buildConfigurationList = D54221A51AF64A7000F4E9A8 /* Build configuration list for PBXNativeTarget "Tutorial" */; 101 | buildPhases = ( 102 | 207FA904D4A0136E51A77329 /* [CP] Check Pods Manifest.lock */, 103 | D54221821AF64A7000F4E9A8 /* Sources */, 104 | D54221831AF64A7000F4E9A8 /* Frameworks */, 105 | D54221841AF64A7000F4E9A8 /* Resources */, 106 | 98EF1B66773AF87D3D6A4C62 /* [CP] Embed Pods Frameworks */, 107 | 8058477F6FC36BF93DD6D31F /* [CP] Copy Pods Resources */, 108 | ); 109 | buildRules = ( 110 | ); 111 | dependencies = ( 112 | ); 113 | name = Tutorial; 114 | productName = Basic; 115 | productReference = D54221861AF64A7000F4E9A8 /* Tutorial.app */; 116 | productType = "com.apple.product-type.application"; 117 | }; 118 | /* End PBXNativeTarget section */ 119 | 120 | /* Begin PBXProject section */ 121 | D542217E1AF64A7000F4E9A8 /* Project object */ = { 122 | isa = PBXProject; 123 | attributes = { 124 | LastSwiftUpdateCheck = 0700; 125 | LastUpgradeCheck = 0900; 126 | ORGANIZATIONNAME = Hyper; 127 | TargetAttributes = { 128 | D54221851AF64A7000F4E9A8 = { 129 | CreatedOnToolsVersion = 6.3.1; 130 | LastSwiftMigration = 0900; 131 | }; 132 | }; 133 | }; 134 | buildConfigurationList = D54221811AF64A7000F4E9A8 /* Build configuration list for PBXProject "Tutorial" */; 135 | compatibilityVersion = "Xcode 3.2"; 136 | developmentRegion = English; 137 | hasScannedForEncodings = 0; 138 | knownRegions = ( 139 | en, 140 | Base, 141 | ); 142 | mainGroup = D542217D1AF64A7000F4E9A8; 143 | productRefGroup = D54221871AF64A7000F4E9A8 /* Products */; 144 | projectDirPath = ""; 145 | projectRoot = ""; 146 | targets = ( 147 | D54221851AF64A7000F4E9A8 /* Tutorial */, 148 | ); 149 | }; 150 | /* End PBXProject section */ 151 | 152 | /* Begin PBXResourcesBuildPhase section */ 153 | D54221841AF64A7000F4E9A8 /* Resources */ = { 154 | isa = PBXResourcesBuildPhase; 155 | buildActionMask = 2147483647; 156 | files = ( 157 | D59807771AF6A8AB004B6D3A /* Images.xcassets in Resources */, 158 | D59807751AF6A8AB004B6D3A /* LaunchScreen.xib in Resources */, 159 | ); 160 | runOnlyForDeploymentPostprocessing = 0; 161 | }; 162 | /* End PBXResourcesBuildPhase section */ 163 | 164 | /* Begin PBXShellScriptBuildPhase section */ 165 | 207FA904D4A0136E51A77329 /* [CP] Check Pods Manifest.lock */ = { 166 | isa = PBXShellScriptBuildPhase; 167 | buildActionMask = 2147483647; 168 | files = ( 169 | ); 170 | inputPaths = ( 171 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 172 | "${PODS_ROOT}/Manifest.lock", 173 | ); 174 | name = "[CP] Check Pods Manifest.lock"; 175 | outputPaths = ( 176 | "$(DERIVED_FILE_DIR)/Pods-Tutorial-checkManifestLockResult.txt", 177 | ); 178 | runOnlyForDeploymentPostprocessing = 0; 179 | shellPath = /bin/sh; 180 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 181 | showEnvVarsInLog = 0; 182 | }; 183 | 8058477F6FC36BF93DD6D31F /* [CP] Copy Pods Resources */ = { 184 | isa = PBXShellScriptBuildPhase; 185 | buildActionMask = 2147483647; 186 | files = ( 187 | ); 188 | inputPaths = ( 189 | ); 190 | name = "[CP] Copy Pods Resources"; 191 | outputPaths = ( 192 | ); 193 | runOnlyForDeploymentPostprocessing = 0; 194 | shellPath = /bin/sh; 195 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tutorial/Pods-Tutorial-resources.sh\"\n"; 196 | showEnvVarsInLog = 0; 197 | }; 198 | 98EF1B66773AF87D3D6A4C62 /* [CP] Embed Pods Frameworks */ = { 199 | isa = PBXShellScriptBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | ); 203 | inputPaths = ( 204 | "${SRCROOT}/Pods/Target Support Files/Pods-Tutorial/Pods-Tutorial-frameworks.sh", 205 | "${BUILT_PRODUCTS_DIR}/Hue/Hue.framework", 206 | "${BUILT_PRODUCTS_DIR}/Pages/Pages.framework", 207 | "${BUILT_PRODUCTS_DIR}/Presentation/Presentation.framework", 208 | ); 209 | name = "[CP] Embed Pods Frameworks"; 210 | outputPaths = ( 211 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Hue.framework", 212 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Pages.framework", 213 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Presentation.framework", 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | shellPath = /bin/sh; 217 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tutorial/Pods-Tutorial-frameworks.sh\"\n"; 218 | showEnvVarsInLog = 0; 219 | }; 220 | /* End PBXShellScriptBuildPhase section */ 221 | 222 | /* Begin PBXSourcesBuildPhase section */ 223 | D54221821AF64A7000F4E9A8 /* Sources */ = { 224 | isa = PBXSourcesBuildPhase; 225 | buildActionMask = 2147483647; 226 | files = ( 227 | D59807741AF6A8AB004B6D3A /* AppDelegate.swift in Sources */, 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | }; 231 | /* End PBXSourcesBuildPhase section */ 232 | 233 | /* Begin PBXVariantGroup section */ 234 | D598076F1AF6A8AB004B6D3A /* LaunchScreen.xib */ = { 235 | isa = PBXVariantGroup; 236 | children = ( 237 | D59807701AF6A8AB004B6D3A /* Base */, 238 | ); 239 | name = LaunchScreen.xib; 240 | sourceTree = ""; 241 | }; 242 | /* End PBXVariantGroup section */ 243 | 244 | /* Begin XCBuildConfiguration section */ 245 | D54221A31AF64A7000F4E9A8 /* Debug */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | ALWAYS_SEARCH_USER_PATHS = NO; 249 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 250 | CLANG_CXX_LIBRARY = "libc++"; 251 | CLANG_ENABLE_MODULES = YES; 252 | CLANG_ENABLE_OBJC_ARC = YES; 253 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 254 | CLANG_WARN_BOOL_CONVERSION = YES; 255 | CLANG_WARN_COMMA = YES; 256 | CLANG_WARN_CONSTANT_CONVERSION = YES; 257 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 258 | CLANG_WARN_EMPTY_BODY = YES; 259 | CLANG_WARN_ENUM_CONVERSION = YES; 260 | CLANG_WARN_INFINITE_RECURSION = YES; 261 | CLANG_WARN_INT_CONVERSION = YES; 262 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 263 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 264 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 265 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 266 | CLANG_WARN_STRICT_PROTOTYPES = YES; 267 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 268 | CLANG_WARN_UNREACHABLE_CODE = YES; 269 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 270 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 271 | COPY_PHASE_STRIP = NO; 272 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 273 | ENABLE_STRICT_OBJC_MSGSEND = YES; 274 | ENABLE_TESTABILITY = YES; 275 | GCC_C_LANGUAGE_STANDARD = gnu99; 276 | GCC_DYNAMIC_NO_PIC = NO; 277 | GCC_NO_COMMON_BLOCKS = YES; 278 | GCC_OPTIMIZATION_LEVEL = 0; 279 | GCC_PREPROCESSOR_DEFINITIONS = ( 280 | "DEBUG=1", 281 | "$(inherited)", 282 | ); 283 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 284 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 285 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 286 | GCC_WARN_UNDECLARED_SELECTOR = YES; 287 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 288 | GCC_WARN_UNUSED_FUNCTION = YES; 289 | GCC_WARN_UNUSED_VARIABLE = YES; 290 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 291 | MTL_ENABLE_DEBUG_INFO = YES; 292 | ONLY_ACTIVE_ARCH = YES; 293 | SDKROOT = iphoneos; 294 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 295 | TARGETED_DEVICE_FAMILY = 2; 296 | }; 297 | name = Debug; 298 | }; 299 | D54221A41AF64A7000F4E9A8 /* Release */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | ALWAYS_SEARCH_USER_PATHS = NO; 303 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 304 | CLANG_CXX_LIBRARY = "libc++"; 305 | CLANG_ENABLE_MODULES = YES; 306 | CLANG_ENABLE_OBJC_ARC = YES; 307 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 308 | CLANG_WARN_BOOL_CONVERSION = YES; 309 | CLANG_WARN_COMMA = YES; 310 | CLANG_WARN_CONSTANT_CONVERSION = YES; 311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 312 | CLANG_WARN_EMPTY_BODY = YES; 313 | CLANG_WARN_ENUM_CONVERSION = YES; 314 | CLANG_WARN_INFINITE_RECURSION = YES; 315 | CLANG_WARN_INT_CONVERSION = YES; 316 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 317 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 318 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 319 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 320 | CLANG_WARN_STRICT_PROTOTYPES = YES; 321 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 322 | CLANG_WARN_UNREACHABLE_CODE = YES; 323 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 324 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 325 | COPY_PHASE_STRIP = NO; 326 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 327 | ENABLE_NS_ASSERTIONS = NO; 328 | ENABLE_STRICT_OBJC_MSGSEND = YES; 329 | GCC_C_LANGUAGE_STANDARD = gnu99; 330 | GCC_NO_COMMON_BLOCKS = YES; 331 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 332 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 333 | GCC_WARN_UNDECLARED_SELECTOR = YES; 334 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 335 | GCC_WARN_UNUSED_FUNCTION = YES; 336 | GCC_WARN_UNUSED_VARIABLE = YES; 337 | IPHONEOS_DEPLOYMENT_TARGET = 8.3; 338 | MTL_ENABLE_DEBUG_INFO = NO; 339 | SDKROOT = iphoneos; 340 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 341 | TARGETED_DEVICE_FAMILY = 2; 342 | VALIDATE_PRODUCT = YES; 343 | }; 344 | name = Release; 345 | }; 346 | D54221A61AF64A7000F4E9A8 /* Debug */ = { 347 | isa = XCBuildConfiguration; 348 | baseConfigurationReference = 2CDA8E7FFA227995DDF8F400 /* Pods-Tutorial.debug.xcconfig */; 349 | buildSettings = { 350 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 351 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 352 | INFOPLIST_FILE = Tutorial/Info.plist; 353 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 354 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 355 | PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.$(PRODUCT_NAME:rfc1034identifier)"; 356 | PRODUCT_NAME = Tutorial; 357 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 358 | SWIFT_VERSION = 4.0; 359 | TARGETED_DEVICE_FAMILY = "1,2"; 360 | }; 361 | name = Debug; 362 | }; 363 | D54221A71AF64A7000F4E9A8 /* Release */ = { 364 | isa = XCBuildConfiguration; 365 | baseConfigurationReference = E96A7DBC0B2631A864975E3A /* Pods-Tutorial.release.xcconfig */; 366 | buildSettings = { 367 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 368 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 369 | INFOPLIST_FILE = Tutorial/Info.plist; 370 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 371 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 372 | PRODUCT_BUNDLE_IDENTIFIER = "no.hyper.$(PRODUCT_NAME:rfc1034identifier)"; 373 | PRODUCT_NAME = Tutorial; 374 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 375 | SWIFT_VERSION = 4.0; 376 | TARGETED_DEVICE_FAMILY = "1,2"; 377 | }; 378 | name = Release; 379 | }; 380 | /* End XCBuildConfiguration section */ 381 | 382 | /* Begin XCConfigurationList section */ 383 | D54221811AF64A7000F4E9A8 /* Build configuration list for PBXProject "Tutorial" */ = { 384 | isa = XCConfigurationList; 385 | buildConfigurations = ( 386 | D54221A31AF64A7000F4E9A8 /* Debug */, 387 | D54221A41AF64A7000F4E9A8 /* Release */, 388 | ); 389 | defaultConfigurationIsVisible = 0; 390 | defaultConfigurationName = Release; 391 | }; 392 | D54221A51AF64A7000F4E9A8 /* Build configuration list for PBXNativeTarget "Tutorial" */ = { 393 | isa = XCConfigurationList; 394 | buildConfigurations = ( 395 | D54221A61AF64A7000F4E9A8 /* Debug */, 396 | D54221A71AF64A7000F4E9A8 /* Release */, 397 | ); 398 | defaultConfigurationIsVisible = 0; 399 | defaultConfigurationName = Release; 400 | }; 401 | /* End XCConfigurationList section */ 402 | }; 403 | rootObject = D542217E1AF64A7000F4E9A8 /* Project object */; 404 | } 405 | -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Hue 3 | import Presentation 4 | 5 | @UIApplicationMain 6 | class AppDelegate: UIResponder, UIApplicationDelegate { 7 | var window: UIWindow? 8 | 9 | private lazy var navigationController: UINavigationController = { [unowned self] in 10 | let controller = UINavigationController(rootViewController: self.presentationController) 11 | controller.view.backgroundColor = UIColor(hex:"FF5703") 12 | return controller 13 | }() 14 | 15 | private lazy var presentationController: PresentationController = { 16 | let controller = PresentationController(pages: []) 17 | controller.setNavigationTitle = false 18 | return controller 19 | }() 20 | 21 | private lazy var leftButton: UIBarButtonItem = { [unowned self] in 22 | let button = UIBarButtonItem( 23 | title: "Previous page", 24 | style: .plain, 25 | target: self.presentationController, 26 | action: #selector(PresentationController.moveBack) 27 | ) 28 | 29 | button.setTitleTextAttributes( 30 | [NSAttributedStringKey.foregroundColor: UIColor.white], 31 | for: .normal 32 | ) 33 | 34 | return button 35 | }() 36 | 37 | private lazy var rightButton: UIBarButtonItem = { [unowned self] in 38 | let button = UIBarButtonItem( 39 | title: "Next page", 40 | style: .plain, 41 | target: self.presentationController, 42 | action: #selector(PresentationController.moveForward) 43 | ) 44 | 45 | button.setTitleTextAttributes( 46 | [NSAttributedStringKey.foregroundColor: UIColor.white], 47 | for: .normal 48 | ) 49 | 50 | return button 51 | }() 52 | 53 | func application(_ application: UIApplication, 54 | didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 55 | UINavigationBar.appearance().barTintColor = UIColor(hex: "FF5703") 56 | UINavigationBar.appearance().barStyle = .blackTranslucent 57 | 58 | presentationController.navigationItem.leftBarButtonItem = leftButton 59 | presentationController.navigationItem.rightBarButtonItem = rightButton 60 | 61 | configureSlides() 62 | configureBackground() 63 | 64 | window = UIWindow(frame: UIScreen.main.bounds) 65 | window?.rootViewController = navigationController 66 | window?.makeKeyAndVisible() 67 | 68 | return true 69 | } 70 | 71 | private func configureSlides() { 72 | let ratio: CGFloat = UIDevice.current.userInterfaceIdiom == .pad ? 1 : 0.4 73 | let font = UIFont(name: "ArialRoundedMTBold", size: 42.0 * ratio)! 74 | let color = UIColor.white 75 | let paragraphStyle = NSMutableParagraphStyle() 76 | paragraphStyle.alignment = .center 77 | 78 | let attributes = [NSAttributedStringKey.font: font, NSAttributedStringKey.foregroundColor: color, 79 | NSAttributedStringKey.paragraphStyle: paragraphStyle] 80 | 81 | let titles = ["Tutorial on how to make a profit", "Step I", "Step II", "Step III", "Thanks"].map { 82 | Content.content(forTitle: $0, attributes: attributes) 83 | } 84 | let texts = ["", "Collect underpants\n💭", "🎅🎅🏻🎅🏼🎅🏽🎅🏾🎅🏿", "Profit\n💸", ""].map { 85 | Content.content(forText: $0, attributes: attributes) 86 | } 87 | 88 | var slides = [SlideController]() 89 | 90 | for index in 0...4 { 91 | let controller = SlideController(contents: [titles[index], texts[index]]) 92 | 93 | if index == 0 { 94 | titles[index].position.left = 0.5 95 | 96 | controller.add(animations: [ 97 | DissolveAnimation(content: titles[index], duration: 2.0, delay: 1.0, initial: true)]) 98 | } else { 99 | controller.add(animations: [ 100 | Content.centerTransition(forSlideContent: titles[index]), 101 | Content.centerTransition(forSlideContent: texts[index])]) 102 | } 103 | 104 | slides.append(controller) 105 | } 106 | 107 | slides[4].add(content: Content.content(forImage: UIImage(named: "HyperLogo")!)) 108 | 109 | presentationController.add(slides) 110 | } 111 | 112 | private func configureBackground() { 113 | let images = ["Cloud1", "Cloud2", "Cloud1"].map { UIImageView(image: UIImage(named: $0)) } 114 | let content1 = Content(view: images[0], position: Position(left: -0.3, top: 0.2)) 115 | let content2 = Content(view: images[1], position: Position(right: -0.3, top: 0.22)) 116 | let content3 = Content(view: images[2], position: Position(left: 0.5, top: 0.5)) 117 | 118 | presentationController.addToBackground([content1, content2, content3]) 119 | 120 | presentationController.addAnimations([ 121 | TransitionAnimation(content: content1, destination: Position(left: 0.2, top: 0.2)), 122 | TransitionAnimation(content: content2, destination: Position(right: 0.3, top: 0.22)), 123 | PopAnimation(content: content3, duration: 1.0) 124 | ], forPage: 0) 125 | 126 | presentationController.addAnimations([ 127 | TransitionAnimation(content: content1, destination: Position(left: 0.3, top: 0.2)), 128 | TransitionAnimation(content: content2, destination: Position(right: 0.4, top: 0.22)) 129 | ], forPage: 1) 130 | 131 | presentationController.addAnimations([ 132 | TransitionAnimation(content: content1, destination: Position(left: 0.5, top: 0.2)), 133 | TransitionAnimation(content: content2, destination: Position(right: 0.5, top: 0.22)) 134 | ], forPage: 2) 135 | 136 | presentationController.addAnimations([ 137 | TransitionAnimation(content: content1, destination: Position(left: 0.6, top: 0.2)), 138 | TransitionAnimation(content: content2, destination: Position(right: 0.7, top: 0.22)) 139 | ], forPage: 3) 140 | 141 | presentationController.addAnimations([ 142 | TransitionAnimation(content: content1, destination: Position(left: 0.8, top: 0.2)), 143 | TransitionAnimation(content: content2, destination: Position(right: 0.9, top: 0.22)) 144 | ], forPage: 4) 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations~ipad 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationPortraitUpsideDown 35 | UIInterfaceOrientationLandscapeLeft 36 | UIInterfaceOrientationLandscapeRight 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "ipad", 5 | "size" : "29x29", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "ipad", 10 | "size" : "29x29", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "ipad", 15 | "size" : "40x40", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "size" : "40x40", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "size" : "76x76", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "ipad", 30 | "size" : "76x76", 31 | "scale" : "2x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud1.imageset/Cloud1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud1.imageset/Cloud1.png -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud1.imageset/Cloud1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud1.imageset/Cloud1@2x.png -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Cloud1.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Cloud1@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud2.imageset/Cloud2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud2.imageset/Cloud2.png -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud2.imageset/Cloud2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud2.imageset/Cloud2@2x.png -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/Cloud2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "Cloud2.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "Cloud2@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/HyperLogo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "HyperLogo.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "HyperLogo@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/HyperLogo.imageset/HyperLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Tutorial/Tutorial/Resources/Images.xcassets/HyperLogo.imageset/HyperLogo.png -------------------------------------------------------------------------------- /Example/Tutorial/Tutorial/Resources/Images.xcassets/HyperLogo.imageset/HyperLogo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Example/Tutorial/Tutorial/Resources/Images.xcassets/HyperLogo.imageset/HyperLogo@2x.png -------------------------------------------------------------------------------- /Images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hyperoslo/Presentation/811bccdcf448ba77540e128e73752dccd0a4f6ed/Images/logo.png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Licensed under the **MIT** license 2 | 3 | > Copyright (c) 2015 Hyper 4 | > 5 | > Permission is hereby granted, free of charge, to any person obtaining 6 | > a copy of this software and associated documentation files (the 7 | > "Software"), to deal in the Software without restriction, including 8 | > without limitation the rights to use, copy, modify, merge, publish, 9 | > distribute, sublicense, and/or sell copies of the Software, and to 10 | > permit persons to whom the Software is furnished to do so, subject to 11 | > the following conditions: 12 | > 13 | > The above copyright notice and this permission notice shall be 14 | > included in all copies or substantial portions of the Software. 15 | > 16 | > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | > EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | > MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | > IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | > CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 21 | > TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 22 | > SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Pod/Pod.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | BDA1580B1AD7ED450011D55A /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BDA1580A1AD7ED450011D55A /* Pods.framework */; }; 11 | D50583F31AEFD983003D8F05 /* SpecHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = D50583F21AEFD983003D8F05 /* SpecHelper.swift */; }; 12 | D516EFF11AF6B800002BE7CA /* DissolveAnimationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D516EFF01AF6B800002BE7CA /* DissolveAnimationSpec.swift */; }; 13 | D526B3CB1AF0EA4600A9CA0F /* ContentSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D526B3CA1AF0EA4600A9CA0F /* ContentSpec.swift */; }; 14 | D5A130641AEF99BD0081DAFE /* CGPointExtensionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A130631AEF99BD0081DAFE /* CGPointExtensionSpec.swift */; }; 15 | D5A1306D1AEF9AF30081DAFE /* TransitionAnimationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A1306C1AEF9AF30081DAFE /* TransitionAnimationSpec.swift */; }; 16 | D5A130711AEF9B060081DAFE /* PopAnimationSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A130701AEF9B060081DAFE /* PopAnimationSpec.swift */; }; 17 | D5C28A2D1AEFCFDB00DCC96D /* PositionSpec.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5C28A2C1AEFCFDB00DCC96D /* PositionSpec.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 146D72AC1AB782920058798C /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 146D72B11AB782920058798C /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 23 | 14C136511AB784B200B7B07A /* .travis.yml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = .travis.yml; path = ../.travis.yml; sourceTree = ""; }; 24 | 14C136521AB784B200B7B07A /* CONTRIBUTING.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = CONTRIBUTING.md; path = ../CONTRIBUTING.md; sourceTree = ""; }; 25 | 14C136541AB784B200B7B07A /* LICENSE.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = LICENSE.md; path = ../LICENSE.md; sourceTree = ""; }; 26 | 14C136551AB784B200B7B07A /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = ""; }; 27 | 30212F8CDFCE2FA3013BEA16 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; 28 | 48D596C5F7386460518077F9 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; 29 | 52C4B602692A15E8F471B50B /* Pods-Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.debug.xcconfig"; sourceTree = ""; }; 30 | 7BDF425D7A39B12C5A23B2A0 /* Pods-Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Tests.release.xcconfig"; path = "Pods/Target Support Files/Pods-Tests/Pods-Tests.release.xcconfig"; sourceTree = ""; }; 31 | BDA158081AD7ED3D0011D55A /* Pods.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pods.framework; path = "Pods/../build/Debug-iphoneos/Pods.framework"; sourceTree = ""; }; 32 | BDA1580A1AD7ED450011D55A /* Pods.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pods.framework; path = "Pods/../build/Debug-iphoneos/Pods.framework"; sourceTree = ""; }; 33 | D50583F21AEFD983003D8F05 /* SpecHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpecHelper.swift; sourceTree = ""; }; 34 | D516EFF01AF6B800002BE7CA /* DissolveAnimationSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DissolveAnimationSpec.swift; sourceTree = ""; }; 35 | D526B3CA1AF0EA4600A9CA0F /* ContentSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ContentSpec.swift; sourceTree = ""; }; 36 | D5A130631AEF99BD0081DAFE /* CGPointExtensionSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGPointExtensionSpec.swift; sourceTree = ""; }; 37 | D5A1306C1AEF9AF30081DAFE /* TransitionAnimationSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransitionAnimationSpec.swift; sourceTree = ""; }; 38 | D5A130701AEF9B060081DAFE /* PopAnimationSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PopAnimationSpec.swift; sourceTree = ""; }; 39 | D5C28A2C1AEFCFDB00DCC96D /* PositionSpec.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PositionSpec.swift; sourceTree = ""; }; 40 | F6FACB069003DC522C05C4C3 /* Pods_Tests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | 146D72A91AB782920058798C /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | BDA1580B1AD7ED450011D55A /* Pods.framework in Frameworks */, 49 | ); 50 | runOnlyForDeploymentPostprocessing = 0; 51 | }; 52 | /* End PBXFrameworksBuildPhase section */ 53 | 54 | /* Begin PBXGroup section */ 55 | 09E842F08B79D6D2634C2378 /* Frameworks */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | BDA1580A1AD7ED450011D55A /* Pods.framework */, 59 | BDA158081AD7ED3D0011D55A /* Pods.framework */, 60 | F6FACB069003DC522C05C4C3 /* Pods_Tests.framework */, 61 | ); 62 | name = Frameworks; 63 | sourceTree = ""; 64 | }; 65 | 146D728A1AB782920058798C = { 66 | isa = PBXGroup; 67 | children = ( 68 | 14C136501AB7849300B7B07A /* Metadata */, 69 | 146D72AF1AB782920058798C /* Tests */, 70 | 146D72941AB782920058798C /* Products */, 71 | 42C4F1AEEA311E9A13EB43E8 /* Pods */, 72 | 09E842F08B79D6D2634C2378 /* Frameworks */, 73 | ); 74 | indentWidth = 2; 75 | sourceTree = ""; 76 | tabWidth = 2; 77 | }; 78 | 146D72941AB782920058798C /* Products */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 146D72AC1AB782920058798C /* Tests.xctest */, 82 | ); 83 | name = Products; 84 | sourceTree = ""; 85 | }; 86 | 146D72AF1AB782920058798C /* Tests */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | D5E344401AE8E55A00F958CB /* Specs */, 90 | 146D72B01AB782920058798C /* Supporting Files */, 91 | ); 92 | path = Tests; 93 | sourceTree = ""; 94 | }; 95 | 146D72B01AB782920058798C /* Supporting Files */ = { 96 | isa = PBXGroup; 97 | children = ( 98 | 146D72B11AB782920058798C /* Info.plist */, 99 | ); 100 | name = "Supporting Files"; 101 | sourceTree = ""; 102 | }; 103 | 14C136501AB7849300B7B07A /* Metadata */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 14C136511AB784B200B7B07A /* .travis.yml */, 107 | 14C136521AB784B200B7B07A /* CONTRIBUTING.md */, 108 | 14C136541AB784B200B7B07A /* LICENSE.md */, 109 | 14C136551AB784B200B7B07A /* README.md */, 110 | ); 111 | name = Metadata; 112 | sourceTree = ""; 113 | }; 114 | 42C4F1AEEA311E9A13EB43E8 /* Pods */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 48D596C5F7386460518077F9 /* Pods.debug.xcconfig */, 118 | 30212F8CDFCE2FA3013BEA16 /* Pods.release.xcconfig */, 119 | 52C4B602692A15E8F471B50B /* Pods-Tests.debug.xcconfig */, 120 | 7BDF425D7A39B12C5A23B2A0 /* Pods-Tests.release.xcconfig */, 121 | ); 122 | name = Pods; 123 | sourceTree = ""; 124 | }; 125 | D50583F11AEFD954003D8F05 /* Helpers */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | D50583F21AEFD983003D8F05 /* SpecHelper.swift */, 129 | ); 130 | path = Helpers; 131 | sourceTree = ""; 132 | }; 133 | D5A130601AEF99430081DAFE /* Extensions */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | D5A130631AEF99BD0081DAFE /* CGPointExtensionSpec.swift */, 137 | ); 138 | path = Extensions; 139 | sourceTree = ""; 140 | }; 141 | D5A130691AEF9AC90081DAFE /* Animations */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | D5A130701AEF9B060081DAFE /* PopAnimationSpec.swift */, 145 | D5A1306C1AEF9AF30081DAFE /* TransitionAnimationSpec.swift */, 146 | D516EFF01AF6B800002BE7CA /* DissolveAnimationSpec.swift */, 147 | ); 148 | path = Animations; 149 | sourceTree = ""; 150 | }; 151 | D5E344401AE8E55A00F958CB /* Specs */ = { 152 | isa = PBXGroup; 153 | children = ( 154 | D50583F11AEFD954003D8F05 /* Helpers */, 155 | D5A130601AEF99430081DAFE /* Extensions */, 156 | D5A130691AEF9AC90081DAFE /* Animations */, 157 | D5C28A2C1AEFCFDB00DCC96D /* PositionSpec.swift */, 158 | D526B3CA1AF0EA4600A9CA0F /* ContentSpec.swift */, 159 | ); 160 | path = Specs; 161 | sourceTree = ""; 162 | }; 163 | /* End PBXGroup section */ 164 | 165 | /* Begin PBXNativeTarget section */ 166 | 146D72AB1AB782920058798C /* Tests */ = { 167 | isa = PBXNativeTarget; 168 | buildConfigurationList = 146D72B91AB782920058798C /* Build configuration list for PBXNativeTarget "Tests" */; 169 | buildPhases = ( 170 | 521002C5D51B6D391317105F /* Check Pods Manifest.lock */, 171 | 146D72A81AB782920058798C /* Sources */, 172 | 146D72A91AB782920058798C /* Frameworks */, 173 | 146D72AA1AB782920058798C /* Resources */, 174 | 1FB4FB02C00F9A40C82C3CEF /* Embed Pods Frameworks */, 175 | 41DA61D1CECB79C1D5CB9EB7 /* Copy Pods Resources */, 176 | ); 177 | buildRules = ( 178 | ); 179 | dependencies = ( 180 | ); 181 | name = Tests; 182 | productName = PodTests; 183 | productReference = 146D72AC1AB782920058798C /* Tests.xctest */; 184 | productType = "com.apple.product-type.bundle.unit-test"; 185 | }; 186 | /* End PBXNativeTarget section */ 187 | 188 | /* Begin PBXProject section */ 189 | 146D728B1AB782920058798C /* Project object */ = { 190 | isa = PBXProject; 191 | attributes = { 192 | LastUpgradeCheck = 0620; 193 | ORGANIZATIONNAME = Hyper; 194 | TargetAttributes = { 195 | 146D72AB1AB782920058798C = { 196 | CreatedOnToolsVersion = 6.2; 197 | }; 198 | }; 199 | }; 200 | buildConfigurationList = 146D728E1AB782920058798C /* Build configuration list for PBXProject "Pod" */; 201 | compatibilityVersion = "Xcode 3.2"; 202 | developmentRegion = English; 203 | hasScannedForEncodings = 0; 204 | knownRegions = ( 205 | en, 206 | Base, 207 | ); 208 | mainGroup = 146D728A1AB782920058798C; 209 | productRefGroup = 146D72941AB782920058798C /* Products */; 210 | projectDirPath = ""; 211 | projectRoot = ""; 212 | targets = ( 213 | 146D72AB1AB782920058798C /* Tests */, 214 | ); 215 | }; 216 | /* End PBXProject section */ 217 | 218 | /* Begin PBXResourcesBuildPhase section */ 219 | 146D72AA1AB782920058798C /* Resources */ = { 220 | isa = PBXResourcesBuildPhase; 221 | buildActionMask = 2147483647; 222 | files = ( 223 | ); 224 | runOnlyForDeploymentPostprocessing = 0; 225 | }; 226 | /* End PBXResourcesBuildPhase section */ 227 | 228 | /* Begin PBXShellScriptBuildPhase section */ 229 | 1FB4FB02C00F9A40C82C3CEF /* Embed Pods Frameworks */ = { 230 | isa = PBXShellScriptBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | ); 234 | inputPaths = ( 235 | ); 236 | name = "Embed Pods Frameworks"; 237 | outputPaths = ( 238 | ); 239 | runOnlyForDeploymentPostprocessing = 0; 240 | shellPath = /bin/sh; 241 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; 242 | showEnvVarsInLog = 0; 243 | }; 244 | 41DA61D1CECB79C1D5CB9EB7 /* Copy Pods Resources */ = { 245 | isa = PBXShellScriptBuildPhase; 246 | buildActionMask = 2147483647; 247 | files = ( 248 | ); 249 | inputPaths = ( 250 | ); 251 | name = "Copy Pods Resources"; 252 | outputPaths = ( 253 | ); 254 | runOnlyForDeploymentPostprocessing = 0; 255 | shellPath = /bin/sh; 256 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; 257 | showEnvVarsInLog = 0; 258 | }; 259 | 521002C5D51B6D391317105F /* Check Pods Manifest.lock */ = { 260 | isa = PBXShellScriptBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | ); 264 | inputPaths = ( 265 | ); 266 | name = "Check Pods Manifest.lock"; 267 | outputPaths = ( 268 | ); 269 | runOnlyForDeploymentPostprocessing = 0; 270 | shellPath = /bin/sh; 271 | shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; 272 | showEnvVarsInLog = 0; 273 | }; 274 | /* End PBXShellScriptBuildPhase section */ 275 | 276 | /* Begin PBXSourcesBuildPhase section */ 277 | 146D72A81AB782920058798C /* Sources */ = { 278 | isa = PBXSourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | D5A130711AEF9B060081DAFE /* PopAnimationSpec.swift in Sources */, 282 | D5A1306D1AEF9AF30081DAFE /* TransitionAnimationSpec.swift in Sources */, 283 | D50583F31AEFD983003D8F05 /* SpecHelper.swift in Sources */, 284 | D5C28A2D1AEFCFDB00DCC96D /* PositionSpec.swift in Sources */, 285 | D516EFF11AF6B800002BE7CA /* DissolveAnimationSpec.swift in Sources */, 286 | D5A130641AEF99BD0081DAFE /* CGPointExtensionSpec.swift in Sources */, 287 | D526B3CB1AF0EA4600A9CA0F /* ContentSpec.swift in Sources */, 288 | ); 289 | runOnlyForDeploymentPostprocessing = 0; 290 | }; 291 | /* End PBXSourcesBuildPhase section */ 292 | 293 | /* Begin XCBuildConfiguration section */ 294 | 146D72B41AB782920058798C /* Debug */ = { 295 | isa = XCBuildConfiguration; 296 | buildSettings = { 297 | ALWAYS_SEARCH_USER_PATHS = NO; 298 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 299 | CLANG_CXX_LIBRARY = "libc++"; 300 | CLANG_ENABLE_MODULES = YES; 301 | CLANG_ENABLE_OBJC_ARC = YES; 302 | CLANG_WARN_BOOL_CONVERSION = YES; 303 | CLANG_WARN_CONSTANT_CONVERSION = YES; 304 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 305 | CLANG_WARN_EMPTY_BODY = YES; 306 | CLANG_WARN_ENUM_CONVERSION = YES; 307 | CLANG_WARN_INT_CONVERSION = YES; 308 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 309 | CLANG_WARN_UNREACHABLE_CODE = YES; 310 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 311 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 312 | COPY_PHASE_STRIP = NO; 313 | ENABLE_STRICT_OBJC_MSGSEND = YES; 314 | GCC_C_LANGUAGE_STANDARD = gnu99; 315 | GCC_DYNAMIC_NO_PIC = NO; 316 | GCC_OPTIMIZATION_LEVEL = 0; 317 | GCC_PREPROCESSOR_DEFINITIONS = ( 318 | "DEBUG=1", 319 | "$(inherited)", 320 | ); 321 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 322 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 323 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 324 | GCC_WARN_UNDECLARED_SELECTOR = YES; 325 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 326 | GCC_WARN_UNUSED_FUNCTION = YES; 327 | GCC_WARN_UNUSED_VARIABLE = YES; 328 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 329 | MTL_ENABLE_DEBUG_INFO = YES; 330 | ONLY_ACTIVE_ARCH = YES; 331 | SDKROOT = iphoneos; 332 | }; 333 | name = Debug; 334 | }; 335 | 146D72B51AB782920058798C /* Release */ = { 336 | isa = XCBuildConfiguration; 337 | buildSettings = { 338 | ALWAYS_SEARCH_USER_PATHS = NO; 339 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 340 | CLANG_CXX_LIBRARY = "libc++"; 341 | CLANG_ENABLE_MODULES = YES; 342 | CLANG_ENABLE_OBJC_ARC = YES; 343 | CLANG_WARN_BOOL_CONVERSION = YES; 344 | CLANG_WARN_CONSTANT_CONVERSION = YES; 345 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 346 | CLANG_WARN_EMPTY_BODY = YES; 347 | CLANG_WARN_ENUM_CONVERSION = YES; 348 | CLANG_WARN_INT_CONVERSION = YES; 349 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 350 | CLANG_WARN_UNREACHABLE_CODE = YES; 351 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 352 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 353 | COPY_PHASE_STRIP = NO; 354 | ENABLE_NS_ASSERTIONS = NO; 355 | ENABLE_STRICT_OBJC_MSGSEND = YES; 356 | GCC_C_LANGUAGE_STANDARD = gnu99; 357 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 358 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 359 | GCC_WARN_UNDECLARED_SELECTOR = YES; 360 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 361 | GCC_WARN_UNUSED_FUNCTION = YES; 362 | GCC_WARN_UNUSED_VARIABLE = YES; 363 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 364 | MTL_ENABLE_DEBUG_INFO = NO; 365 | SDKROOT = iphoneos; 366 | VALIDATE_PRODUCT = YES; 367 | }; 368 | name = Release; 369 | }; 370 | 146D72BA1AB782920058798C /* Debug */ = { 371 | isa = XCBuildConfiguration; 372 | baseConfigurationReference = 48D596C5F7386460518077F9 /* Pods.debug.xcconfig */; 373 | buildSettings = { 374 | CLANG_ENABLE_MODULES = YES; 375 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | INFOPLIST_FILE = Tests/Info.plist; 381 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 382 | PRODUCT_NAME = "$(TARGET_NAME)"; 383 | SWIFT_OBJC_BRIDGING_HEADER = ""; 384 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 385 | }; 386 | name = Debug; 387 | }; 388 | 146D72BB1AB782920058798C /* Release */ = { 389 | isa = XCBuildConfiguration; 390 | baseConfigurationReference = 30212F8CDFCE2FA3013BEA16 /* Pods.release.xcconfig */; 391 | buildSettings = { 392 | CLANG_ENABLE_MODULES = YES; 393 | FRAMEWORK_SEARCH_PATHS = "$(inherited)"; 394 | INFOPLIST_FILE = Tests/Info.plist; 395 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 396 | PRODUCT_NAME = "$(TARGET_NAME)"; 397 | SWIFT_OBJC_BRIDGING_HEADER = ""; 398 | }; 399 | name = Release; 400 | }; 401 | /* End XCBuildConfiguration section */ 402 | 403 | /* Begin XCConfigurationList section */ 404 | 146D728E1AB782920058798C /* Build configuration list for PBXProject "Pod" */ = { 405 | isa = XCConfigurationList; 406 | buildConfigurations = ( 407 | 146D72B41AB782920058798C /* Debug */, 408 | 146D72B51AB782920058798C /* Release */, 409 | ); 410 | defaultConfigurationIsVisible = 0; 411 | defaultConfigurationName = Release; 412 | }; 413 | 146D72B91AB782920058798C /* Build configuration list for PBXNativeTarget "Tests" */ = { 414 | isa = XCConfigurationList; 415 | buildConfigurations = ( 416 | 146D72BA1AB782920058798C /* Debug */, 417 | 146D72BB1AB782920058798C /* Release */, 418 | ); 419 | defaultConfigurationIsVisible = 0; 420 | defaultConfigurationName = Release; 421 | }; 422 | /* End XCConfigurationList section */ 423 | }; 424 | rootObject = 146D728B1AB782920058798C /* Project object */; 425 | } 426 | -------------------------------------------------------------------------------- /Pod/Pod.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Pod/Pod.xcodeproj/xcshareddata/xcschemes/Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Pod/Pod.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Pod/Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | 3 | use_frameworks! 4 | 5 | platform :ios, '8.0' 6 | 7 | pod 'Presentation', path: '../' 8 | pod 'Quick', '0.3.1' 9 | pod 'Nimble', '1.0.0-rc.1' 10 | -------------------------------------------------------------------------------- /Pod/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Cartography (0.5.0) 3 | - Nimble (1.0.0-rc.1) 4 | - Pages (0.6.1) 5 | - Presentation (1.0): 6 | - Cartography (~> 0.5.0) 7 | - Pages (~> 0.6.1) 8 | - Quick (0.3.1) 9 | 10 | DEPENDENCIES: 11 | - Nimble (= 1.0.0-rc.1) 12 | - Presentation (from `../`) 13 | - Quick (= 0.3.1) 14 | 15 | EXTERNAL SOURCES: 16 | Presentation: 17 | :path: ../ 18 | 19 | SPEC CHECKSUMS: 20 | Cartography: 774e5cc446f5a6bca5d4345c5aa6af9a1fe74dc6 21 | Nimble: 23f1dbddf1706172c7d740430858e5dfa93d997a 22 | Pages: 515a8ec7396cfb7cdacc28c0beceb2ce39c065cb 23 | Presentation: 47da74597602fa2555292d7c1d48e85eb503463b 24 | Quick: 824572d3d198d51e52cf4aa722cebf7e59952a35 25 | 26 | COCOAPODS: 0.37.2 27 | -------------------------------------------------------------------------------- /Pod/Tests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | no.hyper.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Pod/Tests/Specs/Animations/DissolveAnimationSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | import Presentation 4 | 5 | class DissolveAnimationSpec: QuickSpec { 6 | 7 | override func spec() { 8 | describe("DissolveAnimation") { 9 | var animation: DissolveAnimation! 10 | var view: UIView! 11 | var content: Content! 12 | var superview: UIView! 13 | 14 | beforeEach { 15 | view = SpecHelper.imageView() 16 | content = Content(view: view, position: Position(left: 0.2, bottom: 0.2)) 17 | superview = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 300.0, height: 200.0)) 18 | animation = DissolveAnimation(content: content, duration: 0.0, delay: 0.0) 19 | } 20 | 21 | describe("#init") { 22 | it("sets alpha to zero") { 23 | expect(Double(view.alpha)) ≈ Double(0.0) 24 | } 25 | } 26 | 27 | describe("#play") { 28 | beforeEach { 29 | superview.addSubview(view) 30 | animation.play() 31 | } 32 | 33 | it("changes alpha to 1.0") { 34 | expect(Double(view.alpha)) ≈ Double(1.0) 35 | } 36 | } 37 | 38 | describe("#playBack") { 39 | beforeEach { 40 | superview.addSubview(view) 41 | animation.playBack() 42 | } 43 | 44 | it("changes alpha to zero") { 45 | expect(Double(view.alpha)) ≈ Double(0.0) 46 | } 47 | } 48 | 49 | describe("#moveWith") { 50 | context("with superview") { 51 | beforeEach { 52 | superview.addSubview(view) 53 | } 54 | 55 | context("with positive offsetRatio") { 56 | it("changes alpha correctly") { 57 | let offsetRatio: CGFloat = 0.4 58 | 59 | animation.moveWith(offsetRatio) 60 | expect(Double(view.alpha)) ≈ Double(0.4) 61 | } 62 | } 63 | 64 | context("with negative offsetRatio") { 65 | it("changes alpha correctly") { 66 | let offsetRatio: CGFloat = -0.4 67 | 68 | animation.moveWith(offsetRatio) 69 | expect(Double(view.alpha)) ≈ Double(0.6) 70 | } 71 | } 72 | } 73 | 74 | context("without superview") { 75 | it("doesn't change alpha") { 76 | let offsetRatio: CGFloat = 0.4 77 | 78 | animation.moveWith(offsetRatio) 79 | expect(Double(view.alpha)) ≈ Double(0.0) 80 | } 81 | } 82 | } 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Pod/Tests/Specs/Animations/PopAnimationSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | import Presentation 4 | 5 | class PopAnimationSpec: QuickSpec { 6 | 7 | override func spec() { 8 | describe("PopAnimation") { 9 | var animation: PopAnimation! 10 | var view: UIView! 11 | var content: Content! 12 | var superview: UIView! 13 | 14 | beforeEach { 15 | view = SpecHelper.imageView() 16 | content = Content(view: view, position: Position(left: 0.2, bottom: 0.2)) 17 | superview = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 300.0, height: 200.0)) 18 | animation = PopAnimation(content: content, duration: 0) 19 | } 20 | 21 | describe("#init") { 22 | it("hides view") { 23 | expect(view.hidden).to(beTrue()) 24 | } 25 | } 26 | 27 | describe("#moveWith") { 28 | context("with superview") { 29 | beforeEach { 30 | superview.addSubview(view) 31 | } 32 | 33 | context("with positive offsetRatio") { 34 | it("moves view correctly") { 35 | let offsetRatio: CGFloat = 0.4 36 | 37 | animation.moveWith(offsetRatio) 38 | expect(Double(view.alpha)) ≈ Double(0.4) 39 | } 40 | } 41 | 42 | context("with negative offsetRatio") { 43 | it("moves view correctly") { 44 | let offsetRatio: CGFloat = -0.4 45 | 46 | animation.moveWith(offsetRatio) 47 | expect(Double(view.alpha)) ≈ Double(0.6) 48 | } 49 | } 50 | } 51 | 52 | context("without superview") { 53 | it("doesn't change position") { 54 | let offsetRatio: CGFloat = 0.4 55 | 56 | animation.moveWith(offsetRatio) 57 | expect(Double(view.alpha)) ≈ Double(1.0) 58 | } 59 | } 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Pod/Tests/Specs/Animations/TransitionAnimationSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | import Presentation 4 | 5 | class TransitionAnimationSpec: QuickSpec { 6 | 7 | override func spec() { 8 | describe("TransitionAnimation") { 9 | var animation: TransitionAnimation! 10 | var view: UIView! 11 | var content: Content! 12 | var destination: Position! 13 | var superview: UIView! 14 | 15 | beforeEach { 16 | view = SpecHelper.imageView() 17 | content = Content(view: view, position: Position(left: 0.3, top: 0.5)) 18 | destination = Position(left: 0.5, top: 0.5) 19 | superview = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 300.0, height: 200.0)) 20 | animation = TransitionAnimation(content: content, destination: destination, duration: 0) 21 | } 22 | 23 | describe("#play") { 24 | context("with superview") { 25 | beforeEach { 26 | superview.addSubview(view) 27 | content.layout() 28 | } 29 | 30 | it("moves view to the destination point") { 31 | let center = destination.originInFrame(superview.bounds) 32 | 33 | animation.play() 34 | expect(view.center).to(equal(center)) 35 | } 36 | } 37 | 38 | context("without superview") { 39 | it("doesn't change position") { 40 | let center = view.center 41 | 42 | animation.play() 43 | expect(view.center).to(equal(center)) 44 | } 45 | } 46 | } 47 | 48 | describe("#playBack") { 49 | var center = CGPointZero 50 | 51 | context("with superview") { 52 | beforeEach { 53 | superview.addSubview(view) 54 | content.layout() 55 | center = view.center 56 | animation.play() 57 | } 58 | 59 | it("moves view to the destination point") { 60 | animation.playBack() 61 | expect(view.center).to(equal(center)) 62 | } 63 | } 64 | 65 | context("without superview") { 66 | var center = CGPointZero 67 | 68 | beforeEach { 69 | superview.addSubview(view) 70 | content.layout() 71 | animation.play() 72 | center = view.center 73 | 74 | view.removeFromSuperview() 75 | } 76 | 77 | it("doesn't change position") { 78 | animation.playBack() 79 | expect(view.center).to(equal(center)) 80 | } 81 | } 82 | } 83 | 84 | describe("#moveWith") { 85 | var center = CGPointZero 86 | 87 | beforeEach { 88 | center = view.center 89 | } 90 | 91 | context("with superview") { 92 | var startX: CGFloat = 0.0 93 | var dx: CGFloat = 0.0 94 | 95 | beforeEach { 96 | superview.addSubview(view) 97 | content.layout() 98 | center = view.center 99 | 100 | let start = view.center.positionInFrame(superview.bounds) 101 | startX = start.xInFrame(superview.bounds) 102 | dx = destination.xInFrame(superview.bounds) - startX 103 | } 104 | 105 | context("with positive offsetRatio") { 106 | it("moves view correctly") { 107 | let offsetRatio: CGFloat = 0.4 108 | let offset = dx * offsetRatio 109 | center.x = startX + offset 110 | 111 | animation.moveWith(offsetRatio) 112 | expect(view.center).to(equal(center)) 113 | } 114 | } 115 | 116 | context("with negative offsetRatio") { 117 | it("moves view correctly") { 118 | let offsetRatio: CGFloat = -0.4 119 | let offset = dx * (1.0 + offsetRatio) 120 | center.x = startX + offset 121 | 122 | animation.moveWith(offsetRatio) 123 | expect(view.center).to(equal(center)) 124 | } 125 | } 126 | } 127 | 128 | context("without superview") { 129 | it("doesn't change position") { 130 | let offsetRatio: CGFloat = -0.4 131 | 132 | animation.moveWith(offsetRatio) 133 | expect(view.center).to(equal(center)) 134 | } 135 | } 136 | 137 | context("with playing animations") { 138 | beforeEach { 139 | superview.addSubview(view) 140 | content.layout() 141 | center = view.center 142 | 143 | UIView.animateWithDuration(2.0, animations: { 144 | view.alpha = 0.5 145 | }) 146 | } 147 | 148 | it("doesn't change position") { 149 | let offsetRatio: CGFloat = -0.4 150 | 151 | animation.moveWith(offsetRatio) 152 | expect(view.center).to(equal(center)) 153 | } 154 | } 155 | } 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /Pod/Tests/Specs/ContentSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | import UIKit 4 | import Presentation 5 | 6 | class ContentSpec: QuickSpec { 7 | 8 | override func spec() { 9 | describe("Content") { 10 | var content: Content! 11 | var position: Position! 12 | var superview: UIView! 13 | 14 | beforeEach { 15 | position = Position(left: 0.5, top: 0.5) 16 | content = Content(view: SpecHelper.imageView(), position: position) 17 | superview = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 300.0, height: 200.0)) 18 | } 19 | 20 | describe("#layout") { 21 | context("with superview") { 22 | beforeEach { 23 | superview.addSubview(content.view) 24 | } 25 | 26 | it("changes center correctly") { 27 | let center = position.originInFrame(superview.bounds) 28 | 29 | content.layout() 30 | expect(content.view.center).to(equal(center)) 31 | } 32 | 33 | it("changes origin correctly") { 34 | content.centered = false 35 | let origin = position.originInFrame(superview.bounds) 36 | 37 | content.layout() 38 | expect(content.view.frame.origin).to(equal(origin)) 39 | } 40 | } 41 | 42 | context("without superview") { 43 | it("doesn't change origin") { 44 | let origin = content.view.frame.origin 45 | 46 | content.layout() 47 | expect(content.view.frame.origin).to(equal(origin)) 48 | } 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Pod/Tests/Specs/Extensions/CGPointExtensionSpec.swift: -------------------------------------------------------------------------------- 1 | import Quick 2 | import Nimble 3 | import Presentation 4 | 5 | class CGPointExtensionSpec: QuickSpec { 6 | 7 | override func spec() { 8 | describe("CGPointExtension") { 9 | var point: CGPoint! 10 | let frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 80.0) 11 | 12 | beforeEach { 13 | point = CGPoint(x: 100.0, y: 80.0) 14 | } 15 | 16 | describe("#positionInFrame") { 17 | it ("returns correct position") { 18 | var left = point.x / CGRectGetWidth(frame) 19 | var top = point.y / CGRectGetHeight(frame) 20 | let position = point.positionInFrame(frame) 21 | 22 | expect(Double(position.left)) ≈ Double(left) 23 | expect(Double(position.top)) ≈ Double(top) 24 | } 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Pod/Tests/Specs/Helpers/SpecHelper.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | class SpecHelper { 4 | 5 | class func image() -> UIImage { 6 | let bundle = NSBundle(forClass: SpecHelper.self) 7 | 8 | var image = UIImage() 9 | if let imagePath = bundle.pathForResource("hyper-logo", ofType: "png") { 10 | if let loadedImage = UIImage(contentsOfFile: imagePath) { 11 | image = loadedImage 12 | } 13 | } 14 | 15 | return image 16 | } 17 | 18 | class func imageView() -> UIImageView { 19 | return UIImageView(image: image()) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Pod/Tests/Specs/PositionSpec.swift: -------------------------------------------------------------------------------- 1 | import Presentation 2 | import Quick 3 | import Nimble 4 | 5 | class PositionSpec: QuickSpec { 6 | 7 | override func spec() { 8 | describe("Position") { 9 | var position: Position! 10 | var frame: CGRect! 11 | 12 | beforeEach { 13 | position = Position(left: 0.2, top: 0.2) 14 | frame = CGRect(x: 0.0, y: 0.0, width: 100.0, height: 100.0) 15 | } 16 | 17 | describe("#init") { 18 | context("with left and top") { 19 | beforeEach { 20 | position = Position(left: 0.2, top: 0.2) 21 | } 22 | 23 | it("sets position values") { 24 | expect(position.left).to(equal(0.2)) 25 | expect(position.top).to(equal(0.2)) 26 | } 27 | } 28 | 29 | context("with left and bottom") { 30 | beforeEach { 31 | position = Position(left: 0.2, bottom: 0.2) 32 | } 33 | 34 | it("sets position values") { 35 | expect(position.left).to(equal(0.2)) 36 | expect(Double(position.bottom)) ≈ 0.2 37 | } 38 | } 39 | 40 | context("with right and top") { 41 | beforeEach { 42 | position = Position(right: 0.2, top: 0.2) 43 | } 44 | 45 | it("sets position values") { 46 | expect(Double(position.right)) ≈ 0.2 47 | expect(Double(position.top)) ≈ 0.2 48 | } 49 | } 50 | 51 | context("with right and bottom") { 52 | beforeEach { 53 | position = Position(right: 0.2, bottom: 0.2) 54 | } 55 | 56 | it("sets position values") { 57 | expect(Double(position.right)) ≈ 0.2 58 | expect(Double(position.bottom)) ≈ 0.2 59 | } 60 | } 61 | } 62 | 63 | describe("#right") { 64 | it("sets left") { 65 | position.right = 0.4 66 | expect(Double(position.left)) ≈ 0.6 67 | } 68 | } 69 | 70 | describe("#bottom") { 71 | it("sets top") { 72 | position.bottom = 0.4 73 | expect(Double(position.top)) ≈ 0.6 74 | } 75 | } 76 | 77 | describe("#positionCopy") { 78 | it("returns new instance") { 79 | let copy = position.positionCopy 80 | expect(copy).notTo(equal(position)) 81 | } 82 | } 83 | 84 | describe("#horizontalMirror") { 85 | it("returns correct position") { 86 | let mirror = position.horizontalMirror 87 | expect(mirror.left).to(equal(position.right)) 88 | expect(mirror.top).to(equal(position.left)) 89 | } 90 | } 91 | 92 | describe("#originInFrame") { 93 | it("returns correct point") { 94 | let point = position.originInFrame(frame) 95 | expect(Double(point.x)) ≈ 20.0 96 | expect(Double(point.y)) ≈ 20.0 97 | } 98 | } 99 | 100 | describe("#xInFrame") { 101 | it("returns correct x coordinate") { 102 | let x = position.xInFrame(frame) 103 | expect(Double(x)) ≈ 20.0 104 | } 105 | } 106 | 107 | describe("#yInFrame") { 108 | it("returns correct y coordinate") { 109 | let y = position.yInFrame(frame) 110 | expect(Double(y)) ≈ 20.0 111 | } 112 | } 113 | 114 | describe("#isEqualToPosition") { 115 | it("is equal to position") { 116 | let somePosition = Position(left: 0.2, top: 0.2) 117 | expect(position.isEqualToPosition(somePosition)).to(beTrue()) 118 | } 119 | 120 | it("is not equal to position") { 121 | let somePosition = Position(left: 0.3, top: 0.2) 122 | expect(position.isEqualToPosition(somePosition)).notTo(beTrue()) 123 | } 124 | } 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Presentation.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "Presentation" 3 | s.summary = "Presentation helps you to make tutorials, release notes and animated pages." 4 | s.version = "4.1.3" 5 | s.homepage = "https://github.com/hyperoslo/Presentation" 6 | s.license = 'MIT' 7 | s.author = { "Hyper" => "ios@hyper.no" } 8 | s.source = { :git => "https://github.com/hyperoslo/Presentation.git", :tag => s.version.to_s } 9 | s.social_media_url = 'https://twitter.com/hyperoslo' 10 | 11 | s.platform = :ios, '8.0' 12 | s.requires_arc = true 13 | 14 | s.source_files = 'Source/**/*' 15 | s.dependency 'Pages', '~> 2.0.5' 16 | end 17 | -------------------------------------------------------------------------------- /Presentation.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D523B0E71C43AC70001AD1EC /* Animatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0DC1C43AC70001AD1EC /* Animatable.swift */; }; 11 | D523B0E81C43AC70001AD1EC /* DissolveAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0DD1C43AC70001AD1EC /* DissolveAnimation.swift */; }; 12 | D523B0E91C43AC70001AD1EC /* PopAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0DE1C43AC70001AD1EC /* PopAnimation.swift */; }; 13 | D523B0EA1C43AC70001AD1EC /* TransitionAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0DF1C43AC70001AD1EC /* TransitionAnimation.swift */; }; 14 | D523B0EB1C43AC70001AD1EC /* Content.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0E01C43AC70001AD1EC /* Content.swift */; }; 15 | D523B0EC1C43AC70001AD1EC /* CGPointExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0E21C43AC70001AD1EC /* CGPointExtension.swift */; }; 16 | D523B0ED1C43AC70001AD1EC /* Position.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0E31C43AC70001AD1EC /* Position.swift */; }; 17 | D523B0EE1C43AC70001AD1EC /* PresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0E41C43AC70001AD1EC /* PresentationController.swift */; }; 18 | D523B0EF1C43AC70001AD1EC /* SlideController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D523B0E51C43AC70001AD1EC /* SlideController.swift */; }; 19 | D523B0F21C43AE94001AD1EC /* Pages.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D523B0F01C43AE94001AD1EC /* Pages.framework */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXFileReference section */ 23 | D523B0CD1C43AB90001AD1EC /* Presentation.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Presentation.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 24 | D523B0D91C43AC70001AD1EC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 25 | D523B0DC1C43AC70001AD1EC /* Animatable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animatable.swift; sourceTree = ""; }; 26 | D523B0DD1C43AC70001AD1EC /* DissolveAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DissolveAnimation.swift; sourceTree = ""; }; 27 | D523B0DE1C43AC70001AD1EC /* PopAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PopAnimation.swift; sourceTree = ""; }; 28 | D523B0DF1C43AC70001AD1EC /* TransitionAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransitionAnimation.swift; sourceTree = ""; }; 29 | D523B0E01C43AC70001AD1EC /* Content.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Content.swift; sourceTree = ""; }; 30 | D523B0E21C43AC70001AD1EC /* CGPointExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGPointExtension.swift; sourceTree = ""; }; 31 | D523B0E31C43AC70001AD1EC /* Position.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Position.swift; sourceTree = ""; }; 32 | D523B0E41C43AC70001AD1EC /* PresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresentationController.swift; sourceTree = ""; }; 33 | D523B0E51C43AC70001AD1EC /* SlideController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlideController.swift; sourceTree = ""; }; 34 | D523B0F01C43AE94001AD1EC /* Pages.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pages.framework; path = Carthage/Build/iOS/Pages.framework; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | D523B0C91C43AB90001AD1EC /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | D523B0F21C43AE94001AD1EC /* Pages.framework in Frameworks */, 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | /* End PBXFrameworksBuildPhase section */ 47 | 48 | /* Begin PBXGroup section */ 49 | D523B0C31C43AB90001AD1EC = { 50 | isa = PBXGroup; 51 | children = ( 52 | D523B0D81C43AC70001AD1EC /* SupportFiles */, 53 | D523B0DA1C43AC70001AD1EC /* Source */, 54 | D523B0F51C43AF9B001AD1EC /* Frameworks */, 55 | D523B0CE1C43AB90001AD1EC /* Products */, 56 | ); 57 | sourceTree = ""; 58 | }; 59 | D523B0CE1C43AB90001AD1EC /* Products */ = { 60 | isa = PBXGroup; 61 | children = ( 62 | D523B0CD1C43AB90001AD1EC /* Presentation.framework */, 63 | ); 64 | name = Products; 65 | sourceTree = ""; 66 | }; 67 | D523B0D81C43AC70001AD1EC /* SupportFiles */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | D523B0D91C43AC70001AD1EC /* Info.plist */, 71 | ); 72 | path = SupportFiles; 73 | sourceTree = ""; 74 | }; 75 | D523B0DA1C43AC70001AD1EC /* Source */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | D523B0E01C43AC70001AD1EC /* Content.swift */, 79 | D523B0E31C43AC70001AD1EC /* Position.swift */, 80 | D523B0E41C43AC70001AD1EC /* PresentationController.swift */, 81 | D523B0E51C43AC70001AD1EC /* SlideController.swift */, 82 | D523B0DB1C43AC70001AD1EC /* Animations */, 83 | D523B0E11C43AC70001AD1EC /* Extensions */, 84 | ); 85 | path = Source; 86 | sourceTree = ""; 87 | }; 88 | D523B0DB1C43AC70001AD1EC /* Animations */ = { 89 | isa = PBXGroup; 90 | children = ( 91 | D523B0DC1C43AC70001AD1EC /* Animatable.swift */, 92 | D523B0DD1C43AC70001AD1EC /* DissolveAnimation.swift */, 93 | D523B0DE1C43AC70001AD1EC /* PopAnimation.swift */, 94 | D523B0DF1C43AC70001AD1EC /* TransitionAnimation.swift */, 95 | ); 96 | path = Animations; 97 | sourceTree = ""; 98 | }; 99 | D523B0E11C43AC70001AD1EC /* Extensions */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | D523B0E21C43AC70001AD1EC /* CGPointExtension.swift */, 103 | ); 104 | path = Extensions; 105 | sourceTree = ""; 106 | }; 107 | D523B0F51C43AF9B001AD1EC /* Frameworks */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | D523B0F01C43AE94001AD1EC /* Pages.framework */, 111 | ); 112 | name = Frameworks; 113 | sourceTree = ""; 114 | }; 115 | /* End PBXGroup section */ 116 | 117 | /* Begin PBXHeadersBuildPhase section */ 118 | D523B0CA1C43AB90001AD1EC /* Headers */ = { 119 | isa = PBXHeadersBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXHeadersBuildPhase section */ 126 | 127 | /* Begin PBXNativeTarget section */ 128 | D523B0CC1C43AB90001AD1EC /* Presentation-iOS */ = { 129 | isa = PBXNativeTarget; 130 | buildConfigurationList = D523B0D51C43AB90001AD1EC /* Build configuration list for PBXNativeTarget "Presentation-iOS" */; 131 | buildPhases = ( 132 | D523B0C81C43AB90001AD1EC /* Sources */, 133 | D523B0C91C43AB90001AD1EC /* Frameworks */, 134 | D523B0CA1C43AB90001AD1EC /* Headers */, 135 | D523B0CB1C43AB90001AD1EC /* Resources */, 136 | D523B0F41C43AE99001AD1EC /* ShellScript */, 137 | ); 138 | buildRules = ( 139 | ); 140 | dependencies = ( 141 | ); 142 | name = "Presentation-iOS"; 143 | productName = Presentation; 144 | productReference = D523B0CD1C43AB90001AD1EC /* Presentation.framework */; 145 | productType = "com.apple.product-type.framework"; 146 | }; 147 | /* End PBXNativeTarget section */ 148 | 149 | /* Begin PBXProject section */ 150 | D523B0C41C43AB90001AD1EC /* Project object */ = { 151 | isa = PBXProject; 152 | attributes = { 153 | LastUpgradeCheck = 0900; 154 | ORGANIZATIONNAME = "Hyper Interaktiv AS"; 155 | TargetAttributes = { 156 | D523B0CC1C43AB90001AD1EC = { 157 | CreatedOnToolsVersion = 7.2; 158 | LastSwiftMigration = 0900; 159 | }; 160 | }; 161 | }; 162 | buildConfigurationList = D523B0C71C43AB90001AD1EC /* Build configuration list for PBXProject "Presentation" */; 163 | compatibilityVersion = "Xcode 3.2"; 164 | developmentRegion = English; 165 | hasScannedForEncodings = 0; 166 | knownRegions = ( 167 | en, 168 | ); 169 | mainGroup = D523B0C31C43AB90001AD1EC; 170 | productRefGroup = D523B0CE1C43AB90001AD1EC /* Products */; 171 | projectDirPath = ""; 172 | projectRoot = ""; 173 | targets = ( 174 | D523B0CC1C43AB90001AD1EC /* Presentation-iOS */, 175 | ); 176 | }; 177 | /* End PBXProject section */ 178 | 179 | /* Begin PBXResourcesBuildPhase section */ 180 | D523B0CB1C43AB90001AD1EC /* Resources */ = { 181 | isa = PBXResourcesBuildPhase; 182 | buildActionMask = 2147483647; 183 | files = ( 184 | ); 185 | runOnlyForDeploymentPostprocessing = 0; 186 | }; 187 | /* End PBXResourcesBuildPhase section */ 188 | 189 | /* Begin PBXShellScriptBuildPhase section */ 190 | D523B0F41C43AE99001AD1EC /* ShellScript */ = { 191 | isa = PBXShellScriptBuildPhase; 192 | buildActionMask = 2147483647; 193 | files = ( 194 | ); 195 | inputPaths = ( 196 | "$(SRCROOT)/Carthage/Build/iOS/Pages.framework", 197 | ); 198 | outputPaths = ( 199 | ); 200 | runOnlyForDeploymentPostprocessing = 0; 201 | shellPath = /bin/sh; 202 | shellScript = "/usr/local/bin/carthage copy-frameworks"; 203 | }; 204 | /* End PBXShellScriptBuildPhase section */ 205 | 206 | /* Begin PBXSourcesBuildPhase section */ 207 | D523B0C81C43AB90001AD1EC /* Sources */ = { 208 | isa = PBXSourcesBuildPhase; 209 | buildActionMask = 2147483647; 210 | files = ( 211 | D523B0ED1C43AC70001AD1EC /* Position.swift in Sources */, 212 | D523B0E91C43AC70001AD1EC /* PopAnimation.swift in Sources */, 213 | D523B0E71C43AC70001AD1EC /* Animatable.swift in Sources */, 214 | D523B0EC1C43AC70001AD1EC /* CGPointExtension.swift in Sources */, 215 | D523B0E81C43AC70001AD1EC /* DissolveAnimation.swift in Sources */, 216 | D523B0EB1C43AC70001AD1EC /* Content.swift in Sources */, 217 | D523B0EA1C43AC70001AD1EC /* TransitionAnimation.swift in Sources */, 218 | D523B0EF1C43AC70001AD1EC /* SlideController.swift in Sources */, 219 | D523B0EE1C43AC70001AD1EC /* PresentationController.swift in Sources */, 220 | ); 221 | runOnlyForDeploymentPostprocessing = 0; 222 | }; 223 | /* End PBXSourcesBuildPhase section */ 224 | 225 | /* Begin XCBuildConfiguration section */ 226 | D523B0D31C43AB90001AD1EC /* Debug */ = { 227 | isa = XCBuildConfiguration; 228 | buildSettings = { 229 | ALWAYS_SEARCH_USER_PATHS = NO; 230 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 231 | CLANG_CXX_LIBRARY = "libc++"; 232 | CLANG_ENABLE_MODULES = YES; 233 | CLANG_ENABLE_OBJC_ARC = YES; 234 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 235 | CLANG_WARN_BOOL_CONVERSION = YES; 236 | CLANG_WARN_COMMA = YES; 237 | CLANG_WARN_CONSTANT_CONVERSION = YES; 238 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 239 | CLANG_WARN_EMPTY_BODY = YES; 240 | CLANG_WARN_ENUM_CONVERSION = YES; 241 | CLANG_WARN_INFINITE_RECURSION = YES; 242 | CLANG_WARN_INT_CONVERSION = YES; 243 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 244 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 245 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 246 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 247 | CLANG_WARN_STRICT_PROTOTYPES = YES; 248 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 249 | CLANG_WARN_UNREACHABLE_CODE = YES; 250 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 251 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 252 | COPY_PHASE_STRIP = NO; 253 | CURRENT_PROJECT_VERSION = 1; 254 | DEBUG_INFORMATION_FORMAT = dwarf; 255 | ENABLE_STRICT_OBJC_MSGSEND = YES; 256 | ENABLE_TESTABILITY = YES; 257 | GCC_C_LANGUAGE_STANDARD = gnu99; 258 | GCC_DYNAMIC_NO_PIC = NO; 259 | GCC_NO_COMMON_BLOCKS = YES; 260 | GCC_OPTIMIZATION_LEVEL = 0; 261 | GCC_PREPROCESSOR_DEFINITIONS = ( 262 | "DEBUG=1", 263 | "$(inherited)", 264 | ); 265 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 266 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 267 | GCC_WARN_UNDECLARED_SELECTOR = YES; 268 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 269 | GCC_WARN_UNUSED_FUNCTION = YES; 270 | GCC_WARN_UNUSED_VARIABLE = YES; 271 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 272 | MTL_ENABLE_DEBUG_INFO = YES; 273 | ONLY_ACTIVE_ARCH = YES; 274 | SDKROOT = iphoneos; 275 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 276 | TARGETED_DEVICE_FAMILY = "1,2"; 277 | VERSIONING_SYSTEM = "apple-generic"; 278 | VERSION_INFO_PREFIX = ""; 279 | }; 280 | name = Debug; 281 | }; 282 | D523B0D41C43AB90001AD1EC /* Release */ = { 283 | isa = XCBuildConfiguration; 284 | buildSettings = { 285 | ALWAYS_SEARCH_USER_PATHS = NO; 286 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 287 | CLANG_CXX_LIBRARY = "libc++"; 288 | CLANG_ENABLE_MODULES = YES; 289 | CLANG_ENABLE_OBJC_ARC = YES; 290 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 291 | CLANG_WARN_BOOL_CONVERSION = YES; 292 | CLANG_WARN_COMMA = YES; 293 | CLANG_WARN_CONSTANT_CONVERSION = YES; 294 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 295 | CLANG_WARN_EMPTY_BODY = YES; 296 | CLANG_WARN_ENUM_CONVERSION = YES; 297 | CLANG_WARN_INFINITE_RECURSION = YES; 298 | CLANG_WARN_INT_CONVERSION = YES; 299 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 300 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 301 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 302 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 303 | CLANG_WARN_STRICT_PROTOTYPES = YES; 304 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 305 | CLANG_WARN_UNREACHABLE_CODE = YES; 306 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 307 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 308 | COPY_PHASE_STRIP = NO; 309 | CURRENT_PROJECT_VERSION = 1; 310 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 311 | ENABLE_NS_ASSERTIONS = NO; 312 | ENABLE_STRICT_OBJC_MSGSEND = YES; 313 | GCC_C_LANGUAGE_STANDARD = gnu99; 314 | GCC_NO_COMMON_BLOCKS = YES; 315 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 316 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 317 | GCC_WARN_UNDECLARED_SELECTOR = YES; 318 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 319 | GCC_WARN_UNUSED_FUNCTION = YES; 320 | GCC_WARN_UNUSED_VARIABLE = YES; 321 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 322 | MTL_ENABLE_DEBUG_INFO = NO; 323 | SDKROOT = iphoneos; 324 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 325 | TARGETED_DEVICE_FAMILY = "1,2"; 326 | VALIDATE_PRODUCT = YES; 327 | VERSIONING_SYSTEM = "apple-generic"; 328 | VERSION_INFO_PREFIX = ""; 329 | }; 330 | name = Release; 331 | }; 332 | D523B0D61C43AB90001AD1EC /* Debug */ = { 333 | isa = XCBuildConfiguration; 334 | buildSettings = { 335 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 336 | DEFINES_MODULE = YES; 337 | DYLIB_COMPATIBILITY_VERSION = 1; 338 | DYLIB_CURRENT_VERSION = 1; 339 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 340 | FRAMEWORK_SEARCH_PATHS = ( 341 | "$(inherited)", 342 | "$(PROJECT_DIR)/Carthage/Build/iOS", 343 | ); 344 | INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/Info.plist"; 345 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 346 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 347 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 348 | PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Presentation; 349 | PRODUCT_NAME = Presentation; 350 | SKIP_INSTALL = YES; 351 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 352 | SWIFT_VERSION = 4.0; 353 | }; 354 | name = Debug; 355 | }; 356 | D523B0D71C43AB90001AD1EC /* Release */ = { 357 | isa = XCBuildConfiguration; 358 | buildSettings = { 359 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 360 | DEFINES_MODULE = YES; 361 | DYLIB_COMPATIBILITY_VERSION = 1; 362 | DYLIB_CURRENT_VERSION = 1; 363 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 364 | FRAMEWORK_SEARCH_PATHS = ( 365 | "$(inherited)", 366 | "$(PROJECT_DIR)/Carthage/Build/iOS", 367 | ); 368 | INFOPLIST_FILE = "$(SRCROOT)/SupportFiles/Info.plist"; 369 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 370 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 371 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 372 | PRODUCT_BUNDLE_IDENTIFIER = no.hyper.Presentation; 373 | PRODUCT_NAME = Presentation; 374 | SKIP_INSTALL = YES; 375 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 376 | SWIFT_VERSION = 4.0; 377 | }; 378 | name = Release; 379 | }; 380 | /* End XCBuildConfiguration section */ 381 | 382 | /* Begin XCConfigurationList section */ 383 | D523B0C71C43AB90001AD1EC /* Build configuration list for PBXProject "Presentation" */ = { 384 | isa = XCConfigurationList; 385 | buildConfigurations = ( 386 | D523B0D31C43AB90001AD1EC /* Debug */, 387 | D523B0D41C43AB90001AD1EC /* Release */, 388 | ); 389 | defaultConfigurationIsVisible = 0; 390 | defaultConfigurationName = Release; 391 | }; 392 | D523B0D51C43AB90001AD1EC /* Build configuration list for PBXNativeTarget "Presentation-iOS" */ = { 393 | isa = XCConfigurationList; 394 | buildConfigurations = ( 395 | D523B0D61C43AB90001AD1EC /* Debug */, 396 | D523B0D71C43AB90001AD1EC /* Release */, 397 | ); 398 | defaultConfigurationIsVisible = 0; 399 | defaultConfigurationName = Release; 400 | }; 401 | /* End XCConfigurationList section */ 402 | }; 403 | rootObject = D523B0C41C43AB90001AD1EC /* Project object */; 404 | } 405 | -------------------------------------------------------------------------------- /Presentation.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Presentation.xcodeproj/xcshareddata/xcschemes/Presentation-iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 72 | 73 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ⚠️ DEPRECATED, NO LONGER MAINTAINED 2 | 3 | ![Presentation logo](https://raw.githubusercontent.com/hyperoslo/Presentation/master/Images/logo.png) 4 | 5 | [![Version](https://img.shields.io/cocoapods/v/Presentation.svg?style=flat)](http://cocoadocs.org/docsets/Presentation) 6 | [![CI Status](http://img.shields.io/travis/hyperoslo/Presentation.svg?style=flat)](https://travis-ci.org/hyperoslo/Presentation) 7 | [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) 8 | ![Swift](https://img.shields.io/badge/%20in-swift%204.0-orange.svg) 9 | [![License](https://img.shields.io/cocoapods/l/Presentation.svg?style=flat)](http://cocoadocs.org/docsets/Presentation) 10 | [![Platform](https://img.shields.io/cocoapods/p/Presentation.svg?style=flat)](http://cocoadocs.org/docsets/Presentation) 11 | 12 | Looking for the easiest way of presenting something in your iOS app? Then you are in the right place. **Presentation** will help you make your tutorials, release notes and any kind of animated pages with the minimum amount of effort. 13 | 14 | *Presentation* includes the following features: 15 | 16 | - Custom positioning: You can use [Position](https://github.com/hyperoslo/Presentation/blob/master/Source/Position.swift) for percentage-based position declaration. 17 | - [Content](https://github.com/hyperoslo/Presentation/blob/master/Source/Content.swift): View model used for custom positioning and animations. It translates your percents to AutoLayout constraints behind the scenes. 18 | - Slides: You can use any kind of `UIViewController` as a slide. [SlideController](https://github.com/hyperoslo/Presentation/blob/master/Source/SlideController.swift) is your good friend if you want to use custom positioning and animation features on your pages. 19 | - Background: You can add views that are visible across all the pages. Also it's possible to animate those views during the transition to the specific page. 20 | - [Animations](https://github.com/hyperoslo/Presentation/tree/master/Source/Animations): You can easily animate the appearance of a view on the specific page. 21 | 22 | Presentation works both on the iPhone and the iPad. You can use it with both `Swift` and `Objective-C`. 23 | 24 | Try one of our [demos](https://github.com/hyperoslo/Presentation/tree/master/Example) to see how it works: 25 | 26 | ```shell 27 | pod try Presentation 28 | ``` 29 | 30 | 31 |

32 | 33 |

34 | 35 | ## Table of Contents 36 | 37 | * [Usage](#usage) 38 | * [Presentation controller](#presentation-controller) 39 | * [Position](#position) 40 | * [Content view model](#content-view-model) 41 | * [Slides](#slides) 42 | * [Page animations](#page-animations) 43 | * [Background views](#background-views) 44 | * [Installation](#installation) 45 | * [Components](#components) 46 | * [Contributing](#contributing) 47 | * [Credits](#credits) 48 | * [License](#license) 49 | 50 | ## Usage 51 | 52 | ### Presentation controller 53 | 54 | ```swift 55 | import Presentation 56 | 57 | let viewController1 = UIViewController() 58 | viewController1.title = "Controller A" 59 | 60 | let viewController2 = UIViewController() 61 | viewController2.title = "Controller B" 62 | 63 | let presentationController = PresentationController(pages: [viewController1, viewController2]) 64 | ``` 65 | 66 | If that's the only thing you need, look into [Pages](https://github.com/hyperoslo/Pages). 67 | 68 | ### Position 69 | 70 | `Position` is percentage-based; you can use `left`, `right`, `top`, `bottom` to set a position. 71 | 72 | ```swift 73 | let position = Position(left: 0.3, top: 0.4) 74 | ``` 75 | 76 | ### Content view model 77 | 78 | `Content` view model is a layer between `UIView` and `Position`. The current position is the center of a view by default, but can also be changed to the origin of a view. 79 | 80 | ```swift 81 | let view = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 100)) 82 | let position = Position(left: 0.3, top: 0.4) 83 | 84 | let centeredContent = Content(view: label, position: position) 85 | let originContent = Content(view: label, position: position, centered: false) 86 | ``` 87 | 88 | ### Slides 89 | 90 | ```swift 91 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 100)) 92 | label.text = "Slide 1" 93 | 94 | let position = Position(left: 0.3, top: 0.4) 95 | let content = Content(view: label, position: position) 96 | 97 | let controller = SlideController(contents: [content]) 98 | 99 | presentationController.add([controller]) 100 | ``` 101 | 102 | ### Page animations 103 | 104 | ```swift 105 | let contents = ["Slide 1", "Slide 2", "Slide 3"].map { title -> Content in 106 | let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 100)) 107 | label.text = title 108 | 109 | let position = Position(left: 0.3, top: 0.4) 110 | 111 | return Content(view: label, position: position) 112 | } 113 | 114 | var slides = [SlideController]() 115 | 116 | for index in 0...2 { 117 | let content = contents[index] 118 | let controller = SlideController(contents: [content]) 119 | let animation = TransitionAnimation( 120 | content: content, 121 | destination: Position(left: 0.5, top: content.initialPosition.top), 122 | duration: 2.0, 123 | dumping: 0.8, 124 | reflective: true) 125 | controller.add(animations: [animation]) 126 | 127 | slides.append(controller) 128 | } 129 | 130 | presentationController.add(slides) 131 | ``` 132 | 133 | ### Background views 134 | 135 | ```swift 136 | let imageView = UIImageView(image: UIImage(named: "image")) 137 | let content = Content(view: imageView, position: Position(left: -0.3, top: 0.2)) 138 | 139 | presentationController.addToBackground([content]) 140 | 141 | // Add pages animations 142 | presentationController.add(animations: [ 143 | TransitionAnimation(content: content, destination: Position(left: 0.2, top: 0.2))], 144 | forPage: 0) 145 | 146 | presentationController.add(animations: [ 147 | TransitionAnimation(content: content, destination: Position(left: 0.3, top: 0.2))], 148 | forPage: 1) 149 | ``` 150 | 151 | ## Installation 152 | 153 | **Presentation** is available through [CocoaPods](http://cocoapods.org). To install 154 | it, simply add the following line to your Podfile: 155 | 156 | ```ruby 157 | pod 'Presentation' 158 | ``` 159 | 160 | **Presentation** is also available through [Carthage](https://github.com/Carthage/Carthage). 161 | To install just write into your Cartfile: 162 | 163 | ```ruby 164 | github "hyperoslo/Presentation" 165 | ``` 166 | 167 | ## Components 168 | 169 | **Presentation** wouldn’t be possible without the help of these components: 170 | 171 | * [**Pages**](https://github.com/hyperoslo/Pages): The easiest way of setting up a `UIPageViewController` 172 | 173 | * [**Cartography**](https://github.com/robb/Cartography): Helps you set up your Auto Layout constraints declaratively and without any stringly typing! 174 | 175 | ## Contributing 176 | 177 | Please see our [playbook](https://github.com/hyperoslo/playbook/blob/master/GIT_AND_GITHUB.md) for guidelines on contributing. 178 | 179 | ## Credits 180 | 181 | [Hyper](http://hyper.no) made this. We’re a digital communications agency with a passion for good code and delightful user experiences. If you’re using this library we probably want to [hire you](https://github.com/hyperoslo/iOS-playbook/blob/master/HYPER_RECIPES.md) (we consider remote employees, too; the only requirement is that you’re awesome). 182 | 183 | ## License 184 | 185 | Presentation is available under the MIT license. See the [LICENSE](https://github.com/hyperoslo/Presentation/blob/master/LICENSE.md). 186 | -------------------------------------------------------------------------------- /Source/Animations/Animatable.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @objc public protocol Animatable { 4 | func play() 5 | func playBack() 6 | func moveWith(offsetRatio: CGFloat) 7 | } 8 | -------------------------------------------------------------------------------- /Source/Animations/DissolveAnimation.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public class DissolveAnimation: NSObject, Animatable { 4 | private let content: Content 5 | private let duration: TimeInterval 6 | private let delay: TimeInterval 7 | private var initial: Bool 8 | private var played = false 9 | 10 | public init(content: Content, 11 | duration: TimeInterval = 1.0, 12 | delay: TimeInterval = 0.0, 13 | initial: Bool = false) { 14 | self.content = content 15 | self.duration = duration 16 | self.delay = delay 17 | self.initial = initial 18 | 19 | content.view.alpha = 0.0 20 | 21 | super.init() 22 | } 23 | 24 | private func animate() { 25 | let alpha: CGFloat = content.view.alpha == 0.0 ? 1.0 : 0.0 26 | 27 | UIView.animate( 28 | withDuration: duration, 29 | delay: delay, 30 | usingSpringWithDamping: 1.0, 31 | initialSpringVelocity: 0.5, 32 | options: [.beginFromCurrentState, .allowUserInteraction], 33 | animations: ({ [unowned self] in 34 | self.content.view.alpha = alpha 35 | }), 36 | completion: nil 37 | ) 38 | 39 | played = true 40 | } 41 | } 42 | 43 | // MARK: - Animatable 44 | 45 | extension DissolveAnimation { 46 | public func play() { 47 | if content.view.superview != nil { 48 | if !(initial && played) { 49 | content.view.alpha = 0.0 50 | animate() 51 | } 52 | } 53 | } 54 | 55 | public func playBack() { 56 | if content.view.superview != nil { 57 | if !(initial && played) { 58 | content.view.alpha = 1.0 59 | animate() 60 | } 61 | } 62 | } 63 | 64 | public func moveWith(offsetRatio: CGFloat) { 65 | let view = content.view 66 | 67 | if view.layer.animationKeys() == nil { 68 | if view.superview != nil { 69 | let ratio = offsetRatio > 0.0 ? offsetRatio : (1.0 + offsetRatio) 70 | view.alpha = max(0.0, min(1.0, ratio)) 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Source/Animations/PopAnimation.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public class PopAnimation: NSObject, Animatable { 4 | private let content: Content 5 | private let duration: TimeInterval 6 | private var initial: Bool 7 | private var played = false 8 | 9 | public init(content: Content, duration: TimeInterval = 1.0, initial: Bool = false) { 10 | self.content = content 11 | self.duration = duration 12 | self.initial = initial 13 | 14 | content.view.isHidden = true 15 | 16 | super.init() 17 | } 18 | 19 | private func animate() { 20 | let view = content.view 21 | if view.isHidden { 22 | view.transform = CGAffineTransform(scaleX: 0.95, y: 0.95) 23 | } 24 | view.isHidden = false 25 | 26 | UIView.animate( 27 | withDuration: duration, 28 | animations: ({ 29 | view.transform = CGAffineTransform(scaleX: 1.05, y: 1.05) 30 | view.alpha = 0.8 31 | }), 32 | completion: ({ _ in 33 | UIView.animate(withDuration: 0.1, 34 | animations: { 35 | view.transform = CGAffineTransform(scaleX: 0.95, y: 0.95) 36 | view.alpha = 0.9 37 | }, completion: { _ in 38 | UIView.animate(withDuration: 0.1, 39 | animations: { 40 | view.transform = CGAffineTransform.identity 41 | view.alpha = 1.0 42 | }, completion: nil) 43 | }) 44 | }) 45 | ) 46 | 47 | played = true 48 | } 49 | } 50 | 51 | // MARK: - Animatable 52 | 53 | extension PopAnimation { 54 | public func play() { 55 | if content.view.superview != nil { 56 | if !(initial && played) { 57 | content.view.isHidden = true 58 | animate() 59 | } 60 | } 61 | } 62 | 63 | public func playBack() { 64 | if content.view.superview != nil { 65 | if !(initial && played) { 66 | content.view.isHidden = false 67 | animate() 68 | } 69 | } 70 | } 71 | 72 | public func moveWith(offsetRatio: CGFloat) { 73 | let view = content.view 74 | 75 | if view.layer.animationKeys() == nil { 76 | if view.superview != nil { 77 | let ratio = offsetRatio > 0.0 ? offsetRatio : (1.0 + offsetRatio) 78 | view.alpha = max(0.0, min(1.0, ratio)) 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Source/Animations/TransitionAnimation.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public class TransitionAnimation: NSObject, Animatable { 4 | private let content: Content 5 | private let destination: Position 6 | private let duration: TimeInterval 7 | private let damping: CGFloat 8 | var reflective: Bool 9 | private var initial: Bool 10 | private var played = false 11 | 12 | lazy var start: Position = { [unowned self] in 13 | return self.content.position.positionCopy 14 | }() 15 | 16 | lazy var startMirror: Position = { [unowned self] in 17 | return self.start.horizontalMirror 18 | }() 19 | 20 | public init(content: Content, 21 | destination: Position, 22 | duration: TimeInterval = 1.0, 23 | damping: CGFloat = 0.7, 24 | reflective: Bool = false, 25 | initial: Bool = false) { 26 | self.content = content 27 | self.destination = destination 28 | self.duration = duration 29 | self.damping = damping 30 | self.reflective = reflective 31 | self.initial = initial 32 | 33 | super.init() 34 | } 35 | 36 | private func animate(to position: Position) { 37 | UIView.animate( 38 | withDuration: duration, 39 | delay: 0, 40 | usingSpringWithDamping: damping, 41 | initialSpringVelocity: 0.5, 42 | options: [.beginFromCurrentState, .allowUserInteraction], 43 | animations: ({ [unowned self] in 44 | self.content.position = position 45 | self.content.animate() 46 | }), 47 | completion: nil 48 | ) 49 | 50 | played = true 51 | } 52 | } 53 | 54 | // MARK: - Animatable 55 | 56 | extension TransitionAnimation { 57 | public func play() { 58 | if let _ = content.view.superview { 59 | if !(initial && played) { 60 | let position = reflective ? startMirror : start 61 | 62 | content.position = position 63 | content.animate() 64 | 65 | animate(to: destination) 66 | } 67 | } 68 | } 69 | 70 | public func playBack() { 71 | if content.view.superview != nil { 72 | if !(initial && played) { 73 | let position = reflective ? startMirror : start 74 | 75 | animate(to: position) 76 | } 77 | } 78 | } 79 | 80 | public func moveWith(offsetRatio: CGFloat) { 81 | if content.view.layer.animationKeys() == nil { 82 | let view = content.view 83 | 84 | if let superview = view.superview { 85 | let position = reflective && offsetRatio < 0.0 ? startMirror : start 86 | 87 | let startX = position.xInFrame(superview.bounds) 88 | let dx = destination.xInFrame(superview.bounds) - startX 89 | 90 | let startY = position.yInFrame(superview.bounds) 91 | let dy = destination.yInFrame(superview.bounds) - startY 92 | 93 | let ratio = max(0.0, min(1.0, offsetRatio > 0.0 ? offsetRatio : (1.0 + offsetRatio))) 94 | let offsetX = dx * ratio 95 | let offsetY = dy * ratio 96 | 97 | var origin = content.position.originInFrame(superview.bounds) 98 | origin.x = startX + offsetX 99 | origin.y = startY + offsetY 100 | 101 | content.position = origin.position(in: superview.bounds) 102 | } 103 | } 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Source/Content.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public final class Content: NSObject { 4 | public var view: UIView 5 | public var centered: Bool 6 | 7 | public var position: Position { 8 | didSet { 9 | layout() 10 | } 11 | } 12 | 13 | public private(set) var initialPosition: Position 14 | private var constraints = [NSLayoutConstraint]() 15 | 16 | public init(view: UIView, position: Position, centered: Bool = true) { 17 | self.view = view 18 | self.position = position 19 | self.centered = centered 20 | initialPosition = position.positionCopy 21 | 22 | super.init() 23 | 24 | view.translatesAutoresizingMaskIntoConstraints = false 25 | setupSizeConstraints() 26 | } 27 | 28 | public func layout() { 29 | guard let superview = view.superview else { 30 | return 31 | } 32 | 33 | NSLayoutConstraint.deactivate(constraints) 34 | 35 | let xAttribute: NSLayoutConstraint.Attribute = centered ? .centerX : .leading 36 | let yAttribute: NSLayoutConstraint.Attribute = centered ? .centerY : .top 37 | let xSuperAttribute: NSLayoutConstraint.Attribute = position.left == 0 ? .leading : .trailing 38 | let ySuperAttribute: NSLayoutConstraint.Attribute = position.top == 0 ? .top : .bottom 39 | let xMultiplier: CGFloat = position.left == 0 ? 1 : position.left 40 | let yMultiplier: CGFloat = position.top == 0 ? 1 : position.top 41 | 42 | constraints = [ 43 | NSLayoutConstraint( 44 | item: view, 45 | attribute: xAttribute, 46 | relatedBy: .equal, 47 | toItem: superview, 48 | attribute: xSuperAttribute, 49 | multiplier: xMultiplier, 50 | constant: 0 51 | ), 52 | NSLayoutConstraint( 53 | item: view, 54 | attribute: yAttribute, 55 | relatedBy: .equal, 56 | toItem: superview, 57 | attribute: ySuperAttribute, 58 | multiplier: yMultiplier, 59 | constant: 0 60 | ) 61 | ] 62 | 63 | NSLayoutConstraint.activate(constraints) 64 | view.layoutIfNeeded() 65 | } 66 | 67 | public func animate() { 68 | view.superview!.layoutIfNeeded() 69 | } 70 | 71 | private func setupSizeConstraints() { 72 | makeSizeConstraint(attribute: .width, constant: view.frame.width).isActive = true 73 | makeSizeConstraint(attribute: .height, constant: view.frame.height).isActive = true 74 | } 75 | 76 | private func makeSizeConstraint(attribute: NSLayoutConstraint.Attribute, 77 | constant: CGFloat) -> NSLayoutConstraint { 78 | return NSLayoutConstraint( 79 | item: view, 80 | attribute: attribute, 81 | relatedBy: .equal, 82 | toItem: nil, 83 | attribute: .notAnAttribute, 84 | multiplier: 1, 85 | constant: constant 86 | ) 87 | } 88 | } 89 | 90 | public extension Content { 91 | class func content(forTitle text: String, attributes: [NSAttributedString.Key: Any]? = nil) -> Content { 92 | let label = UILabel(frame: CGRect.zero) 93 | label.numberOfLines = 1 94 | label.attributedText = NSAttributedString(string: text, attributes: attributes) 95 | label.sizeToFit() 96 | 97 | let position = Position(left: 0.9, bottom: 0.2) 98 | 99 | return Content(view: label, position: position) 100 | } 101 | 102 | class func content(forText text: String, attributes: [NSAttributedString.Key: Any]? = nil) -> Content { 103 | let textView = UITextView(frame: CGRect.zero) 104 | textView.backgroundColor = UIColor.clear 105 | textView.attributedText = NSAttributedString(string: text, attributes: attributes) 106 | textView.sizeToFit() 107 | 108 | return Content(view: textView, position: Position(left: 0.9, bottom: 0.1)) 109 | } 110 | 111 | class func content(forImage image: UIImage) -> Content { 112 | let imageView = UIImageView(image: image) 113 | return Content(view: imageView, position: Position(left: 0.5, bottom: 0.5)) 114 | } 115 | 116 | class func centerTransition(forSlideContent content: Content) -> Animatable { 117 | return TransitionAnimation( 118 | content: content, 119 | destination: Position(left: 0.5, bottom: content.initialPosition.bottom), 120 | duration: 2.0, 121 | damping: 0.8, 122 | reflective: true 123 | ) 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /Source/Extensions/CGPointExtension.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | public extension CGPoint { 4 | public func position(in frame: CGRect) -> Position { 5 | let left = x / frame.width 6 | let top = y / frame.height 7 | return Position(left: left, top: top) 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Source/Position.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | @objc public class Position: NSObject { 4 | public var left: CGFloat = 0.0 5 | public var top: CGFloat = 0.0 6 | 7 | public var right: CGFloat { 8 | get { 9 | return 1.0 - left 10 | } 11 | set { 12 | left = 1.0 - newValue 13 | } 14 | } 15 | 16 | public var bottom: CGFloat { 17 | get { 18 | return 1.0 - top 19 | } 20 | set { 21 | top = 1.0 - newValue 22 | } 23 | } 24 | 25 | public init(left: CGFloat, top: CGFloat) { 26 | super.init() 27 | self.left = left 28 | self.top = top 29 | } 30 | 31 | public init(left: CGFloat, bottom: CGFloat) { 32 | super.init() 33 | self.left = left 34 | self.bottom = bottom 35 | } 36 | 37 | public init(right: CGFloat, top: CGFloat) { 38 | super.init() 39 | self.right = right 40 | self.top = top 41 | } 42 | 43 | public init(right: CGFloat, bottom: CGFloat) { 44 | super.init() 45 | self.right = right 46 | self.bottom = bottom 47 | } 48 | 49 | public var positionCopy: Position { 50 | return Position(left: left, top: top) 51 | } 52 | 53 | public var horizontalMirror: Position { 54 | return Position(left: right, top: top) 55 | } 56 | 57 | public func originInFrame(_ frame: CGRect) -> CGPoint { 58 | return CGPoint(x: xInFrame(frame), y: yInFrame(frame)) 59 | } 60 | 61 | public func xInFrame(_ frame: CGRect) -> CGFloat { 62 | let margin = frame.width * left 63 | return frame.minX + margin 64 | } 65 | 66 | public func yInFrame(_ frame: CGRect) -> CGFloat { 67 | let margin = frame.height * top 68 | return frame.minY + margin 69 | } 70 | 71 | public func isEqualTo(position: Position, epsilon: CGFloat = 0.0001) -> Bool { 72 | let dx = left - position.left, dy = top - position.top 73 | return (dx * dx + dy * dy) < epsilon 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /Source/PresentationController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Pages 3 | 4 | @objc public protocol PresentationControllerDelegate { 5 | func presentationController( 6 | _ presentationController: PresentationController, 7 | didSetViewController viewController: UIViewController, 8 | atPage page: Int 9 | ) 10 | } 11 | 12 | open class PresentationController: PagesController { 13 | public weak var presentationDelegate: PresentationControllerDelegate? 14 | public var maxAnimationDelay: Double = 3 15 | 16 | private var backgroundContents = [Content]() 17 | private var slides = [SlideController]() 18 | private var animationsForPages = [Int : [Animatable]]() 19 | 20 | private var animationIndex = 0 21 | private weak var scrollView: UIScrollView? 22 | private var animationTimer: Timer? 23 | 24 | public convenience init(pages: [UIViewController]) { 25 | self.init( 26 | transitionStyle: .scroll, 27 | navigationOrientation: .horizontal, 28 | options: nil 29 | ) 30 | 31 | add(pages) 32 | } 33 | 34 | // MARK: - View lifecycle 35 | 36 | open override func viewDidLoad() { 37 | pagesDelegate = self 38 | super.viewDidLoad() 39 | } 40 | 41 | open override func viewDidAppear(_ animated: Bool) { 42 | super.viewDidAppear(animated) 43 | 44 | for subview in view.subviews { 45 | if subview is UIScrollView { 46 | scrollView = subview as? UIScrollView 47 | scrollView?.delegate = self 48 | } 49 | } 50 | 51 | animateAtIndex(0, perform: { animation in 52 | animation.play() 53 | }) 54 | } 55 | 56 | // MARK: - Public methods 57 | 58 | open override func goTo(_ index: Int) { 59 | startAnimationTimer() 60 | 61 | super.goTo(index) 62 | 63 | if index >= 0 && index < pagesCount { 64 | let reverse = index < animationIndex 65 | if !reverse { 66 | animationIndex = index 67 | } 68 | 69 | for slide in slides { 70 | if reverse { 71 | slide.goToLeft() 72 | } else { 73 | slide.goToRight() 74 | } 75 | } 76 | 77 | scrollView?.delegate = nil 78 | 79 | animateAtIndex(animationIndex, perform: { animation in 80 | if reverse { 81 | animation.playBack() 82 | } else { 83 | animation.play() 84 | } 85 | }) 86 | } 87 | } 88 | 89 | // MARK: - Animation Timer 90 | 91 | private func startAnimationTimer() { 92 | stopAnimationTimer() 93 | scrollView?.isUserInteractionEnabled = false 94 | 95 | if animationTimer == nil { 96 | DispatchQueue.main.async { 97 | self.animationTimer = Timer.scheduledTimer(timeInterval: self.maxAnimationDelay, 98 | target: self, 99 | selector: #selector(self.updateAnimationTimer(_:)), 100 | userInfo: nil, 101 | repeats: false) 102 | RunLoop.current.add(self.animationTimer!, forMode: RunLoop.Mode.common) 103 | } 104 | } 105 | } 106 | 107 | private func stopAnimationTimer() { 108 | animationTimer?.invalidate() 109 | animationTimer = nil 110 | } 111 | 112 | @objc func updateAnimationTimer(_ timer: Timer) { 113 | stopAnimationTimer() 114 | scrollView?.isUserInteractionEnabled = true 115 | } 116 | 117 | // MARK: - Content 118 | 119 | open override func add(_ viewControllers: [UIViewController]) { 120 | for case let controller as SlideController in viewControllers { 121 | slides.append(controller) 122 | } 123 | super.add(viewControllers) 124 | } 125 | 126 | public func addToBackground(_ elements: [Content]) { 127 | for content in elements { 128 | backgroundContents.append(content) 129 | view.addSubview(content.view) 130 | view.sendSubviewToBack(content.view) 131 | content.layout() 132 | } 133 | } 134 | } 135 | 136 | // MARK: - Animations 137 | 138 | extension PresentationController { 139 | public func addAnimations(_ animations: [Animatable], forPage page: Int) { 140 | for animation in animations { 141 | addAnimation(animation, forPage: page) 142 | } 143 | } 144 | 145 | public func addAnimation(_ animation: Animatable, forPage page: Int) { 146 | if animationsForPages[page] == nil { 147 | animationsForPages[page] = [] 148 | } 149 | animationsForPages[page]?.append(animation) 150 | } 151 | 152 | private func animateAtIndex(_ index: Int, perform: (_ animation: Animatable) -> Void) { 153 | if let animations = animationsForPages[index] { 154 | for animation in animations { 155 | perform(animation) 156 | } 157 | } 158 | } 159 | } 160 | 161 | // MARK: - PagesControllerDelegate 162 | 163 | extension PresentationController: PagesControllerDelegate { 164 | open func pageViewController(_ pageViewController: UIPageViewController, 165 | setViewController viewController: UIViewController, 166 | atPage page: Int) { 167 | animationIndex = page 168 | scrollView?.delegate = self 169 | 170 | presentationDelegate?.presentationController( 171 | self, 172 | didSetViewController: viewController, 173 | atPage: page 174 | ) 175 | } 176 | } 177 | 178 | // MARK: - UIScrollViewDelegate 179 | 180 | extension PresentationController: UIScrollViewDelegate { 181 | open func scrollViewDidScroll(_ scrollView: UIScrollView) { 182 | let offset = scrollView.contentOffset.x - (view.frame).width 183 | let offsetRatio = offset / (view.frame).width 184 | var index = animationIndex 185 | 186 | if offsetRatio > 0.0 || index == 0 { 187 | index += 1 188 | } 189 | 190 | let canMove = offsetRatio != 0.0 && 191 | !(animationIndex == 0 && offsetRatio < 0.0) && 192 | !(index == pagesCount) 193 | 194 | if canMove { 195 | animateAtIndex(index, perform: { animation in 196 | animation.moveWith(offsetRatio: offsetRatio) 197 | }) 198 | for slide in slides { 199 | if index <= animationIndex { 200 | slide.goToLeft() 201 | } else { 202 | slide.goToRight() 203 | } 204 | } 205 | } 206 | 207 | scrollView.layoutIfNeeded() 208 | view.layoutIfNeeded() 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /Source/SlideController.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | 3 | open class SlideController: UIViewController { 4 | private var contents = [Content]() 5 | private var animations = [Animatable]() 6 | private var visible = false 7 | 8 | public convenience init(contents: [Content]) { 9 | self.init() 10 | add(contents: contents) 11 | } 12 | 13 | // MARK: - View lifecycle 14 | 15 | open override func viewWillAppear(_ animated: Bool) { 16 | super.viewWillAppear(animated) 17 | 18 | if !visible { 19 | visible = true 20 | for content in contents { 21 | content.layout() 22 | } 23 | 24 | for animation in animations { 25 | animation.play() 26 | } 27 | } 28 | } 29 | 30 | open override func viewDidDisappear(_ animated: Bool) { 31 | super.viewDidDisappear(animated) 32 | visible = false 33 | } 34 | 35 | // MARK: - Navigation 36 | 37 | open func goToLeft() { 38 | for case let animation as TransitionAnimation in animations { 39 | animation.reflective = true 40 | } 41 | } 42 | 43 | open func goToRight() { 44 | for case let animation as TransitionAnimation in animations { 45 | animation.reflective = false 46 | } 47 | } 48 | } 49 | 50 | // MARK: - Public methods 51 | 52 | public extension SlideController { 53 | func add(contents: [Content]) { 54 | for content in contents { 55 | add(content: content) 56 | } 57 | } 58 | 59 | func add(content: Content) { 60 | contents.append(content) 61 | view.addSubview(content.view) 62 | content.layout() 63 | } 64 | 65 | func add(animations: [Animatable]) { 66 | for animation in animations { 67 | add(animation: animation) 68 | } 69 | } 70 | 71 | func add(animation: Animatable) { 72 | animations.append(animation) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /SupportFiles/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | --------------------------------------------------------------------------------