├── .gitignore ├── .swift-version ├── .travis.yml ├── LICENSE ├── README.md ├── READMEImages ├── IdentifyInspector.png ├── SlippingNaviController.gif └── UINavigationController.gif ├── SlippingNaviController.podspec ├── SlippingNaviController.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── SlippingNaviController.xcscheme └── xcuserdata │ └── Dev.MJ.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── SlippingNaviController ├── Info.plist ├── SlippingNaviController.h ├── SlippingNaviController.swift └── SlippingPopTransition.swift /.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 | *.xcuserstate 25 | 26 | ## Obj-C/Swift specific 27 | *.hmap 28 | *.ipa 29 | *.dSYM.zip 30 | *.dSYM 31 | 32 | ## Playgrounds 33 | timeline.xctimeline 34 | playground.xcworkspace 35 | 36 | # Swift Package Manager 37 | # 38 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 39 | # Packages/ 40 | # Package.pins 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 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8.3 3 | sudo: false 4 | 5 | #before_install 6 | 7 | #install: 8 | 9 | #before_script: 10 | 11 | script: 12 | - xcodebuild clean build -project SlippingNaviController.xcodeproj -scheme SlippingNaviController -destination "platform=iOS Simulator,OS=10.3,name=iPhone 7" 13 | 14 | 15 | #after_script: 16 | 17 | #after_install 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Dev.MJ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SlippingNaviController 2 | 3 | ![Swift](https://img.shields.io/badge/Swift-3.0-orange.svg) ![CocoaPods](https://img.shields.io/cocoapods/v/SlippingNaviController.svg) ![platform](https://img.shields.io/badge/platform-iOS-blue.svg) ![License](https://img.shields.io/badge/license-MIT-brightgreen.svg) [![TravisCI](https://api.travis-ci.org/Dev-MJ/SlippingNaviController.svg)](https://github.com/Dev-MJ/SlippingNaviController.git) 4 | 5 | # About 6 | 7 | This makes it easier to implement backward gestures in UINavigationController, such as **Instagrams** and **Facebook**. 8 | 9 | ### UINavigationController 10 | 11 | ![gifImage](READMEImages/UINavigationController.gif) 12 | 13 | 14 | 15 | ### SlippingNavigationController 16 | 17 | ![gifImage](READMEImages/SlippingNaviController.gif) 18 | 19 | # Requirements 20 | 21 | * iOS 9.0 + 22 | * Xcode 8.0 + 23 | 24 | # Installation 25 | 26 | **CocoaPods** 27 | 28 | ```ruby 29 | $ gem install cocoapods 30 | ``` 31 | 32 | ```ruby 33 | use_frameworks! 34 | platform :ios, '9.0' 35 | pod 'SlippingNaviController' 36 | ``` 37 | 38 | ```ruby 39 | pod install 40 | ``` 41 | 42 | 43 | 44 | **Carthage** 45 | 46 | ```swift 47 | //I don't know carthage hahahaha.. 48 | //next time :) 49 | ``` 50 | 51 | 52 | 53 | # Usage 54 | 55 | If you are `not using a storyboard`, you can implement SlippingNavigationController instead of navigationController in AppDelegate or ViewController. 56 | 57 | ```swift 58 | import SlippingNaviController 59 | ``` 60 | 61 | ```swift 62 | let navigationController = SlippingNaviController(rootViewController: yourviewController) 63 | self.window?.rootViewController = navigationController 64 | ``` 65 | 66 | 67 | 68 | If you are `using a storyboard`, you can set the UINavigationController's Custom Class in the Identify Inspector. 69 | 70 | ![image](READMEImages/IdentifyInspector.png) 71 | 72 | 73 | 74 | # MIT License 75 | 76 | ``` 77 | MIT License 78 | 79 | Copyright (c) 2017 Dev.MJ 80 | 81 | Permission is hereby granted, free of charge, to any person obtaining a copy 82 | of this software and associated documentation files (the "Software"), to deal 83 | in the Software without restriction, including without limitation the rights 84 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 85 | copies of the Software, and to permit persons to whom the Software is 86 | furnished to do so, subject to the following conditions: 87 | 88 | The above copyright notice and this permission notice shall be included in all 89 | copies or substantial portions of the Software. 90 | 91 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 92 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 93 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 94 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 95 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 96 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 97 | SOFTWARE. 98 | ``` 99 | -------------------------------------------------------------------------------- /READMEImages/IdentifyInspector.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev-MJ/SlippingNaviController/57bee954ffb4dad9254cdf79df1696accced8e6b/READMEImages/IdentifyInspector.png -------------------------------------------------------------------------------- /READMEImages/SlippingNaviController.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev-MJ/SlippingNaviController/57bee954ffb4dad9254cdf79df1696accced8e6b/READMEImages/SlippingNaviController.gif -------------------------------------------------------------------------------- /READMEImages/UINavigationController.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Dev-MJ/SlippingNaviController/57bee954ffb4dad9254cdf79df1696accced8e6b/READMEImages/UINavigationController.gif -------------------------------------------------------------------------------- /SlippingNaviController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "SlippingNaviController" 3 | s.version = "0.1.0" 4 | s.summary = "UINavigationController's popViewController with panGesture" 5 | s.homepage = "https://github.com/Dev-MJ/SlippingNaviController" 6 | s.license = { :type => "MIT", :file => "LICENSE" } 7 | s.author = { "Dev.MJ" => "mr.lucifers@gmail.com" } 8 | s.source = { :git => "https://github.com/Dev-MJ/SlippingNaviController.git", :tag => s.version.to_s } 9 | s.source_files = "SlippingNaviController/*.swift" 10 | s.frameworks = "UIKit" 11 | s.ios.deployment_target = "9.0" 12 | s.pod_target_xcconfig = { "SWIFT_VERSION" => "3.0" } 13 | end 14 | -------------------------------------------------------------------------------- /SlippingNaviController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8A0394361EC0BA330052E28E /* SlippingPopTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A0394351EC0BA330052E28E /* SlippingPopTransition.swift */; }; 11 | 8A7FA7311EC1E23600B833C3 /* SlippingNaviController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8A7FA7301EC1E23600B833C3 /* SlippingNaviController.swift */; }; 12 | 8AB14A961EBF5E2F003DE5DF /* SlippingNaviController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8AB14A941EBF5E2F003DE5DF /* SlippingNaviController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXFileReference section */ 16 | 8A0394351EC0BA330052E28E /* SlippingPopTransition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlippingPopTransition.swift; sourceTree = ""; }; 17 | 8A7FA7301EC1E23600B833C3 /* SlippingNaviController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SlippingNaviController.swift; sourceTree = ""; }; 18 | 8AB14A911EBF5E2F003DE5DF /* SlippingNaviController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SlippingNaviController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 19 | 8AB14A941EBF5E2F003DE5DF /* SlippingNaviController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SlippingNaviController.h; sourceTree = ""; }; 20 | 8AB14A951EBF5E2F003DE5DF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | 8AB14A8D1EBF5E2F003DE5DF /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | ); 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXFrameworksBuildPhase section */ 32 | 33 | /* Begin PBXGroup section */ 34 | 8AB14A871EBF5E2F003DE5DF = { 35 | isa = PBXGroup; 36 | children = ( 37 | 8AB14A931EBF5E2F003DE5DF /* SlippingNaviController */, 38 | 8AB14A921EBF5E2F003DE5DF /* Products */, 39 | ); 40 | sourceTree = ""; 41 | }; 42 | 8AB14A921EBF5E2F003DE5DF /* Products */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | 8AB14A911EBF5E2F003DE5DF /* SlippingNaviController.framework */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | 8AB14A931EBF5E2F003DE5DF /* SlippingNaviController */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | 8AB14A941EBF5E2F003DE5DF /* SlippingNaviController.h */, 54 | 8AB14A951EBF5E2F003DE5DF /* Info.plist */, 55 | 8A0394351EC0BA330052E28E /* SlippingPopTransition.swift */, 56 | 8A7FA7301EC1E23600B833C3 /* SlippingNaviController.swift */, 57 | ); 58 | path = SlippingNaviController; 59 | sourceTree = ""; 60 | }; 61 | /* End PBXGroup section */ 62 | 63 | /* Begin PBXHeadersBuildPhase section */ 64 | 8AB14A8E1EBF5E2F003DE5DF /* Headers */ = { 65 | isa = PBXHeadersBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | 8AB14A961EBF5E2F003DE5DF /* SlippingNaviController.h in Headers */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXHeadersBuildPhase section */ 73 | 74 | /* Begin PBXNativeTarget section */ 75 | 8AB14A901EBF5E2F003DE5DF /* SlippingNaviController */ = { 76 | isa = PBXNativeTarget; 77 | buildConfigurationList = 8AB14A991EBF5E2F003DE5DF /* Build configuration list for PBXNativeTarget "SlippingNaviController" */; 78 | buildPhases = ( 79 | 8AB14A8C1EBF5E2F003DE5DF /* Sources */, 80 | 8AB14A8D1EBF5E2F003DE5DF /* Frameworks */, 81 | 8AB14A8E1EBF5E2F003DE5DF /* Headers */, 82 | 8AB14A8F1EBF5E2F003DE5DF /* Resources */, 83 | ); 84 | buildRules = ( 85 | ); 86 | dependencies = ( 87 | ); 88 | name = SlippingNaviController; 89 | productName = SlippingNaviController; 90 | productReference = 8AB14A911EBF5E2F003DE5DF /* SlippingNaviController.framework */; 91 | productType = "com.apple.product-type.framework"; 92 | }; 93 | /* End PBXNativeTarget section */ 94 | 95 | /* Begin PBXProject section */ 96 | 8AB14A881EBF5E2F003DE5DF /* Project object */ = { 97 | isa = PBXProject; 98 | attributes = { 99 | LastUpgradeCheck = 0830; 100 | ORGANIZATIONNAME = Dev.MJ; 101 | TargetAttributes = { 102 | 8AB14A901EBF5E2F003DE5DF = { 103 | CreatedOnToolsVersion = 8.3.2; 104 | DevelopmentTeam = 78F59JC234; 105 | LastSwiftMigration = 0830; 106 | ProvisioningStyle = Automatic; 107 | }; 108 | }; 109 | }; 110 | buildConfigurationList = 8AB14A8B1EBF5E2F003DE5DF /* Build configuration list for PBXProject "SlippingNaviController" */; 111 | compatibilityVersion = "Xcode 3.2"; 112 | developmentRegion = English; 113 | hasScannedForEncodings = 0; 114 | knownRegions = ( 115 | en, 116 | ); 117 | mainGroup = 8AB14A871EBF5E2F003DE5DF; 118 | productRefGroup = 8AB14A921EBF5E2F003DE5DF /* Products */; 119 | projectDirPath = ""; 120 | projectRoot = ""; 121 | targets = ( 122 | 8AB14A901EBF5E2F003DE5DF /* SlippingNaviController */, 123 | ); 124 | }; 125 | /* End PBXProject section */ 126 | 127 | /* Begin PBXResourcesBuildPhase section */ 128 | 8AB14A8F1EBF5E2F003DE5DF /* Resources */ = { 129 | isa = PBXResourcesBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | ); 133 | runOnlyForDeploymentPostprocessing = 0; 134 | }; 135 | /* End PBXResourcesBuildPhase section */ 136 | 137 | /* Begin PBXSourcesBuildPhase section */ 138 | 8AB14A8C1EBF5E2F003DE5DF /* Sources */ = { 139 | isa = PBXSourcesBuildPhase; 140 | buildActionMask = 2147483647; 141 | files = ( 142 | 8A0394361EC0BA330052E28E /* SlippingPopTransition.swift in Sources */, 143 | 8A7FA7311EC1E23600B833C3 /* SlippingNaviController.swift in Sources */, 144 | ); 145 | runOnlyForDeploymentPostprocessing = 0; 146 | }; 147 | /* End PBXSourcesBuildPhase section */ 148 | 149 | /* Begin XCBuildConfiguration section */ 150 | 8AB14A971EBF5E2F003DE5DF /* Debug */ = { 151 | isa = XCBuildConfiguration; 152 | buildSettings = { 153 | ALWAYS_SEARCH_USER_PATHS = NO; 154 | CLANG_ANALYZER_NONNULL = YES; 155 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 156 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 157 | CLANG_CXX_LIBRARY = "libc++"; 158 | CLANG_ENABLE_MODULES = YES; 159 | CLANG_ENABLE_OBJC_ARC = YES; 160 | CLANG_WARN_BOOL_CONVERSION = YES; 161 | CLANG_WARN_CONSTANT_CONVERSION = YES; 162 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 163 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 164 | CLANG_WARN_EMPTY_BODY = YES; 165 | CLANG_WARN_ENUM_CONVERSION = YES; 166 | CLANG_WARN_INFINITE_RECURSION = YES; 167 | CLANG_WARN_INT_CONVERSION = YES; 168 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 169 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 170 | CLANG_WARN_UNREACHABLE_CODE = YES; 171 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 172 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 173 | COPY_PHASE_STRIP = NO; 174 | CURRENT_PROJECT_VERSION = 1; 175 | DEBUG_INFORMATION_FORMAT = dwarf; 176 | ENABLE_STRICT_OBJC_MSGSEND = YES; 177 | ENABLE_TESTABILITY = YES; 178 | GCC_C_LANGUAGE_STANDARD = gnu99; 179 | GCC_DYNAMIC_NO_PIC = NO; 180 | GCC_NO_COMMON_BLOCKS = YES; 181 | GCC_OPTIMIZATION_LEVEL = 0; 182 | GCC_PREPROCESSOR_DEFINITIONS = ( 183 | "DEBUG=1", 184 | "$(inherited)", 185 | ); 186 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 187 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 188 | GCC_WARN_UNDECLARED_SELECTOR = YES; 189 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 190 | GCC_WARN_UNUSED_FUNCTION = YES; 191 | GCC_WARN_UNUSED_VARIABLE = YES; 192 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 193 | MTL_ENABLE_DEBUG_INFO = YES; 194 | ONLY_ACTIVE_ARCH = YES; 195 | SDKROOT = iphoneos; 196 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 197 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 198 | TARGETED_DEVICE_FAMILY = "1,2"; 199 | VERSIONING_SYSTEM = "apple-generic"; 200 | VERSION_INFO_PREFIX = ""; 201 | }; 202 | name = Debug; 203 | }; 204 | 8AB14A981EBF5E2F003DE5DF /* Release */ = { 205 | isa = XCBuildConfiguration; 206 | buildSettings = { 207 | ALWAYS_SEARCH_USER_PATHS = NO; 208 | CLANG_ANALYZER_NONNULL = YES; 209 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 210 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 211 | CLANG_CXX_LIBRARY = "libc++"; 212 | CLANG_ENABLE_MODULES = YES; 213 | CLANG_ENABLE_OBJC_ARC = YES; 214 | CLANG_WARN_BOOL_CONVERSION = YES; 215 | CLANG_WARN_CONSTANT_CONVERSION = YES; 216 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 217 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 218 | CLANG_WARN_EMPTY_BODY = YES; 219 | CLANG_WARN_ENUM_CONVERSION = YES; 220 | CLANG_WARN_INFINITE_RECURSION = YES; 221 | CLANG_WARN_INT_CONVERSION = YES; 222 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 223 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 224 | CLANG_WARN_UNREACHABLE_CODE = YES; 225 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 226 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 227 | COPY_PHASE_STRIP = NO; 228 | CURRENT_PROJECT_VERSION = 1; 229 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 230 | ENABLE_NS_ASSERTIONS = NO; 231 | ENABLE_STRICT_OBJC_MSGSEND = YES; 232 | GCC_C_LANGUAGE_STANDARD = gnu99; 233 | GCC_NO_COMMON_BLOCKS = YES; 234 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 235 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 236 | GCC_WARN_UNDECLARED_SELECTOR = YES; 237 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 238 | GCC_WARN_UNUSED_FUNCTION = YES; 239 | GCC_WARN_UNUSED_VARIABLE = YES; 240 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 241 | MTL_ENABLE_DEBUG_INFO = NO; 242 | SDKROOT = iphoneos; 243 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 244 | TARGETED_DEVICE_FAMILY = "1,2"; 245 | VALIDATE_PRODUCT = YES; 246 | VERSIONING_SYSTEM = "apple-generic"; 247 | VERSION_INFO_PREFIX = ""; 248 | }; 249 | name = Release; 250 | }; 251 | 8AB14A9A1EBF5E2F003DE5DF /* Debug */ = { 252 | isa = XCBuildConfiguration; 253 | buildSettings = { 254 | CLANG_ENABLE_MODULES = YES; 255 | CODE_SIGN_IDENTITY = ""; 256 | DEFINES_MODULE = YES; 257 | DEVELOPMENT_TEAM = 78F59JC234; 258 | DYLIB_COMPATIBILITY_VERSION = 1; 259 | DYLIB_CURRENT_VERSION = 1; 260 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 261 | INFOPLIST_FILE = SlippingNaviController/Info.plist; 262 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 263 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 264 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 265 | PRODUCT_BUNDLE_IDENTIFIER = Dev.MJ.SlippingNaviController; 266 | PRODUCT_NAME = "$(TARGET_NAME)"; 267 | SKIP_INSTALL = YES; 268 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 269 | SWIFT_VERSION = 3.0; 270 | TARGETED_DEVICE_FAMILY = 1; 271 | }; 272 | name = Debug; 273 | }; 274 | 8AB14A9B1EBF5E2F003DE5DF /* Release */ = { 275 | isa = XCBuildConfiguration; 276 | buildSettings = { 277 | CLANG_ENABLE_MODULES = YES; 278 | CODE_SIGN_IDENTITY = ""; 279 | DEFINES_MODULE = YES; 280 | DEVELOPMENT_TEAM = 78F59JC234; 281 | DYLIB_COMPATIBILITY_VERSION = 1; 282 | DYLIB_CURRENT_VERSION = 1; 283 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 284 | INFOPLIST_FILE = SlippingNaviController/Info.plist; 285 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 286 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 287 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 288 | PRODUCT_BUNDLE_IDENTIFIER = Dev.MJ.SlippingNaviController; 289 | PRODUCT_NAME = "$(TARGET_NAME)"; 290 | SKIP_INSTALL = YES; 291 | SWIFT_VERSION = 3.0; 292 | TARGETED_DEVICE_FAMILY = 1; 293 | }; 294 | name = Release; 295 | }; 296 | /* End XCBuildConfiguration section */ 297 | 298 | /* Begin XCConfigurationList section */ 299 | 8AB14A8B1EBF5E2F003DE5DF /* Build configuration list for PBXProject "SlippingNaviController" */ = { 300 | isa = XCConfigurationList; 301 | buildConfigurations = ( 302 | 8AB14A971EBF5E2F003DE5DF /* Debug */, 303 | 8AB14A981EBF5E2F003DE5DF /* Release */, 304 | ); 305 | defaultConfigurationIsVisible = 0; 306 | defaultConfigurationName = Release; 307 | }; 308 | 8AB14A991EBF5E2F003DE5DF /* Build configuration list for PBXNativeTarget "SlippingNaviController" */ = { 309 | isa = XCConfigurationList; 310 | buildConfigurations = ( 311 | 8AB14A9A1EBF5E2F003DE5DF /* Debug */, 312 | 8AB14A9B1EBF5E2F003DE5DF /* Release */, 313 | ); 314 | defaultConfigurationIsVisible = 0; 315 | defaultConfigurationName = Release; 316 | }; 317 | /* End XCConfigurationList section */ 318 | }; 319 | rootObject = 8AB14A881EBF5E2F003DE5DF /* Project object */; 320 | } 321 | -------------------------------------------------------------------------------- /SlippingNaviController.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SlippingNaviController.xcodeproj/xcshareddata/xcschemes/SlippingNaviController.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /SlippingNaviController.xcodeproj/xcuserdata/Dev.MJ.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SlippingNaviController.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 8AB14A901EBF5E2F003DE5DF 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /SlippingNaviController/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 | 0.1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SlippingNaviController/SlippingNaviController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SlippingNaviController.h 3 | // SlippingNaviController 4 | // 5 | // Created by Dev.MJ on 07/05/2017. 6 | // Copyright © 2017 Dev.MJ. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SlippingNaviController. 12 | FOUNDATION_EXPORT double SlippingNaviControllerVersionNumber; 13 | 14 | //! Project version string for SlippingNaviController. 15 | FOUNDATION_EXPORT const unsigned char SlippingNaviControllerVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SlippingNaviController/SlippingNaviController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SlippingNaviController.swift 3 | // SlippingNaviController 4 | // 5 | // Created by Dev.MJ on 09/05/2017. 6 | // Copyright © 2017 Dev.MJ. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SlippingNaviController: UINavigationController { 12 | 13 | ///백분율 기반 interactive transition object는 하나의 VC가 사라지고 다른 VC가 나타나는 사이에 맞춤 애니메이션을 구동합니다. 14 | ///애니메이션을 설정하고 수행하기 위해 UIViewControllerAnimatedTransitioning 프로토콜을 채택한 사용자 정의 객체인 transition animator delegate를 사용합니다. 15 | var interactivePopTransition: UIPercentDrivenInteractiveTransition? 16 | 17 | 18 | // MARK: - View Life Cycle 19 | 20 | override func viewDidLoad() { 21 | super.viewDidLoad() 22 | self.delegate = self 23 | } 24 | } 25 | 26 | extension SlippingNaviController: UINavigationControllerDelegate { 27 | 28 | //optional. navigationController가 VC의 view와 navigation item properties를 표시하기 바로 전에 호출됩니다. 29 | func navigationController(_ navigationController: UINavigationController, 30 | willShow viewController: UIViewController, 31 | animated: Bool) { 32 | self.addPanguesture(viewController: viewController) 33 | } 34 | 35 | //optional. delegate가 VC의 transition동안 사용 할 noninteractive animator object를 return하게 하기 위해 호출 됩니다. 36 | //네비게이션 스택에 추가되거나 네비게이션 스택에서 제거 될 때 뷰 컨트롤러간에 custom animation transition을 제공하려는 경우 이 delegate 메서드를 구현합니다. 37 | //반환하는 객체는 지정된 시간 동안 지정된 유형의 작업에 대해 지정된 뷰 컨트롤러에 대해 noninteractive animation을 구성하고 수행 할 수 있어야 한다. 38 | func navigationController(_ navigationController: UINavigationController, 39 | animationControllerFor operation: UINavigationControllerOperation, 40 | from fromVC: UIViewController, 41 | to toVC: UIViewController) -> UIViewControllerAnimatedTransitioning? { 42 | ///발생하는 transition 유형 43 | if operation == .pop { //navigation stack에 가장 위에 있는 vc가 제거 44 | return SlippingPopTransition() 45 | }else{ 46 | return nil 47 | } 48 | } 49 | 50 | //optional. delegate가 VC의 transition동안 사용 할 interactive animator object를 return하게 하기 위해 호출 됩니다. 51 | //네비게이션 스택에 추가되거나 네비게이션 스택에서 제거 될 때 뷰 컨트롤러간에 custom interactive transition을 제공하고자 할 때 이 델리게이트 메소드를 구현합니다. 52 | //반환하는 객체는 transition의 상호 작용 측면을 구성해야하며 animationController 매개 변수의 객체로 작업하여 애니메이션을 시작해야합니다. 53 | func navigationController(_ navigationController: UINavigationController, 54 | interactionControllerFor animationController: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? { 55 | if animationController.isKind(of: SlippingPopTransition.self) { 56 | return self.interactivePopTransition 57 | }else{ 58 | return nil 59 | } 60 | } 61 | 62 | func addPanguesture(viewController: UIViewController) { 63 | let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture)) 64 | viewController.view.addGestureRecognizer(pan) 65 | } 66 | 67 | func handlePanGesture(panGesture: UIPanGestureRecognizer){ 68 | var progress = panGesture.translation(in: self.view).x / self.view.frame.width 69 | progress = min(1, max(0, progress)) 70 | switch panGesture.state { 71 | case .began: 72 | self.interactivePopTransition = UIPercentDrivenInteractiveTransition() 73 | self.popViewController(animated: true) 74 | case .changed: 75 | self.interactivePopTransition?.update(progress) 76 | case .ended, .cancelled: 77 | if progress > 0.1 { 78 | self.interactivePopTransition?.finish() 79 | }else{ 80 | self.interactivePopTransition?.cancel() 81 | } 82 | self.interactivePopTransition = nil 83 | default: 84 | break 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /SlippingNaviController/SlippingPopTransition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SlippingPopTransition.swift 3 | // SlippingNaviController 4 | // 5 | // Created by Dev.MJ on 08/05/2017. 6 | // Copyright © 2017 Dev.MJ. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SlippingPopTransition: NSObject {} 12 | 13 | extension SlippingPopTransition: UIViewControllerAnimatedTransitioning { 14 | 15 | //required. Duration of the transition animation 16 | func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 17 | return 0.3 18 | } 19 | 20 | //required. 애니메이터 객체에 전환 애니메이션을 수행하도록 지시. 21 | func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 22 | //transitionContext : transition에 관한 정보를 포함한 context object. 23 | //transition이 시작할 때 보이는 VC 24 | guard let startVC = transitionContext.viewController(forKey: .from) else { return } 25 | //transition이 끝난 뒤에 보이는 VC 26 | guard let endVC = transitionContext.viewController(forKey: .to) else { return } 27 | 28 | ///The view in which the animated transition should take place. 29 | let containerView = transitionContext.containerView 30 | if let endView = endVC.view, let startView = startVC.view { 31 | containerView.addSubview(endView) 32 | containerView.bringSubview(toFront: startView) 33 | endView.frame = transitionContext.finalFrame(for: endVC) 34 | 35 | UIView.animate(withDuration: transitionDuration(using: transitionContext), 36 | delay: 0, 37 | options: .curveLinear, 38 | animations: { 39 | startVC.view.frame = CGRect(x: endVC.view.frame.width, 40 | y: startVC.view.frame.origin.y, 41 | width: startVC.view.frame.width, 42 | height: startVC.view.frame.height) 43 | }, 44 | completion: { finished in 45 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 46 | }) 47 | } 48 | } 49 | } 50 | --------------------------------------------------------------------------------