├── .gitignore ├── .travis.yml ├── Example ├── Podfile ├── Podfile.lock ├── Pods │ ├── Local Podspecs │ │ └── TransitionController.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ └── Target Support Files │ │ ├── Pods-TransitionController_Example │ │ ├── Info.plist │ │ ├── Pods-TransitionController_Example-acknowledgements.markdown │ │ ├── Pods-TransitionController_Example-acknowledgements.plist │ │ ├── Pods-TransitionController_Example-dummy.m │ │ ├── Pods-TransitionController_Example-frameworks.sh │ │ ├── Pods-TransitionController_Example-resources.sh │ │ ├── Pods-TransitionController_Example-umbrella.h │ │ ├── Pods-TransitionController_Example.debug.xcconfig │ │ ├── Pods-TransitionController_Example.modulemap │ │ └── Pods-TransitionController_Example.release.xcconfig │ │ ├── Pods-TransitionController_Tests │ │ ├── Info.plist │ │ ├── Pods-TransitionController_Tests-acknowledgements.markdown │ │ ├── Pods-TransitionController_Tests-acknowledgements.plist │ │ ├── Pods-TransitionController_Tests-dummy.m │ │ ├── Pods-TransitionController_Tests-frameworks.sh │ │ ├── Pods-TransitionController_Tests-resources.sh │ │ ├── Pods-TransitionController_Tests-umbrella.h │ │ ├── Pods-TransitionController_Tests.debug.xcconfig │ │ ├── Pods-TransitionController_Tests.modulemap │ │ └── Pods-TransitionController_Tests.release.xcconfig │ │ └── TransitionController │ │ ├── Info.plist │ │ ├── TransitionController-dummy.m │ │ ├── TransitionController-prefix.pch │ │ ├── TransitionController-umbrella.h │ │ ├── TransitionController.modulemap │ │ └── TransitionController.xcconfig ├── Tests │ ├── Info.plist │ └── Tests.swift ├── TransitionController.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ └── TransitionController-Example.xcscheme ├── TransitionController.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── TransitionController │ ├── AppDelegate.swift │ ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard │ ├── Extensions │ └── UIImageView+frameForImageInImageViewAspectFit.swift │ ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── Resoruces │ ├── image1.jpg │ ├── image2.jpg │ ├── image3.jpg │ ├── image4.jpg │ ├── image5.jpg │ ├── image6.jpg │ ├── image7.jpg │ ├── image8.jpg │ ├── image9.jpg │ └── text.txt │ ├── Transition │ ├── Image │ │ ├── Image.storyboard │ │ ├── ImageTransitionController.swift │ │ └── ImageViewController.swift │ ├── SlideImages │ │ ├── Cell.swift │ │ ├── HorizontalSlideNavigationController.swift │ │ ├── HorizontalSlideViewController.swift │ │ ├── SlideImages.storyboard │ │ └── SlideImagesViewController.swift │ ├── TabBar │ │ ├── CustomTabBarController.swift │ │ ├── TabBar.storyboard │ │ └── TabController.swift │ └── Text │ │ ├── Text.storyboard │ │ ├── TextDetailViewController.swift │ │ ├── TextNavigationController.swift │ │ └── TextViewController.swift │ └── ViewController.swift ├── LICENSE ├── README.md ├── TransitionController.podspec ├── TransitionController ├── Assets │ └── .gitkeep └── Classes │ ├── .gitkeep │ ├── BaseTransition.swift │ ├── Controller │ ├── AnimatedTransition.swift │ ├── CommonTransition.swift │ ├── TransitionCollectionViewController.swift │ ├── TransitionNavigationController.swift │ ├── TransitionTabBarController.swift │ ├── TransitionTableViewController.swift │ └── TransitionViewController.swift │ ├── Extensions │ └── UIView+imageWithView.swift │ └── TransitionDelegate.swift ├── _Pods.xcodeproj └── img ├── single.gif ├── single.png ├── slide.gif └── slide.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots/**/*.png 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # references: 2 | # * https://www.objc.io/issues/6-build-tools/travis-ci/ 3 | # * https://github.com/supermarin/xcpretty#usage 4 | 5 | osx_image: xcode12.2 6 | language: swift 7 | # cache: cocoapods 8 | podfile: Example/Podfile 9 | before_install: 10 | - gem install cocoapods # Since Travis is not always on latest version 11 | - pod install --project-directory=Example 12 | script: 13 | - xcodebuild -version 14 | - xcodebuild -showsdks 15 | - xcodebuild -list 16 | - set -o pipefail && xcodebuild test -workspace Example/TransitionController.xcworkspace -scheme TransitionController-Example -destination 'platform=iOS Simulator,name=iPhone 12,OS=14.2' | xcpretty 17 | - pod lib lint 18 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | 3 | target 'TransitionController_Example' do 4 | pod 'TransitionController', :path => '../' 5 | 6 | target 'TransitionController_Tests' do 7 | inherit! :search_paths 8 | 9 | 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - TransitionController (0.1.0) 3 | 4 | DEPENDENCIES: 5 | - TransitionController (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | TransitionController: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | TransitionController: f0dade7a898fb71bc539c9c9da4612cc3ad6264a 13 | 14 | PODFILE CHECKSUM: b9c1a70a50c238bfa7554e601d742db820bc75ed 15 | 16 | COCOAPODS: 1.5.3 17 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/TransitionController.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TransitionController", 3 | "version": "0.1.0", 4 | "summary": "A short description of TransitionController.", 5 | "description": "TODO: Add long description of the pod here.", 6 | "homepage": "https://github.com/pikachu987/TransitionController", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "pikachu987": "pikachu77769@gmail.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/pikachu987/TransitionController.git", 16 | "tag": "0.1.0" 17 | }, 18 | "platforms": { 19 | "ios": "8.0" 20 | }, 21 | "source_files": "TransitionController/Classes/**/*" 22 | } 23 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - TransitionController (0.1.0) 3 | 4 | DEPENDENCIES: 5 | - TransitionController (from `../`) 6 | 7 | EXTERNAL SOURCES: 8 | TransitionController: 9 | :path: "../" 10 | 11 | SPEC CHECKSUMS: 12 | TransitionController: f0dade7a898fb71bc539c9c9da4612cc3ad6264a 13 | 14 | PODFILE CHECKSUM: b9c1a70a50c238bfa7554e601d742db820bc75ed 15 | 16 | COCOAPODS: 1.5.3 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/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.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## TransitionController 5 | 6 | Copyright (c) 2019 pikachu987 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2019 pikachu987 <pikachu77769@gmail.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | TransitionController 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_TransitionController_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_TransitionController_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | 145 | if [[ "$CONFIGURATION" == "Debug" ]]; then 146 | install_framework "${BUILT_PRODUCTS_DIR}/TransitionController/TransitionController.framework" 147 | fi 148 | if [[ "$CONFIGURATION" == "Release" ]]; then 149 | install_framework "${BUILT_PRODUCTS_DIR}/TransitionController/TransitionController.framework" 150 | fi 151 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 152 | wait 153 | fi 154 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_TransitionController_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_TransitionController_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TransitionController" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/TransitionController/TransitionController.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "TransitionController" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_TransitionController_Example { 2 | umbrella header "Pods-TransitionController_Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Example/Pods-TransitionController_Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TransitionController" 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 5 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/TransitionController/TransitionController.framework/Headers" 6 | OTHER_LDFLAGS = $(inherited) -framework "TransitionController" 7 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/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.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | Generated by CocoaPods - https://cocoapods.org 4 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Generated by CocoaPods - https://cocoapods.org 18 | Title 19 | 20 | Type 21 | PSGroupSpecifier 22 | 23 | 24 | StringsTable 25 | Acknowledgements 26 | Title 27 | Acknowledgements 28 | 29 | 30 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_TransitionController_Tests : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_TransitionController_Tests 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_TransitionController_TestsVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_TransitionController_TestsVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests.debug.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TransitionController" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/TransitionController/TransitionController.framework/Headers" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_TransitionController_Tests { 2 | umbrella header "Pods-TransitionController_Tests-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-TransitionController_Tests/Pods-TransitionController_Tests.release.xcconfig: -------------------------------------------------------------------------------- 1 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/TransitionController" 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' 4 | OTHER_CFLAGS = $(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/TransitionController/TransitionController.framework/Headers" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 8 | PODS_ROOT = ${SRCROOT}/Pods 9 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/TransitionController/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 | $(MARKETING_VERSION) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/TransitionController/TransitionController-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_TransitionController : NSObject 3 | @end 4 | @implementation PodsDummy_TransitionController 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/TransitionController/TransitionController-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/TransitionController/TransitionController-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double TransitionControllerVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char TransitionControllerVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/TransitionController/TransitionController.modulemap: -------------------------------------------------------------------------------- 1 | framework module TransitionController { 2 | umbrella header "TransitionController-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/TransitionController/TransitionController.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/TransitionController 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) "-D" "COCOAPODS" 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Example/Tests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Tests/Tests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | import TransitionController 3 | 4 | class Tests: XCTestCase { 5 | 6 | override func setUp() { 7 | super.setUp() 8 | // Put setup code here. This method is called before the invocation of each test method in the class. 9 | } 10 | 11 | override func tearDown() { 12 | // Put teardown code here. This method is called after the invocation of each test method in the class. 13 | super.tearDown() 14 | } 15 | 16 | func testExample() { 17 | // This is an example of a functional test case. 18 | XCTAssert(true, "Pass") 19 | } 20 | 21 | func testPerformanceExample() { 22 | // This is an example of a performance test case. 23 | self.measure() { 24 | // Put the code you want to measure the time of here. 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /Example/TransitionController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/TransitionController.xcodeproj/xcshareddata/xcschemes/TransitionController-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 67 | 68 | 78 | 80 | 86 | 87 | 88 | 89 | 90 | 91 | 97 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /Example/TransitionController.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/TransitionController.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/TransitionController/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(_ application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(_ application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(_ application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(_ application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(_ application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /Example/TransitionController/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/TransitionController/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /Example/TransitionController/Extensions/UIImageView+frameForImageInImageViewAspectFit.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIImageView+frameForImageInImageViewAspectFit.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UIImageView { 12 | var frameForImageInImageViewAspectFit: CGRect { 13 | if let img = self.image { 14 | let imageRatio = img.size.width / img.size.height 15 | let viewRatio = self.frame.size.width / self.frame.size.height 16 | if(imageRatio < viewRatio) { 17 | let scale = self.frame.size.height / img.size.height 18 | let width = scale * img.size.width 19 | let topLeftX = (self.frame.size.width - width) * 0.5 20 | return CGRect(x: topLeftX, y: 0, width: width, height: self.frame.size.height) 21 | } else { 22 | let scale = self.frame.size.width / img.size.width 23 | let height = scale * img.size.height 24 | let topLeftY = (self.frame.size.height - height) * 0.5 25 | return CGRect(x: 0, y: topLeftY, width: self.frame.size.width, height: height) 26 | } 27 | } 28 | return CGRect(x: 0, y: 0, width: 0, height: 0) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Example/TransitionController/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "size" : "1024x1024", 46 | "scale" : "1x" 47 | } 48 | ], 49 | "info" : { 50 | "version" : 1, 51 | "author" : "xcode" 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/TransitionController/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 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image1.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image2.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image3.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image4.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image5.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image6.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image7.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image8.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/image9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/Example/TransitionController/Resoruces/image9.jpg -------------------------------------------------------------------------------- /Example/TransitionController/Resoruces/text.txt: -------------------------------------------------------------------------------- 1 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 2 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 3 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 4 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 5 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 6 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 7 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 8 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 9 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 10 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 11 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 12 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 13 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 14 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 15 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 16 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 17 | 18 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/Image/Image.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 37 | 38 | 39 | 40 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/Image/ImageTransitionController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageTransitionController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | class ImageTransitionController: TransitionViewController { 13 | @IBOutlet private weak var scrollView: UIScrollView! 14 | @IBOutlet private weak var imageView: UIImageView! 15 | 16 | var image: UIImage? 17 | 18 | override var presentToView: UIView? { 19 | let view = UIView(frame: self.imageView.frameForImageInImageViewAspectFit) 20 | view.contentMode = .scaleAspectFit 21 | return view 22 | } 23 | 24 | override var dismissFromView: UIView? { 25 | return self.imageView 26 | } 27 | 28 | override var dismissFromImage: UIImage? { 29 | return self.image 30 | } 31 | 32 | override func viewDidLoad() { 33 | super.viewDidLoad() 34 | 35 | self.imageView.image = image 36 | self.imageView.clipsToBounds = true 37 | self.imageView.contentMode = .scaleAspectFit 38 | 39 | self.scrollView.backgroundColor = .clear 40 | self.scrollView.zoomScale = 1 41 | self.scrollView.minimumZoomScale = 0.1 42 | self.scrollView.maximumZoomScale = 3 43 | self.scrollView.clipsToBounds = true 44 | self.scrollView.showsVerticalScrollIndicator = false 45 | self.scrollView.showsHorizontalScrollIndicator = false 46 | self.scrollView.delegate = self 47 | } 48 | } 49 | 50 | // MARK: UIScrollViewDelegate 51 | extension ImageTransitionController: UIScrollViewDelegate { 52 | func viewForZooming(in scrollView: UIScrollView) -> UIView? { 53 | return self.imageView 54 | } 55 | 56 | func scrollViewDidZoom(_ scrollView: UIScrollView) { 57 | if scrollView.zoomScale <= 1 { 58 | let offsetX = max((scrollView.bounds.width - scrollView.contentSize.width) * 0.5, 0) 59 | let offsetY = max((scrollView.bounds.height - scrollView.contentSize.height) * 0.5, 0) 60 | scrollView.contentInset = UIEdgeInsets(top: offsetY, left: offsetX, bottom: 0, right: 0) 61 | } else { 62 | let imageSize = self.imageView.frameForImageInImageViewAspectFit 63 | 64 | let widthRate = self.view.bounds.width / imageSize.width 65 | let heightRate = self.view.bounds.height / imageSize.height 66 | 67 | if widthRate < heightRate { 68 | let imageOffset = -imageSize.origin.y 69 | let scrollOffset = (scrollView.bounds.height - scrollView.contentSize.height) * 0.5 70 | if imageOffset > scrollOffset { 71 | scrollView.contentInset = UIEdgeInsets(top: imageOffset, left: 0, bottom: imageOffset, right: 0) 72 | } else { 73 | scrollView.contentInset = UIEdgeInsets(top: scrollOffset, left: 0, bottom: scrollOffset, right: 0) 74 | } 75 | } else { 76 | let imageOffset = -imageSize.origin.x 77 | let scrollOffset = (scrollView.bounds.width - scrollView.contentSize.width) * 0.5 78 | if imageOffset > scrollOffset { 79 | scrollView.contentInset = UIEdgeInsets(top: 0, left: imageOffset, bottom: 0, right: imageOffset) 80 | } else { 81 | scrollView.contentInset = UIEdgeInsets(top: 0, left: scrollOffset, bottom: 0, right: scrollOffset) 82 | } 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/Image/ImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | class ImageViewController: UIViewController { 13 | @IBOutlet private weak var imageView: UIImageView! 14 | @IBOutlet private weak var colorSwitch: UISwitch! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | self.imageView.clipsToBounds = true 20 | self.imageView.contentMode = .scaleAspectFill 21 | self.imageView.layer.cornerRadius = self.imageView.frame.width/2 22 | } 23 | 24 | @IBAction private func transitionTap(_ sender: UIButton) { 25 | guard let viewController = UIStoryboard(name: "Image", bundle: nil).instantiateViewController(withIdentifier: "ImageTransitionController") as? ImageTransitionController else { return } 26 | viewController.transitionDelegate = self 27 | viewController.image = self.imageView.image 28 | viewController.view.backgroundColor = self.colorSwitch.isOn ? .black : .white 29 | self.present(viewController, animated: true, completion: nil) 30 | } 31 | } 32 | 33 | // MARK: TransitionDelegate 34 | extension ImageViewController: TransitionDelegate { 35 | var transitionSuperview: UIView { 36 | return self.view 37 | } 38 | 39 | func transitionPresentFromView(_ base: BaseTransition) -> UIView? { 40 | return self.imageView 41 | } 42 | 43 | func transitionPresentFromImage(_ base: BaseTransition) -> UIImage? { 44 | return self.imageView.image 45 | } 46 | 47 | func transitionDismissToView(_ base: BaseTransition) -> UIView? { 48 | return self.imageView 49 | } 50 | 51 | func transitionWillPresent(_ base: BaseTransition, viewController: UIViewController) { 52 | print("transitionWillPresent") 53 | } 54 | 55 | func transitionDidPresent(_ base: BaseTransition, viewController: UIViewController) { 56 | print("transitionDidPresent") 57 | } 58 | 59 | func transitionWillDismiss(_ base: BaseTransition, viewController: UIViewController) { 60 | print("transitionWillDismiss") 61 | } 62 | 63 | func transitionDidDismiss(_ base: BaseTransition, viewController: UIViewController) { 64 | print("transitionDidDismiss") 65 | } 66 | 67 | func transitionGesture(_ base: BaseTransition, viewController: UIViewController, gesture: UIPanGestureRecognizer, progress: CGFloat) { 68 | switch gesture.state { 69 | case .began: 70 | base.transitionView.backgroundColor = self.colorSwitch.isOn ? .black : .white 71 | case .changed: 72 | base.transitionView.backgroundColor = self.colorSwitch.isOn ? UIColor.black.withAlphaComponent(progress / 3) : UIColor.white.withAlphaComponent(progress / 3) 73 | default: 74 | break 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/SlideImages/Cell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Cell.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class Cell: UICollectionViewCell { 12 | static let identifier = "Cell" 13 | 14 | private let imageView: UIImageView = { 15 | let imageView = UIImageView() 16 | imageView.contentMode = .scaleAspectFill 17 | imageView.clipsToBounds = true 18 | return imageView 19 | }() 20 | 21 | var image: UIImage? { 22 | didSet { 23 | self.imageView.image = self.image 24 | } 25 | } 26 | 27 | override init(frame: CGRect) { 28 | super.init(frame: frame) 29 | 30 | self.contentMode = .scaleAspectFill 31 | self.contentView.addSubview(self.imageView) 32 | self.imageView.translatesAutoresizingMaskIntoConstraints = false 33 | self.contentView.addConstraints( 34 | NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": self.imageView]) 35 | ) 36 | self.contentView.addConstraints( 37 | NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": self.imageView]) 38 | ) 39 | } 40 | 41 | required init?(coder aDecoder: NSCoder) { 42 | fatalError("init(coder:) has not been implemented") 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/SlideImages/HorizontalSlideNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HorizontalSlideNavigationController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | class HorizontalSlideNavigationController: TransitionNavigationController { 13 | override var dismissFromView: UIView? { 14 | guard let viewController = self.visibleViewController as? HorizontalSlideViewController else { return nil } 15 | return viewController.visibleCell 16 | } 17 | 18 | override var dismissFromImage: UIImage? { 19 | guard let viewController = self.visibleViewController as? HorizontalSlideViewController else { return nil } 20 | return viewController.visibleImage 21 | } 22 | 23 | override func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 24 | if let _ = gestureRecognizer as? UIScreenEdgePanGestureRecognizer { 25 | return true 26 | } else if let _ = gestureRecognizer as? UIPanGestureRecognizer { 27 | return (self.visibleViewController as? HorizontalSlideViewController) != nil 28 | } 29 | return false 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/SlideImages/HorizontalSlideViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HorizontalSlideViewController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | protocol HorizontalSlideDelegate: class { 13 | var horizontalSlideImages: [UIImage?] { get } 14 | func horizontalSlide(_ index: Int) 15 | } 16 | 17 | class HorizontalSlideViewController: UIViewController { 18 | weak var delegate: HorizontalSlideDelegate? 19 | 20 | private let collectonView: UICollectionView = { 21 | let flowLayout = UICollectionViewFlowLayout() 22 | flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height) 23 | flowLayout.minimumInteritemSpacing = 0 24 | flowLayout.minimumLineSpacing = 0 25 | flowLayout.scrollDirection = .horizontal 26 | flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 27 | let collectonView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) 28 | collectonView.isPagingEnabled = true 29 | collectonView.register(Cell.self, forCellWithReuseIdentifier: Cell.identifier) 30 | return collectonView 31 | }() 32 | 33 | var visibleCell: UICollectionViewCell? { 34 | guard let currentIndexKey = (self.navigationController as? TransitionNavigationController)?.key as? Int else { return nil } 35 | return self.collectonView.cellForItem(at: IndexPath(item: currentIndexKey, section: 0)) 36 | } 37 | 38 | var visibleImage: UIImage? { 39 | guard let currentIndexKey = (self.navigationController as? TransitionNavigationController)?.key as? Int else { return nil } 40 | return self.delegate?.horizontalSlideImages[currentIndexKey] 41 | } 42 | 43 | override func viewDidLoad() { 44 | super.viewDidLoad() 45 | 46 | if #available(iOS 11.0, *) { 47 | self.collectonView.contentInsetAdjustmentBehavior = .never 48 | } else { 49 | self.automaticallyAdjustsScrollViewInsets = false 50 | } 51 | self.view.backgroundColor = .black 52 | self.view.addSubview(self.collectonView) 53 | self.collectonView.translatesAutoresizingMaskIntoConstraints = false 54 | self.view.addConstraints( 55 | NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": self.collectonView]) 56 | ) 57 | self.view.addConstraints( 58 | NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": self.collectonView]) 59 | ) 60 | 61 | self.collectonView.delegate = self 62 | self.collectonView.dataSource = self 63 | 64 | if let index = (self.navigationController as? TransitionNavigationController)?.key as? Int { 65 | DispatchQueue.main.async { 66 | self.collectonView.scrollToItem(at: IndexPath(item: index, section: 0), at: .centeredHorizontally, animated: false) 67 | } 68 | } 69 | 70 | let tempButton = UIButton(frame: CGRect(x: 20, y: UIScreen.main.bounds.height - 100, width: 120, height: 40)) 71 | tempButton.setTitle("Temp Next", for: .normal) 72 | tempButton.layer.cornerRadius = 4 73 | tempButton.backgroundColor = .gray 74 | tempButton.addTarget(self, action: #selector(self.tempNextTap(_:)), for: .touchUpInside) 75 | self.view.addSubview(tempButton) 76 | } 77 | 78 | override func viewWillAppear(_ animated: Bool) { 79 | super.viewWillAppear(animated) 80 | 81 | (self.navigationController as? TransitionNavigationController)?.navigationBarColor = .clear 82 | } 83 | 84 | override func viewWillDisappear(_ animated: Bool) { 85 | super.viewWillDisappear(animated) 86 | 87 | (self.navigationController as? TransitionNavigationController)?.navigationBarColor = nil 88 | } 89 | 90 | @objc private func tempNextTap(_ sender: UIButton) { 91 | guard let textURL = Bundle.main.url(forResource: "text", withExtension: "txt") else { return } 92 | let tempViewController = UIViewController() 93 | tempViewController.view.backgroundColor = .white 94 | let textView = UITextView(frame: UIScreen.main.bounds) 95 | tempViewController.view.addSubview(textView) 96 | textView.text = try? String(contentsOf: textURL) 97 | self.navigationController?.pushViewController(tempViewController, animated: true) 98 | } 99 | } 100 | 101 | // MARK: UICollectionViewDelegate 102 | extension HorizontalSlideViewController: UICollectionViewDelegate { 103 | func scrollViewDidScroll(_ scrollView: UIScrollView) { 104 | guard let count = self.delegate?.horizontalSlideImages.count else { return } 105 | guard let currentIndexKey = (self.navigationController as? TransitionNavigationController)?.key as? Int else { return } 106 | let deltaOffset = scrollView.contentSize.width - scrollView.frame.size.width - scrollView.contentOffset.x 107 | let index = CGFloat(count) - deltaOffset/scrollView.frame.size.width - 1 108 | let currentIndex = Int(round(index)) 109 | if currentIndexKey != currentIndex && currentIndex >= 0 && currentIndex < count { 110 | (self.navigationController as? TransitionNavigationController)?.key = currentIndex 111 | self.delegate?.horizontalSlide(currentIndex) 112 | } 113 | } 114 | } 115 | 116 | // MARK: UICollectionViewDataSource 117 | extension HorizontalSlideViewController: UICollectionViewDataSource { 118 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 119 | return self.delegate?.horizontalSlideImages.count ?? 0 120 | } 121 | 122 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 123 | guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Cell.identifier, for: indexPath) as? Cell else { fatalError() } 124 | cell.image = self.delegate?.horizontalSlideImages[indexPath.item] 125 | return cell 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/SlideImages/SlideImages.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/SlideImages/SlideImagesViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SlideImagesViewController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | class SlideImagesViewController: UIViewController { 13 | private var array = [UIImage?]() 14 | 15 | private let collectonView: UICollectionView = { 16 | let flowLayout = UICollectionViewFlowLayout() 17 | flowLayout.itemSize = CGSize(width: UIScreen.main.bounds.width/3, height: UIScreen.main.bounds.width/3) 18 | flowLayout.minimumInteritemSpacing = 0 19 | flowLayout.minimumLineSpacing = 0 20 | flowLayout.scrollDirection = .vertical 21 | flowLayout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 22 | let collectonView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout) 23 | collectonView.register(Cell.self, forCellWithReuseIdentifier: Cell.identifier) 24 | return collectonView 25 | }() 26 | 27 | override func viewDidLoad() { 28 | super.viewDidLoad() 29 | 30 | self.view.addSubview(self.collectonView) 31 | self.collectonView.translatesAutoresizingMaskIntoConstraints = false 32 | self.view.addConstraints( 33 | NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": self.collectonView]) 34 | ) 35 | self.view.addConstraints( 36 | NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": self.collectonView]) 37 | ) 38 | self.collectonView.delegate = self 39 | self.collectonView.dataSource = self 40 | 41 | let indicator = UIActivityIndicatorView(style: .white) 42 | indicator.startAnimating() 43 | indicator.frame.origin = self.view.center 44 | self.view.addSubview(indicator) 45 | DispatchQueue.global().async { 46 | var array = [UIImage?]() 47 | for index in 1...9 { 48 | array.append(UIImage(named: "image\(index).jpg")) 49 | } 50 | array.append(contentsOf: array) 51 | array.append(contentsOf: array) 52 | array.append(contentsOf: array) 53 | self.array = array 54 | DispatchQueue.main.async { 55 | indicator.stopAnimating() 56 | indicator.removeFromSuperview() 57 | self.collectonView.reloadData() 58 | } 59 | } 60 | } 61 | } 62 | 63 | // MARK: UICollectionViewDelegate 64 | extension SlideImagesViewController: UICollectionViewDelegate { 65 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 66 | let viewController = HorizontalSlideViewController() 67 | viewController.delegate = self 68 | let navigationController = HorizontalSlideNavigationController(rootViewController: viewController) 69 | navigationController.transitionDelegate = self 70 | navigationController.key = indexPath.item 71 | navigationController.navigationBarColor = .clear 72 | navigationController.view.backgroundColor = .black 73 | self.present(navigationController, animated: true, completion: nil) 74 | } 75 | } 76 | 77 | // MARK: UICollectionViewDataSource 78 | extension SlideImagesViewController: UICollectionViewDataSource { 79 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 80 | return self.array.count 81 | } 82 | 83 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 84 | guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Cell.identifier, for: indexPath) as? Cell else { fatalError() } 85 | cell.image = self.array[indexPath.item] 86 | return cell 87 | } 88 | } 89 | 90 | // MARK: HorizontalSlideDelegate 91 | extension SlideImagesViewController: HorizontalSlideDelegate { 92 | var horizontalSlideImages: [UIImage?] { 93 | return self.array 94 | } 95 | 96 | func horizontalSlide(_ index: Int) { 97 | self.collectonView.scrollToItem(at: IndexPath(item: index, section: 0), at: .centeredVertically, animated: false) 98 | } 99 | } 100 | 101 | // MARK: TransitionDelegate 102 | extension SlideImagesViewController: TransitionDelegate { 103 | var transitionSuperview: UIView { 104 | return self.view 105 | } 106 | 107 | func transitionPresentFromView(_ base: BaseTransition) -> UIView? { 108 | guard let index = base.key as? Int else { return nil } 109 | return self.collectonView.cellForItem(at: IndexPath(item: index, section: 0)) 110 | } 111 | 112 | func transitionPresentFromImage(_ base: BaseTransition) -> UIImage? { 113 | guard let index = base.key as? Int else { return nil } 114 | return self.array[index] 115 | } 116 | 117 | func transitionDismissToView(_ base: BaseTransition) -> UIView? { 118 | guard let index = base.key as? Int else { return nil } 119 | return self.collectonView.cellForItem(at: IndexPath(item: index, section: 0)) 120 | } 121 | 122 | func transitionWillPresent(_ base: BaseTransition, viewController: UIViewController) { 123 | print("transitionWillPresent") 124 | } 125 | 126 | func transitionDidPresent(_ base: BaseTransition, viewController: UIViewController) { 127 | print("transitionDidPresent") 128 | } 129 | 130 | func transitionWillDismiss(_ base: BaseTransition, viewController: UIViewController) { 131 | print("transitionWillDismiss") 132 | } 133 | 134 | func transitionDidDismiss(_ base: BaseTransition, viewController: UIViewController) { 135 | print("transitionDidDismiss") 136 | } 137 | 138 | } 139 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/TabBar/CustomTabBarController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CustomTabBarController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | class CustomTabBarController: TransitionTabBarController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | 17 | self.view.backgroundColor = .white 18 | 19 | var viewControllers = [UIViewController]() 20 | 21 | let viewControllerFirst = UIViewController() 22 | viewControllerFirst.view.backgroundColor = .white 23 | viewControllerFirst.tabBarItem = UITabBarItem(title: "First", image: nil, selectedImage: nil) 24 | viewControllers.append(viewControllerFirst) 25 | 26 | let viewControllerSecond = UIViewController() 27 | viewControllerSecond.view.backgroundColor = .white 28 | viewControllerSecond.tabBarItem = UITabBarItem(title: "Second", image: nil, selectedImage: nil) 29 | viewControllers.append(viewControllerSecond) 30 | 31 | let viewControllerThrid = UIViewController() 32 | viewControllerThrid.view.backgroundColor = .white 33 | viewControllerThrid.tabBarItem = UITabBarItem(title: "Third", image: nil, selectedImage: nil) 34 | viewControllers.append(viewControllerThrid) 35 | 36 | self.setViewControllers(viewControllers, animated: false) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/TabBar/TabBar.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/TabBar/TabController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TabController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | class TabController: UIViewController { 13 | @IBOutlet private weak var tabButton: UIButton! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | self.view.backgroundColor = UIColor(red: 236/255, green: 232/255, blue: 219/255, alpha: 1) 19 | self.tabButton.layer.cornerRadius = self.tabButton.frame.width/2 20 | self.tabButton.backgroundColor = UIColor(red: 72/255, green: 91/255, blue: 102/255, alpha: 1) 21 | self.tabButton.setTitleColor(UIColor(red: 215/255, green: 202/255, blue: 182/255, alpha: 1), for: .normal) 22 | self.tabButton.clipsToBounds = true 23 | } 24 | 25 | @IBAction private func tab(_ sender: UIButton) { 26 | let tabBarController = CustomTabBarController() 27 | tabBarController.transitionDelegate = self 28 | self.present(tabBarController, animated: true, completion: nil) 29 | } 30 | } 31 | 32 | // MARK: TransitionDelegate 33 | extension TabController: TransitionDelegate { 34 | var transitionSuperview: UIView { 35 | return self.view 36 | } 37 | 38 | func transitionPresentFromView(_ base: BaseTransition) -> UIView? { 39 | return self.tabButton 40 | } 41 | 42 | func transitionDismissToView(_ base: BaseTransition) -> UIView? { 43 | return self.tabButton 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/Text/Text.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/Text/TextDetailViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextDetailViewController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class TextDetailViewController: UIViewController { 12 | var text: String? 13 | 14 | @IBOutlet private weak var textView: UITextView! 15 | 16 | override func viewDidLoad() { 17 | super.viewDidLoad() 18 | 19 | self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Close", style: .plain, target: self, action: #selector(self.backTap(_:))) 20 | 21 | self.textView.isEditable = false 22 | self.textView.text = self.text 23 | 24 | DispatchQueue.main.async { 25 | self.textView.scrollRangeToVisible(NSRange(location: 0, length: 0)) 26 | } 27 | } 28 | 29 | @objc private func backTap(_ sender: UIBarButtonItem) { 30 | self.dismiss(animated: true, completion: nil) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/Text/TextNavigationController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextNavigationController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | class TextNavigationController: TransitionNavigationController { 13 | override var presentToView: UIView? { 14 | guard let _ = self.visibleViewController as? TextDetailViewController else { return nil } 15 | let view = UIView() 16 | let top = UIApplication.shared.statusBarFrame.height + self.navigationBar.frame.height 17 | view.frame = CGRect(x: 0, y: top, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height - top) 18 | view.backgroundColor = .white 19 | return view 20 | } 21 | 22 | override func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 23 | if let _ = gestureRecognizer as? UIScreenEdgePanGestureRecognizer { 24 | return true 25 | } else if let _ = gestureRecognizer as? UIPanGestureRecognizer { 26 | return (self.visibleViewController as? HorizontalSlideViewController) != nil 27 | } 28 | return false 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Example/TransitionController/Transition/Text/TextViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TextViewController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import TransitionController 11 | 12 | class TextViewController: UIViewController { 13 | @IBOutlet private weak var textButton: UIButton! 14 | 15 | override func viewDidLoad() { 16 | super.viewDidLoad() 17 | 18 | self.view.backgroundColor = UIColor(red: 236/255, green: 232/255, blue: 219/255, alpha: 1) 19 | } 20 | 21 | @IBAction private func textTap(_ sender: UIButton) { 22 | guard let viewController = UIStoryboard(name: "Text", bundle: nil).instantiateViewController(withIdentifier: "TextDetailViewController") as? TextDetailViewController else { return } 23 | guard let textURL = Bundle.main.url(forResource: "text", withExtension: "txt") else { return } 24 | viewController.text = try? String(contentsOf: textURL) 25 | let navigationController = TextNavigationController(rootViewController: viewController) 26 | navigationController.transitionDelegate = self 27 | navigationController.view.backgroundColor = .white 28 | navigationController.key = sender 29 | self.present(navigationController, animated: true, completion: nil) 30 | } 31 | } 32 | 33 | // MARK: TransitionDelegate 34 | extension TextViewController: TransitionDelegate { 35 | var transitionSuperview: UIView { 36 | return self.view 37 | } 38 | 39 | func transitionPresentFromView(_ base: BaseTransition) -> UIView? { 40 | return self.textButton 41 | } 42 | 43 | func transitionDismissToView(_ base: BaseTransition) -> UIView? { 44 | return self.textButton 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Example/TransitionController/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // TransitionController 4 | // 5 | // Created by pikachu987 on 06/05/2019. 6 | // Copyright (c) 2019 pikachu987. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum ControllerType: String { 12 | case image = "Image Example" 13 | case text = "Text Example" 14 | case slideImages = "Slide Images Example" 15 | case tabBar = "Tab Bar Example" 16 | 17 | static var array: [ControllerType] { 18 | return [.image, .text, .slideImages, .tabBar] 19 | } 20 | } 21 | 22 | class ViewController: UIViewController { 23 | 24 | override func viewDidLoad() { 25 | super.viewDidLoad() 26 | // Do any additional setup after loading the view. 27 | 28 | } 29 | } 30 | 31 | extension ViewController: UITableViewDelegate { 32 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 33 | tableView.deselectRow(at: indexPath, animated: true) 34 | let type = ControllerType.array[indexPath.row] 35 | switch type { 36 | case .image: 37 | let viewController = UIStoryboard(name: "Image", bundle: nil).instantiateViewController(withIdentifier: "ImageViewController") 38 | self.navigationController?.pushViewController(viewController, animated: true) 39 | case .text: 40 | let viewController = UIStoryboard(name: "Text", bundle: nil).instantiateViewController(withIdentifier: "TextViewController") 41 | self.navigationController?.pushViewController(viewController, animated: true) 42 | case .slideImages: 43 | let viewController = UIStoryboard(name: "SlideImages", bundle: nil).instantiateViewController(withIdentifier: "SlideImagesViewController") 44 | self.navigationController?.pushViewController(viewController, animated: true) 45 | case .tabBar: 46 | let viewController = UIStoryboard(name: "TabBar", bundle: nil).instantiateViewController(withIdentifier: "TabController") 47 | self.navigationController?.pushViewController(viewController, animated: true) 48 | } 49 | 50 | } 51 | } 52 | 53 | extension ViewController: UITableViewDataSource { 54 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 55 | return ControllerType.array.count 56 | } 57 | 58 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 59 | let cell = UITableViewCell() 60 | cell.textLabel?.text = ControllerType.array[indexPath.row].rawValue 61 | return cell 62 | } 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 pikachu987 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TransitionController 2 | 3 | [![CI Status](https://img.shields.io/travis/pikachu987/TransitionController.svg?style=flat)](https://travis-ci.org/pikachu987/TransitionController) 4 | [![Version](https://img.shields.io/cocoapods/v/TransitionController.svg?style=flat)](https://cocoapods.org/pods/TransitionController) 5 | [![License](https://img.shields.io/cocoapods/l/TransitionController.svg?style=flat)](https://cocoapods.org/pods/TransitionController) 6 | [![Platform](https://img.shields.io/cocoapods/p/TransitionController.svg?style=flat)](https://cocoapods.org/pods/TransitionController) 7 | ![](https://img.shields.io/badge/Supported-iOS9%20%7C%20OSX%2010.9-4BC51D.svg?style=flat-square) 8 | ![](https://img.shields.io/badge/Swift-5.0-orange.svg?style=flat) 9 | 10 | ## Introduce 11 | 12 | You can dismiss transition and present transition between UIViewController, UINavigationController, UITabBarController, UICollectionViewController, and UITableViewController.
13 | Receives a delegate for the willPresent, didPresent, willDismiss and didDismiss of the ViewController. 14 | 15 | ||| 16 | |---|---| 17 | ||| 18 | 19 | 20 | ## Requirements 21 | 22 | `TransitionController` written in Swift 5.0. Compatible with iOS 9.0+ 23 | 24 | ## Installation 25 | 26 | TransitionController is available through [CocoaPods](https://cocoapods.org). To install 27 | it, simply add the following line to your Podfile: 28 | 29 | ```ruby 30 | pod 'TransitionController' 31 | ``` 32 | 33 | ## Usage 34 | 35 | ```swift 36 | import TransitionController 37 | ``` 38 | 39 | ```swift 40 | class ImageViewController { 41 | @IBOutlet private weak var imageView: UIImageView! 42 | 43 | @IBAction private func transitionTap(_ sender: UIButton) { 44 | guard let viewController = UIStoryboard(name: "Image", bundle: nil).instantiateViewController(withIdentifier: "ImageTransitionController") as? ImageTransitionController else { return } 45 | // let viewController = ImageTransitionController() 46 | 47 | viewController.transitionDelegate = self 48 | viewController.imageView.image = self.imageView.image 49 | self.present(viewController, animated: true, completion: nil) 50 | } 51 | } 52 | ``` 53 | 54 | ```swift 55 | // MARK: TransitionDelegate 56 | extension ImageViewController: TransitionDelegate { 57 | var transitionSuperview: UIView { 58 | return self.view 59 | } 60 | 61 | func transitionPresentFromView(_ base: BaseTransition) -> UIView? { 62 | return self.imageView 63 | } 64 | 65 | func transitionPresentFromImage(_ base: BaseTransition) -> UIImage? { 66 | return self.imageView.image 67 | } 68 | 69 | func transitionDismissToView(_ base: BaseTransition) -> UIView? { 70 | return self.imageView 71 | } 72 | } 73 | ``` 74 | 75 | #### TransitionController 76 | 77 | ```swift 78 | import UIKit 79 | import TransitionController 80 | 81 | class ImageTransitionController: TransitionViewController { 82 | @IBOutlet weak var imageView: UIImageView! 83 | 84 | override var presentToView: UIView? { 85 | let view = UIView(frame: self.imageView.frameForImageInImageViewAspectFit) 86 | view.contentMode = .scaleAspectFit 87 | return view 88 | } 89 | 90 | override var dismissFromView: UIView? { 91 | return self.imageView 92 | } 93 | 94 | override var dismissFromImage: UIImage? { 95 | return self.imageView.image 96 | } 97 | } 98 | ``` 99 | 100 | ```swift 101 | extension UIImageView { 102 | var frameForImageInImageViewAspectFit: CGRect { 103 | if let img = self.image { 104 | let imageRatio = img.size.width / img.size.height 105 | let viewRatio = self.frame.size.width / self.frame.size.height 106 | if(imageRatio < viewRatio) { 107 | let scale = self.frame.size.height / img.size.height 108 | let width = scale * img.size.width 109 | let topLeftX = (self.frame.size.width - width) * 0.5 110 | return CGRect(x: topLeftX, y: 0, width: width, height: self.frame.size.height) 111 | } else { 112 | let scale = self.frame.size.width / img.size.width 113 | let height = scale * img.size.height 114 | let topLeftY = (self.frame.size.height - height) * 0.5 115 | return CGRect(x: 0, y: topLeftY, width: self.frame.size.width, height: height) 116 | } 117 | } 118 | return CGRect(x: 0, y: 0, width: 0, height: 0) 119 | } 120 | } 121 | ``` 122 | 123 | Done! 🎉🎉🎉 124 | 125 |

126 | 127 | ### Superclass 128 | 129 | ```swift 130 | class ExampleViewController: TransitionViewController { 131 | 132 | } 133 | 134 | class ExampleNavigationController: TransitionNavigationController { 135 | 136 | } 137 | 138 | class ExampleTabBarController: TransitionTabBarController { 139 | 140 | } 141 | 142 | class ExampleTableViewController: TransitionTableViewController { 143 | 144 | } 145 | 146 | class ExampleCollectionViewController: TransitionCollectionViewController { 147 | 148 | } 149 | ``` 150 | 151 | ### BaseTransition Controller protocol 152 | 153 | ```swift 154 | // indexPath or sequence or etc 155 | var key: Any? { set get } 156 | 157 | // transitionContext.containerView 158 | // Top-level view of a transition 159 | var containerView: UIView? { get } 160 | 161 | 162 | // duration when present 163 | var presentDuration: TimeInterval { get } 164 | 165 | // destination view when present 166 | var presentToView: UIView? { get } 167 | 168 | 169 | // duration when dismiss 170 | var dismissDuration: TimeInterval { get } 171 | 172 | // Start point view when dismiss 173 | var dismissFromView: UIView? { get } 174 | 175 | // Start point image when dismiss 176 | var dismissFromImage: UIImage? { get } 177 | 178 | // gesture enabled 179 | // UINavigationController Back Swipe: UIScreenEdgePanGestureRecognizer 180 | // Transition Gesture: UIPanGestureRecognizer 181 | func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool 182 | ``` 183 | 184 | ### Delegate 185 | ```swift 186 | // MARK: TransitionDelegate 187 | extension ViewController: TransitionDelegate { 188 | var transitionSuperview: UIView { 189 | return self.view 190 | } 191 | 192 | func transitionPresentFromView(_ base: BaseTransition) -> UIView? { 193 | return self.imageView 194 | } 195 | 196 | func transitionPresentFromImage(_ base: BaseTransition) -> UIImage? { 197 | return self.imageView.image 198 | } 199 | 200 | func transitionDismissToView(_ base: BaseTransition) -> UIView? { 201 | return self.imageView 202 | } 203 | 204 | func transitionWillPresent(_ base: BaseTransition, viewController: UIViewController) { 205 | print("transitionWillPresent") 206 | } 207 | 208 | func transitionDidPresent(_ base: BaseTransition, viewController: UIViewController) { 209 | print("transitionDidPresent") 210 | } 211 | 212 | func transitionWillDismiss(_ base: BaseTransition, viewController: UIViewController) { 213 | print("transitionWillDismiss") 214 | } 215 | 216 | func transitionDidDismiss(_ base: BaseTransition, viewController: UIViewController) { 217 | print("transitionDidDismiss") 218 | } 219 | 220 | func transitionGesture(_ base: BaseTransition, viewController: UIViewController, gesture: UIPanGestureRecognizer, progress: CGFloat) { 221 | switch gesture.state { 222 | case .began: 223 | base.transitionView.backgroundColor = .black 224 | case .changed: 225 | base.transitionView.backgroundColor = UIColor.black.withAlphaComponent(progress / 3) 226 | default: 227 | break 228 | } 229 | } 230 | } 231 | ``` 232 | 233 | ## More Example 234 | 235 | 236 | ## Author 237 | 238 | pikachu987, pikachu77769@gmail.com 239 | 240 | ## License 241 | 242 | Copyright (c) 2019 pikachu987 243 | 244 | Permission is hereby granted, free of charge, to any person obtaining a copy 245 | of this software and associated documentation files (the "Software"), to deal 246 | in the Software without restriction, including without limitation the rights 247 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 248 | copies of the Software, and to permit persons to whom the Software is 249 | furnished to do so, subject to the following conditions: 250 | 251 | The above copyright notice and this permission notice shall be included in 252 | all copies or substantial portions of the Software. 253 | 254 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 255 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 256 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 257 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 258 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 259 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 260 | THE SOFTWARE. 261 | -------------------------------------------------------------------------------- /TransitionController.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint TransitionController.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'TransitionController' 11 | s.version = '0.1.4' 12 | s.summary = 'Present transition and dismiss transition of UIViewController with simple code' 13 | 14 | # This description is used to generate tags and improve search results. 15 | # * Think: What does it do? Why did you write it? What is the focus? 16 | # * Try to keep it short, snappy and to the point. 17 | # * Write the description between the DESC delimiters below. 18 | # * Finally, don't worry about the indent, CocoaPods strips it! 19 | 20 | s.description = <<-DESC 21 | You can dismiss transition and present transition between UIViewController, UINavigationController, UITabBarController, UICollectionViewController, and UITableViewController. 22 | Receives a delegate for the willPresent, didPresent, willDismiss and didDismiss of the ViewController. 23 | DESC 24 | 25 | s.homepage = 'https://github.com/pikachu987/TransitionController' 26 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 27 | s.license = { :type => 'MIT', :file => 'LICENSE' } 28 | s.author = { 'pikachu987' => 'pikachu77769@gmail.com' } 29 | s.source = { :git => 'https://github.com/pikachu987/TransitionController.git', :tag => s.version.to_s } 30 | # s.social_media_url = 'https://twitter.com/' 31 | 32 | s.ios.deployment_target = '9.0' 33 | 34 | s.source_files = 'TransitionController/Classes/**/*' 35 | s.swift_version = '5.0' 36 | 37 | # s.resource_bundles = { 38 | # 'TransitionController' => ['TransitionController/Assets/*.png'] 39 | # } 40 | 41 | # s.public_header_files = 'Pod/Classes/**/*.h' 42 | # s.frameworks = 'UIKit', 'MapKit' 43 | # s.dependency 'AFNetworking', '~> 2.3' 44 | end 45 | -------------------------------------------------------------------------------- /TransitionController/Assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/TransitionController/Assets/.gitkeep -------------------------------------------------------------------------------- /TransitionController/Classes/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/TransitionController/Classes/.gitkeep -------------------------------------------------------------------------------- /TransitionController/Classes/BaseTransition.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | public protocol BaseTransition: class { 24 | var key: Any? { set get } 25 | 26 | var containerView: UIView? { get } 27 | 28 | var superview: UIView? { get } 29 | 30 | var presentDuration: TimeInterval { get } 31 | var presentFromView: UIView? { get } 32 | var presentFromImage: UIImage? { get } 33 | var presentToView: UIView? { get } 34 | 35 | var dismissDuration: TimeInterval { get } 36 | var dismissFromView: UIView? { get } 37 | var dismissFromImage: UIImage? { get } 38 | var dismissToView: UIView? { get } 39 | 40 | var transitionView: UIView { get } 41 | 42 | func dismiss() 43 | 44 | func transitionGesture(_ gesture: UIPanGestureRecognizer, progress: CGFloat) 45 | 46 | func transitionWillPresent() 47 | func transitionDidPresent() 48 | func transitionWillDismiss() 49 | func transitionDidDismiss() 50 | 51 | func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool 52 | } 53 | -------------------------------------------------------------------------------- /TransitionController/Classes/Controller/AnimatedTransition.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | protocol AnimatedTransitionDelegate: class { 24 | var baseTransition: BaseTransition? { get } 25 | } 26 | 27 | public class AnimatedTransition: NSObject, UIViewControllerAnimatedTransitioning { 28 | weak var delegate: AnimatedTransitionDelegate? 29 | 30 | var mode: Mode = .present 31 | public weak var containerView: UIView? 32 | public var contextView: UIView? 33 | public var imageView: UIImageView? 34 | 35 | public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 36 | if self.mode == .present { 37 | return self.delegate?.baseTransition?.presentDuration ?? 0.35 38 | } else { 39 | return self.delegate?.baseTransition?.dismissDuration ?? 0.35 40 | } 41 | } 42 | 43 | public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 44 | guard let superview = self.delegate?.baseTransition?.superview else { return } 45 | guard let viewController = transitionContext.viewController(forKey: self.mode == .present ? .to : .from) else { return } 46 | 47 | viewController.view.layoutIfNeeded() 48 | let containerView = transitionContext.containerView 49 | self.containerView = containerView 50 | 51 | if self.contextView == nil { 52 | let contextView = UIView() 53 | contextView.translatesAutoresizingMaskIntoConstraints = false 54 | contextView.alpha = 0 55 | contextView.backgroundColor = self.delegate?.baseTransition?.transitionView.backgroundColor 56 | containerView.addSubview(contextView) 57 | containerView.addConstraints( 58 | NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": contextView]) 59 | ) 60 | containerView.addConstraints( 61 | NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[view]-0-|", options: [], metrics: nil, views: ["view": contextView]) 62 | ) 63 | self.contextView = contextView 64 | 65 | let imageView = UIImageView() 66 | imageView.clipsToBounds = true 67 | containerView.addSubview(imageView) 68 | self.imageView = imageView 69 | } 70 | 71 | if self.mode == .present { 72 | let presentDuration = self.delegate?.baseTransition?.presentDuration ?? 0.35 73 | self.delegate?.baseTransition?.transitionWillPresent() 74 | 75 | self.imageView?.image = (self.delegate?.baseTransition?.presentFromImage ?? self.delegate?.baseTransition?.presentToView?.imageWithView) 76 | if let fromView = self.delegate?.baseTransition?.presentFromView { 77 | self.imageView?.layer.cornerRadius = fromView.layer.cornerRadius 78 | self.imageView?.frame = fromView.convert(fromView.bounds, to: superview) 79 | self.imageView?.contentMode = fromView.contentMode 80 | } 81 | UIView.animate(withDuration: presentDuration, animations: { 82 | self.contextView?.alpha = 1 83 | if let toView = self.delegate?.baseTransition?.presentToView { 84 | self.imageView?.frame = toView.frame 85 | self.imageView?.layer.cornerRadius = toView.layer.cornerRadius 86 | } 87 | }, completion: { _ in 88 | self.imageView?.backgroundColor = nil 89 | self.imageView?.image = nil 90 | containerView.addSubview(viewController.view) 91 | transitionContext.completeTransition(true) 92 | self.delegate?.baseTransition?.transitionDidPresent() 93 | }) 94 | 95 | } else if self.mode == .dismiss { 96 | let dismissDuration = self.delegate?.baseTransition?.dismissDuration ?? 0.35 97 | viewController.view.removeFromSuperview() 98 | self.delegate?.baseTransition?.transitionWillDismiss() 99 | 100 | self.imageView?.image = self.delegate?.baseTransition?.dismissFromImage 101 | if let fromView = self.delegate?.baseTransition?.dismissFromView { 102 | self.imageView?.frame = fromView.convert(fromView.bounds, to: containerView) 103 | self.imageView?.layer.cornerRadius = fromView.layer.cornerRadius 104 | } 105 | 106 | UIView.animate(withDuration: dismissDuration, animations: { 107 | self.contextView?.alpha = 0 108 | if let toView = self.delegate?.baseTransition?.dismissToView { 109 | self.imageView?.frame = toView.convert(toView.bounds, to: superview) 110 | self.imageView?.layer.cornerRadius = toView.layer.cornerRadius 111 | self.imageView?.contentMode = toView.contentMode 112 | } 113 | }, completion: { _ in 114 | self.imageView?.image = nil 115 | transitionContext.completeTransition(true) 116 | self.delegate?.baseTransition?.transitionDidDismiss() 117 | }) 118 | } 119 | } 120 | } 121 | 122 | // MARK: AnimatedTransition + Mode 123 | extension AnimatedTransition { 124 | enum Mode { 125 | case present 126 | case dismiss 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /TransitionController/Classes/Controller/CommonTransition.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | public class CommonTransition: NSObject, AnimatedTransitionDelegate { 24 | weak var _baseTransition: BaseTransition? 25 | 26 | var baseTransition: BaseTransition? { 27 | return self._baseTransition 28 | } 29 | 30 | public let animatedTransition = AnimatedTransition() 31 | private var centerPoint = CGPoint.zero 32 | 33 | var containerView: UIView? { 34 | return self.animatedTransition.containerView 35 | } 36 | 37 | var presentAnimatedTransition: AnimatedTransition { 38 | self.animatedTransition.mode = .present 39 | return self.animatedTransition 40 | } 41 | 42 | var dismissAnimatedTransition: AnimatedTransition { 43 | self.animatedTransition.mode = .dismiss 44 | return self.animatedTransition 45 | } 46 | 47 | init(baseTransition: BaseTransition) { 48 | self._baseTransition = baseTransition 49 | super.init() 50 | self.animatedTransition.delegate = self 51 | } 52 | 53 | func panGesture(_ gesture: UIPanGestureRecognizer) { 54 | guard let baseTransition = self.baseTransition else { return } 55 | let view = baseTransition.transitionView 56 | 57 | var gestureProgress: CGFloat { 58 | let origin = self.centerPoint 59 | let changeX = abs(view.center.x - origin.x) 60 | let changeY = abs(view.center.y - origin.y) 61 | let progressX = changeX / view.bounds.width 62 | let progressY = changeY / view.bounds.height 63 | return max(progressX, progressY) 64 | } 65 | 66 | self.baseTransition?.transitionGesture(gesture, progress: gesture.state == .began ? 0 : gestureProgress) 67 | switch gesture.state { 68 | case .began: 69 | self.centerPoint = view.center 70 | case .changed: 71 | let origin = view.center 72 | let change = gesture.translation(in: view) 73 | self.baseTransition?.transitionView.center = CGPoint(x: origin.x + change.x, y: origin.y + change.y) 74 | let alpha = 1 - gestureProgress 75 | self.animatedTransition.contextView?.alpha = alpha 76 | gesture.setTranslation(CGPoint.zero, in: nil) 77 | case .ended: 78 | let velocity = gesture.velocity(in: view) 79 | if gestureProgress > 0.25 || sqrt(velocity.x*velocity.x + velocity.y*velocity.y) > 1000 { 80 | self.baseTransition?.dismiss() 81 | } else { 82 | fallthrough 83 | } 84 | default: 85 | UIView.animate(withDuration: 0.3, animations: { 86 | self.baseTransition?.transitionView.center = self.centerPoint 87 | }, completion: { _ in 88 | self.centerPoint = .zero 89 | self.animatedTransition.contextView?.alpha = 1 90 | }) 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /TransitionController/Classes/Controller/TransitionCollectionViewController.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | open class TransitionCollectionViewController: UIViewController, BaseTransition { 24 | public weak var transitionDelegate: TransitionDelegate? { 25 | didSet { 26 | self.transitioningDelegate = self 27 | self.modalPresentationStyle = .custom 28 | } 29 | } 30 | 31 | open var key: Any? 32 | 33 | public var containerView: UIView? { 34 | return self.commonTransition.containerView 35 | } 36 | 37 | public var superview: UIView? { 38 | return self.transitionDelegate?.transitionSuperview 39 | } 40 | 41 | 42 | open var presentDuration: TimeInterval { 43 | return 0.35 44 | } 45 | 46 | public var presentFromView: UIView? { 47 | guard let view = self.transitionDelegate?.transitionPresentFromView(self) else { 48 | let view = UIView() 49 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 50 | return view 51 | } 52 | return view 53 | } 54 | 55 | public var presentFromImage: UIImage? { 56 | return self.transitionDelegate?.transitionPresentFromImage(self) 57 | } 58 | 59 | open var presentToView: UIView? { 60 | return self.view 61 | } 62 | 63 | 64 | open var dismissDuration: TimeInterval { 65 | return 0.35 66 | } 67 | 68 | open var dismissFromView: UIView? { 69 | return self.view 70 | } 71 | 72 | open var dismissFromImage: UIImage? { 73 | return self.view.imageWithView 74 | } 75 | 76 | public var dismissToView: UIView? { 77 | guard let view = self.transitionDelegate?.transitionDismissToView(self) else { 78 | let view = UIView() 79 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 80 | return view 81 | } 82 | return view 83 | } 84 | 85 | open var transitionView: UIView { 86 | return self.view 87 | } 88 | 89 | public lazy var commonTransition: CommonTransition = { 90 | let commonTransition = CommonTransition(baseTransition: self) 91 | return commonTransition 92 | }() 93 | 94 | public var animatedTransition: AnimatedTransition { 95 | return self.commonTransition.animatedTransition 96 | } 97 | 98 | override open func viewDidLoad() { 99 | super.viewDidLoad() 100 | 101 | let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) 102 | panGestureRecognizer.delegate = self 103 | self.transitionView.addGestureRecognizer(panGestureRecognizer) 104 | } 105 | 106 | public func dismiss() { 107 | self.dismiss(animated: true, completion: nil) 108 | } 109 | 110 | open func transitionGesture(_ gesture: UIPanGestureRecognizer, progress: CGFloat) { 111 | self.transitionDelegate?.transitionGesture(self, viewController: self, gesture: gesture, progress: progress) 112 | } 113 | 114 | open func transitionWillPresent() { 115 | self.transitionDelegate?.transitionWillPresent(self, viewController: self) 116 | } 117 | 118 | open func transitionDidPresent() { 119 | self.transitionDelegate?.transitionDidPresent(self, viewController: self) 120 | } 121 | 122 | open func transitionWillDismiss() { 123 | self.transitionDelegate?.transitionWillDismiss(self, viewController: self) 124 | } 125 | 126 | open func transitionDidDismiss() { 127 | self.transitionDelegate?.transitionDidDismiss(self, viewController: self) 128 | } 129 | 130 | open func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 131 | return true 132 | } 133 | 134 | @objc private func panGesture(_ gesture: UIPanGestureRecognizer) { 135 | self.commonTransition.panGesture(gesture) 136 | } 137 | } 138 | 139 | // MARK: UIGestureRecognizerDelegate 140 | extension TransitionCollectionViewController: UIGestureRecognizerDelegate { 141 | public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 142 | return self.transitionRecognizerShouldBegin(gestureRecognizer) 143 | } 144 | } 145 | 146 | // MARK: UIViewControllerTransitioningDelegate 147 | extension TransitionCollectionViewController: UIViewControllerTransitioningDelegate { 148 | public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 149 | return self.commonTransition.presentAnimatedTransition 150 | } 151 | 152 | public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 153 | return self.commonTransition.dismissAnimatedTransition 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /TransitionController/Classes/Controller/TransitionNavigationController.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | open class TransitionNavigationController: UINavigationController, BaseTransition { 24 | public weak var transitionDelegate: TransitionDelegate? { 25 | didSet { 26 | self.transitioningDelegate = self 27 | self.modalPresentationStyle = .custom 28 | } 29 | } 30 | 31 | open var key: Any? 32 | 33 | public var containerView: UIView? { 34 | return self.commonTransition.containerView 35 | } 36 | 37 | public var superview: UIView? { 38 | return self.transitionDelegate?.transitionSuperview 39 | } 40 | 41 | 42 | public var navigationBarColor: UIColor? { 43 | didSet { 44 | if self.navigationBarColor == nil { 45 | self.navigationBar.setBackgroundImage(nil, for: .default) 46 | self.navigationBar.shadowImage = nil 47 | } else { 48 | self.navigationBar.setBackgroundImage(UIImage(), for: .default) 49 | self.navigationBar.shadowImage = UIImage() 50 | self.navigationBar.backgroundColor = self.navigationBarColor 51 | } 52 | } 53 | } 54 | 55 | open var presentDuration: TimeInterval { 56 | return 0.35 57 | } 58 | 59 | public var presentFromView: UIView? { 60 | guard let view = self.transitionDelegate?.transitionPresentFromView(self) else { 61 | let view = UIView() 62 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 63 | return view 64 | } 65 | return view 66 | } 67 | 68 | public var presentFromImage: UIImage? { 69 | return self.transitionDelegate?.transitionPresentFromImage(self) 70 | } 71 | 72 | open var presentToView: UIView? { 73 | return self.view 74 | } 75 | 76 | 77 | open var dismissDuration: TimeInterval { 78 | return 0.35 79 | } 80 | 81 | open var dismissFromView: UIView? { 82 | return self.view 83 | } 84 | 85 | open var dismissFromImage: UIImage? { 86 | return self.view.imageWithView 87 | } 88 | 89 | public var dismissToView: UIView? { 90 | guard let view = self.transitionDelegate?.transitionDismissToView(self) else { 91 | let view = UIView() 92 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 93 | return view 94 | } 95 | return view 96 | } 97 | 98 | open var transitionView: UIView { 99 | return self.view 100 | } 101 | 102 | public lazy var commonTransition: CommonTransition = { 103 | let commonTransition = CommonTransition(baseTransition: self) 104 | return commonTransition 105 | }() 106 | 107 | public var animatedTransition: AnimatedTransition { 108 | return self.commonTransition.animatedTransition 109 | } 110 | 111 | override open func loadView() { 112 | super.loadView() 113 | 114 | self.interactivePopGestureRecognizer?.delegate = self 115 | self.interactivePopGestureRecognizer?.isEnabled = true 116 | } 117 | 118 | override open func viewDidLoad() { 119 | super.viewDidLoad() 120 | 121 | let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) 122 | panGestureRecognizer.delegate = self 123 | self.transitionView.addGestureRecognizer(panGestureRecognizer) 124 | } 125 | 126 | public func dismiss() { 127 | self.dismiss(animated: true, completion: nil) 128 | } 129 | 130 | open func transitionGesture(_ gesture: UIPanGestureRecognizer, progress: CGFloat) { 131 | self.transitionDelegate?.transitionGesture(self, viewController: self, gesture: gesture, progress: progress) 132 | } 133 | 134 | open func transitionWillPresent() { 135 | self.transitionDelegate?.transitionWillPresent(self, viewController: self) 136 | } 137 | 138 | open func transitionDidPresent() { 139 | self.transitionDelegate?.transitionDidPresent(self, viewController: self) 140 | } 141 | 142 | open func transitionWillDismiss() { 143 | self.transitionDelegate?.transitionWillDismiss(self, viewController: self) 144 | } 145 | 146 | open func transitionDidDismiss() { 147 | self.transitionDelegate?.transitionDidDismiss(self, viewController: self) 148 | } 149 | 150 | open func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 151 | return true 152 | } 153 | 154 | @objc private func panGesture(_ gesture: UIPanGestureRecognizer) { 155 | self.commonTransition.panGesture(gesture) 156 | } 157 | } 158 | 159 | // MARK: UIGestureRecognizerDelegate 160 | extension TransitionNavigationController: UIGestureRecognizerDelegate { 161 | public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 162 | return self.transitionRecognizerShouldBegin(gestureRecognizer) 163 | } 164 | } 165 | 166 | // MARK: UIViewControllerTransitioningDelegate 167 | extension TransitionNavigationController: UIViewControllerTransitioningDelegate { 168 | public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 169 | return self.commonTransition.presentAnimatedTransition 170 | } 171 | 172 | public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 173 | return self.commonTransition.dismissAnimatedTransition 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /TransitionController/Classes/Controller/TransitionTabBarController.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | open class TransitionTabBarController: UITabBarController, BaseTransition { 24 | public weak var transitionDelegate: TransitionDelegate? { 25 | didSet { 26 | self.transitioningDelegate = self 27 | self.modalPresentationStyle = .custom 28 | } 29 | } 30 | 31 | open var key: Any? 32 | 33 | public var containerView: UIView? { 34 | return self.commonTransition.containerView 35 | } 36 | 37 | public var superview: UIView? { 38 | return self.transitionDelegate?.transitionSuperview 39 | } 40 | 41 | 42 | public var isTabBarHiddenColor: Bool = false { 43 | didSet { 44 | if self.isTabBarHiddenColor { 45 | self.tabBar.shadowImage = UIImage() 46 | self.tabBar.backgroundColor = .clear 47 | } else { 48 | self.tabBar.shadowImage = nil 49 | } 50 | } 51 | } 52 | 53 | open var presentDuration: TimeInterval { 54 | return 0.35 55 | } 56 | 57 | public var presentFromView: UIView? { 58 | guard let view = self.transitionDelegate?.transitionPresentFromView(self) else { 59 | let view = UIView() 60 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 61 | return view 62 | } 63 | return view 64 | } 65 | 66 | public var presentFromImage: UIImage? { 67 | return self.transitionDelegate?.transitionPresentFromImage(self) 68 | } 69 | 70 | open var presentToView: UIView? { 71 | return self.view 72 | } 73 | 74 | 75 | open var dismissDuration: TimeInterval { 76 | return 0.35 77 | } 78 | 79 | open var dismissFromView: UIView? { 80 | return self.view 81 | } 82 | 83 | open var dismissFromImage: UIImage? { 84 | return self.view.imageWithView 85 | } 86 | 87 | public var dismissToView: UIView? { 88 | guard let view = self.transitionDelegate?.transitionDismissToView(self) else { 89 | let view = UIView() 90 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 91 | return view 92 | } 93 | return view 94 | } 95 | 96 | open var transitionView: UIView { 97 | return self.view 98 | } 99 | 100 | public lazy var commonTransition: CommonTransition = { 101 | let commonTransition = CommonTransition(baseTransition: self) 102 | return commonTransition 103 | }() 104 | 105 | public var animatedTransition: AnimatedTransition { 106 | return self.commonTransition.animatedTransition 107 | } 108 | 109 | override open func viewDidLoad() { 110 | super.viewDidLoad() 111 | 112 | let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) 113 | panGestureRecognizer.delegate = self 114 | self.transitionView.addGestureRecognizer(panGestureRecognizer) 115 | } 116 | 117 | public func dismiss() { 118 | self.dismiss(animated: true, completion: nil) 119 | } 120 | 121 | open func transitionGesture(_ gesture: UIPanGestureRecognizer, progress: CGFloat) { 122 | self.transitionDelegate?.transitionGesture(self, viewController: self, gesture: gesture, progress: progress) 123 | } 124 | 125 | open func transitionWillPresent() { 126 | self.transitionDelegate?.transitionWillPresent(self, viewController: self) 127 | } 128 | 129 | open func transitionDidPresent() { 130 | self.transitionDelegate?.transitionDidPresent(self, viewController: self) 131 | } 132 | 133 | open func transitionWillDismiss() { 134 | self.transitionDelegate?.transitionWillDismiss(self, viewController: self) 135 | } 136 | 137 | open func transitionDidDismiss() { 138 | self.transitionDelegate?.transitionDidDismiss(self, viewController: self) 139 | } 140 | 141 | open func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 142 | return true 143 | } 144 | 145 | @objc private func panGesture(_ gesture: UIPanGestureRecognizer) { 146 | self.commonTransition.panGesture(gesture) 147 | } 148 | } 149 | 150 | // MARK: UIGestureRecognizerDelegate 151 | extension TransitionTabBarController: UIGestureRecognizerDelegate { 152 | public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 153 | return self.transitionRecognizerShouldBegin(gestureRecognizer) 154 | } 155 | } 156 | 157 | // MARK: UIViewControllerTransitioningDelegate 158 | extension TransitionTabBarController: UIViewControllerTransitioningDelegate { 159 | public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 160 | return self.commonTransition.presentAnimatedTransition 161 | } 162 | 163 | public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 164 | return self.commonTransition.dismissAnimatedTransition 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /TransitionController/Classes/Controller/TransitionTableViewController.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | open class TransitionTableViewController: UIViewController, BaseTransition { 24 | public weak var transitionDelegate: TransitionDelegate? { 25 | didSet { 26 | self.transitioningDelegate = self 27 | self.modalPresentationStyle = .custom 28 | } 29 | } 30 | 31 | open var key: Any? 32 | 33 | public var containerView: UIView? { 34 | return self.commonTransition.containerView 35 | } 36 | 37 | public var superview: UIView? { 38 | return self.transitionDelegate?.transitionSuperview 39 | } 40 | 41 | 42 | open var presentDuration: TimeInterval { 43 | return 0.35 44 | } 45 | 46 | public var presentFromView: UIView? { 47 | guard let view = self.transitionDelegate?.transitionPresentFromView(self) else { 48 | let view = UIView() 49 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 50 | return view 51 | } 52 | return view 53 | } 54 | 55 | public var presentFromImage: UIImage? { 56 | return self.transitionDelegate?.transitionPresentFromImage(self) 57 | } 58 | 59 | open var presentToView: UIView? { 60 | return self.view 61 | } 62 | 63 | 64 | open var dismissDuration: TimeInterval { 65 | return 0.35 66 | } 67 | 68 | open var dismissFromView: UIView? { 69 | return self.view 70 | } 71 | 72 | open var dismissFromImage: UIImage? { 73 | return self.view.imageWithView 74 | } 75 | 76 | public var dismissToView: UIView? { 77 | guard let view = self.transitionDelegate?.transitionDismissToView(self) else { 78 | let view = UIView() 79 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 80 | return view 81 | } 82 | return view 83 | } 84 | 85 | open var transitionView: UIView { 86 | return self.view 87 | } 88 | 89 | public lazy var commonTransition: CommonTransition = { 90 | let commonTransition = CommonTransition(baseTransition: self) 91 | return commonTransition 92 | }() 93 | 94 | public var animatedTransition: AnimatedTransition { 95 | return self.commonTransition.animatedTransition 96 | } 97 | 98 | override open func viewDidLoad() { 99 | super.viewDidLoad() 100 | 101 | let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) 102 | panGestureRecognizer.delegate = self 103 | self.transitionView.addGestureRecognizer(panGestureRecognizer) 104 | } 105 | 106 | public func dismiss() { 107 | self.dismiss(animated: true, completion: nil) 108 | } 109 | 110 | open func transitionGesture(_ gesture: UIPanGestureRecognizer, progress: CGFloat) { 111 | self.transitionDelegate?.transitionGesture(self, viewController: self, gesture: gesture, progress: progress) 112 | } 113 | 114 | open func transitionWillPresent() { 115 | self.transitionDelegate?.transitionWillPresent(self, viewController: self) 116 | } 117 | 118 | open func transitionDidPresent() { 119 | self.transitionDelegate?.transitionDidPresent(self, viewController: self) 120 | } 121 | 122 | open func transitionWillDismiss() { 123 | self.transitionDelegate?.transitionWillDismiss(self, viewController: self) 124 | } 125 | 126 | open func transitionDidDismiss() { 127 | self.transitionDelegate?.transitionDidDismiss(self, viewController: self) 128 | } 129 | 130 | open func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 131 | return true 132 | } 133 | 134 | @objc private func panGesture(_ gesture: UIPanGestureRecognizer) { 135 | self.commonTransition.panGesture(gesture) 136 | } 137 | } 138 | 139 | // MARK: UIGestureRecognizerDelegate 140 | extension TransitionTableViewController: UIGestureRecognizerDelegate { 141 | public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 142 | return self.transitionRecognizerShouldBegin(gestureRecognizer) 143 | } 144 | } 145 | 146 | // MARK: UIViewControllerTransitioningDelegate 147 | extension TransitionTableViewController: UIViewControllerTransitioningDelegate { 148 | public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 149 | return self.commonTransition.presentAnimatedTransition 150 | } 151 | 152 | public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 153 | return self.commonTransition.dismissAnimatedTransition 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /TransitionController/Classes/Controller/TransitionViewController.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | open class TransitionViewController: UIViewController, BaseTransition { 24 | public weak var transitionDelegate: TransitionDelegate? { 25 | didSet { 26 | self.transitioningDelegate = self 27 | self.modalPresentationStyle = .custom 28 | } 29 | } 30 | 31 | open var key: Any? 32 | 33 | public var containerView: UIView? { 34 | return self.commonTransition.containerView 35 | } 36 | 37 | public var superview: UIView? { 38 | return self.transitionDelegate?.transitionSuperview 39 | } 40 | 41 | 42 | open var presentDuration: TimeInterval { 43 | return 0.35 44 | } 45 | 46 | public var presentFromView: UIView? { 47 | guard let view = self.transitionDelegate?.transitionPresentFromView(self) else { 48 | let view = UIView() 49 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 50 | return view 51 | } 52 | return view 53 | } 54 | 55 | public var presentFromImage: UIImage? { 56 | return self.transitionDelegate?.transitionPresentFromImage(self) 57 | } 58 | 59 | open var presentToView: UIView? { 60 | return self.view 61 | } 62 | 63 | 64 | open var dismissDuration: TimeInterval { 65 | return 0.35 66 | } 67 | 68 | open var dismissFromView: UIView? { 69 | return self.view 70 | } 71 | 72 | open var dismissFromImage: UIImage? { 73 | return self.view.imageWithView 74 | } 75 | 76 | public var dismissToView: UIView? { 77 | guard let view = self.transitionDelegate?.transitionDismissToView(self) else { 78 | let view = UIView() 79 | view.frame = CGRect(x: UIScreen.main.bounds.width/2, y: UIScreen.main.bounds.height/2, width: 1, height: 1) 80 | return view 81 | } 82 | return view 83 | } 84 | 85 | public var transitionView: UIView { 86 | return self.view 87 | } 88 | 89 | public lazy var commonTransition: CommonTransition = { 90 | let commonTransition = CommonTransition(baseTransition: self) 91 | return commonTransition 92 | }() 93 | 94 | public var animatedTransition: AnimatedTransition { 95 | return self.commonTransition.animatedTransition 96 | } 97 | 98 | override open func viewDidLoad() { 99 | super.viewDidLoad() 100 | 101 | let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.panGesture(_:))) 102 | panGestureRecognizer.delegate = self 103 | self.transitionView.addGestureRecognizer(panGestureRecognizer) 104 | } 105 | 106 | public func dismiss() { 107 | self.dismiss(animated: true, completion: nil) 108 | } 109 | 110 | open func transitionGesture(_ gesture: UIPanGestureRecognizer, progress: CGFloat) { 111 | self.transitionDelegate?.transitionGesture(self, viewController: self, gesture: gesture, progress: progress) 112 | } 113 | 114 | open func transitionWillPresent() { 115 | self.transitionDelegate?.transitionWillPresent(self, viewController: self) 116 | } 117 | 118 | open func transitionDidPresent() { 119 | self.transitionDelegate?.transitionDidPresent(self, viewController: self) 120 | } 121 | 122 | open func transitionWillDismiss() { 123 | self.transitionDelegate?.transitionWillDismiss(self, viewController: self) 124 | } 125 | 126 | open func transitionDidDismiss() { 127 | self.transitionDelegate?.transitionDidDismiss(self, viewController: self) 128 | } 129 | 130 | open func transitionRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 131 | return true 132 | } 133 | 134 | @objc private func panGesture(_ gesture: UIPanGestureRecognizer) { 135 | self.commonTransition.panGesture(gesture) 136 | } 137 | } 138 | 139 | // MARK: UIGestureRecognizerDelegate 140 | extension TransitionViewController: UIGestureRecognizerDelegate { 141 | public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 142 | return self.transitionRecognizerShouldBegin(gestureRecognizer) 143 | } 144 | } 145 | 146 | // MARK: UIViewControllerTransitioningDelegate 147 | extension TransitionViewController: UIViewControllerTransitioningDelegate { 148 | public func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning? { 149 | return self.commonTransition.presentAnimatedTransition 150 | } 151 | 152 | public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { 153 | return self.commonTransition.dismissAnimatedTransition 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /TransitionController/Classes/Extensions/UIView+imageWithView.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | extension UIView { 24 | var imageWithView: UIImage? { 25 | if #available(iOS 10.0, *) { 26 | let renderer = UIGraphicsImageRenderer(bounds: self.bounds) 27 | return renderer.image { rendererContext in 28 | self.layer.render(in: rendererContext.cgContext) 29 | } 30 | } else { 31 | UIGraphicsBeginImageContext(self.frame.size) 32 | if let context = UIGraphicsGetCurrentContext() { 33 | self.layer.render(in: context) 34 | if let image = UIGraphicsGetImageFromCurrentImageContext() { 35 | return image 36 | } 37 | } 38 | UIGraphicsEndImageContext() 39 | return nil 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TransitionController/Classes/TransitionDelegate.swift: -------------------------------------------------------------------------------- 1 | //Copyright (c) 2019 pikachu987 2 | // 3 | //Permission is hereby granted, free of charge, to any person obtaining a copy 4 | //of this software and associated documentation files (the "Software"), to deal 5 | //in the Software without restriction, including without limitation the rights 6 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | //copies of the Software, and to permit persons to whom the Software is 8 | //furnished to do so, subject to the following conditions: 9 | // 10 | //The above copyright notice and this permission notice shall be included in 11 | //all copies or substantial portions of the Software. 12 | // 13 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | //THE SOFTWARE. 20 | 21 | import UIKit 22 | 23 | public protocol TransitionDelegate: class { 24 | var transitionSuperview: UIView { get } 25 | 26 | func transitionPresentFromView(_ base: BaseTransition) -> UIView? 27 | func transitionPresentFromImage(_ base: BaseTransition) -> UIImage? 28 | 29 | func transitionDismissToView(_ base: BaseTransition) -> UIView? 30 | 31 | func transitionGesture(_ base: BaseTransition, viewController: UIViewController, gesture: UIPanGestureRecognizer, progress: CGFloat) 32 | 33 | func transitionWillPresent(_ base: BaseTransition, viewController: UIViewController) 34 | func transitionDidPresent(_ base: BaseTransition, viewController: UIViewController) 35 | func transitionWillDismiss(_ base: BaseTransition, viewController: UIViewController) 36 | func transitionDidDismiss(_ base: BaseTransition, viewController: UIViewController) 37 | } 38 | 39 | public extension TransitionDelegate { 40 | func transitionPresentFromView(_ base: BaseTransition) -> UIView? { 41 | return nil 42 | } 43 | 44 | func transitionPresentFromImage(_ base: BaseTransition) -> UIImage? { 45 | return nil 46 | } 47 | 48 | func transitionDismissToView(_ base: BaseTransition) -> UIView? { 49 | return nil 50 | } 51 | 52 | func transitionGesture(_ base: BaseTransition, viewController: UIViewController, gesture: UIPanGestureRecognizer, progress: CGFloat) { 53 | 54 | } 55 | 56 | func transitionWillPresent(_ base: BaseTransition, viewController: UIViewController) { 57 | 58 | } 59 | 60 | func transitionDidPresent(_ base: BaseTransition, viewController: UIViewController) { 61 | 62 | } 63 | 64 | func transitionWillDismiss(_ base: BaseTransition, viewController: UIViewController) { 65 | 66 | } 67 | 68 | func transitionDidDismiss(_ base: BaseTransition, viewController: UIViewController) { 69 | 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /_Pods.xcodeproj: -------------------------------------------------------------------------------- 1 | Example/Pods/Pods.xcodeproj -------------------------------------------------------------------------------- /img/single.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/img/single.gif -------------------------------------------------------------------------------- /img/single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/img/single.png -------------------------------------------------------------------------------- /img/slide.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/img/slide.gif -------------------------------------------------------------------------------- /img/slide.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pikachu987/TransitionController/3cf278ff8f298601527df506ee18a9c2f375c375/img/slide.png --------------------------------------------------------------------------------