├── .gitignore ├── README.md ├── SwiftyGestureRecognition.xcodeproj ├── project.pbxproj └── xcshareddata │ └── xcschemes │ └── SwiftyGestureRecognition.xcscheme └── SwiftyGestureRecognition ├── Info.plist ├── SwiftyGestureRecognition.h └── SwiftyGestureRecognition.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | .AppleDouble 4 | .LSOverride 5 | .Spotlight-V100 6 | .Trashes 7 | .AppleDB 8 | .AppleDesktop 9 | .apdisk 10 | ._* 11 | 12 | # Xcode 13 | build/ 14 | *.pbxuser 15 | !default.pbxuser 16 | *.mode1v3 17 | !default.mode1v3 18 | *.mode2v3 19 | !default.mode2v3 20 | *.perspectivev3 21 | !default.perspectivev3 22 | *.xcworkspace 23 | !default.xcworkspace 24 | xcuserdata 25 | *.xccheckout 26 | *.moved-aside 27 | DerivedData 28 | *.hmap 29 | *.ipa 30 | *.xcuserstate 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SwiftyGestureRecognition 2 | 3 | A drop-in library for extending UIGestureRecognizers to aid in prototyping with them in Xcode Playgrounds. 4 | 5 | Definitely not prime for shipping I wrote it just for demo purposes, but it's fun to mess with. Use it to write less boilerplate code when trying out UIGestureRecognizers in Xcode Playgrounds. 6 | 7 | Was built for my presentation at [try! Swift 2016](http://www.tryswift.com), so be sure to check out my talk when it's posted! :D 8 | 9 | Example includes a playground that shows logging a UIPanGestureRecognizer. 10 | 11 | ### How do I use it? 12 | 13 | Create an Xcode Workspace with a playground. Drag + drop SwiftyGestureRecognition.xcodeproj into the workspace and import it into your playground: `import SwiftyGestureRecognition`. 14 | 15 | Using UIGestureRecognizers is now pretty simple! 16 | 17 | ```swift 18 | let gestureRecognizer = UIPanGestureRecognizer(view: aView) 19 | .didBegin { (gestureRecognizer) in 20 | print("began") 21 | }.didChange { (gestureRecognizer) in 22 | print("changed") 23 | }.didEnd { (gestureRecognizer) in 24 | print("ended") 25 | } 26 | ``` 27 | 28 | ### How do I compile? 29 | Xcode pretty much. 30 | 31 | ### License? 32 | Pretty much the BSD license, just don't repackage it and call it your own please! 33 | 34 | Also if you do make some changes, feel free to make a pull request and help make things more awesome! 35 | 36 | ### Contact Info? 37 | 38 | Feel free to follow me on twitter: [@b3ll](https://www.twitter.com/b3ll)! 39 | -------------------------------------------------------------------------------- /SwiftyGestureRecognition.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 66B79BCE1C588336005F73FE /* SwiftyGestureRecognition.h in Headers */ = {isa = PBXBuildFile; fileRef = 66B79BCD1C588336005F73FE /* SwiftyGestureRecognition.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 66B79BD61C58834F005F73FE /* SwiftyGestureRecognition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66B79BD51C58834F005F73FE /* SwiftyGestureRecognition.swift */; }; 12 | /* End PBXBuildFile section */ 13 | 14 | /* Begin PBXFileReference section */ 15 | 66B79BC81C588336005F73FE /* SwiftyGestureRecognition.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyGestureRecognition.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 16 | 66B79BCC1C588336005F73FE /* .gitignore */ = {isa = PBXFileReference; lastKnownFileType = text; name = .gitignore; path = ../.gitignore; sourceTree = ""; }; 17 | 66B79BCD1C588336005F73FE /* SwiftyGestureRecognition.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SwiftyGestureRecognition.h; sourceTree = ""; }; 18 | 66B79BCF1C588336005F73FE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 19 | 66B79BD51C58834F005F73FE /* SwiftyGestureRecognition.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftyGestureRecognition.swift; sourceTree = ""; }; 20 | /* End PBXFileReference section */ 21 | 22 | /* Begin PBXFrameworksBuildPhase section */ 23 | 66B79BC41C588336005F73FE /* Frameworks */ = { 24 | isa = PBXFrameworksBuildPhase; 25 | buildActionMask = 2147483647; 26 | files = ( 27 | ); 28 | runOnlyForDeploymentPostprocessing = 0; 29 | }; 30 | /* End PBXFrameworksBuildPhase section */ 31 | 32 | /* Begin PBXGroup section */ 33 | 66B79BBE1C588336005F73FE = { 34 | isa = PBXGroup; 35 | children = ( 36 | 66B79BCA1C588336005F73FE /* SwiftyGestureRecognition */, 37 | 66B79BC91C588336005F73FE /* Products */, 38 | ); 39 | sourceTree = ""; 40 | }; 41 | 66B79BC91C588336005F73FE /* Products */ = { 42 | isa = PBXGroup; 43 | children = ( 44 | 66B79BC81C588336005F73FE /* SwiftyGestureRecognition.framework */, 45 | ); 46 | name = Products; 47 | sourceTree = ""; 48 | }; 49 | 66B79BCA1C588336005F73FE /* SwiftyGestureRecognition */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 66B79BCD1C588336005F73FE /* SwiftyGestureRecognition.h */, 53 | 66B79BD51C58834F005F73FE /* SwiftyGestureRecognition.swift */, 54 | 66B79BCF1C588336005F73FE /* Info.plist */, 55 | 66B79BCB1C588336005F73FE /* Supporting Files */, 56 | ); 57 | path = SwiftyGestureRecognition; 58 | sourceTree = ""; 59 | }; 60 | 66B79BCB1C588336005F73FE /* Supporting Files */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 66B79BCC1C588336005F73FE /* .gitignore */, 64 | ); 65 | name = "Supporting Files"; 66 | sourceTree = ""; 67 | }; 68 | /* End PBXGroup section */ 69 | 70 | /* Begin PBXHeadersBuildPhase section */ 71 | 66B79BC51C588336005F73FE /* Headers */ = { 72 | isa = PBXHeadersBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | 66B79BCE1C588336005F73FE /* SwiftyGestureRecognition.h in Headers */, 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | /* End PBXHeadersBuildPhase section */ 80 | 81 | /* Begin PBXNativeTarget section */ 82 | 66B79BC71C588336005F73FE /* SwiftyGestureRecognition */ = { 83 | isa = PBXNativeTarget; 84 | buildConfigurationList = 66B79BD21C588336005F73FE /* Build configuration list for PBXNativeTarget "SwiftyGestureRecognition" */; 85 | buildPhases = ( 86 | 66B79BC31C588336005F73FE /* Sources */, 87 | 66B79BC41C588336005F73FE /* Frameworks */, 88 | 66B79BC51C588336005F73FE /* Headers */, 89 | 66B79BC61C588336005F73FE /* Resources */, 90 | ); 91 | buildRules = ( 92 | ); 93 | dependencies = ( 94 | ); 95 | name = SwiftyGestureRecognition; 96 | productName = SwiftyGestureRecognition; 97 | productReference = 66B79BC81C588336005F73FE /* SwiftyGestureRecognition.framework */; 98 | productType = "com.apple.product-type.framework"; 99 | }; 100 | /* End PBXNativeTarget section */ 101 | 102 | /* Begin PBXProject section */ 103 | 66B79BBF1C588336005F73FE /* Project object */ = { 104 | isa = PBXProject; 105 | attributes = { 106 | LastUpgradeCheck = 1130; 107 | ORGANIZATIONNAME = "Adam Bell"; 108 | TargetAttributes = { 109 | 66B79BC71C588336005F73FE = { 110 | CreatedOnToolsVersion = 7.2; 111 | LastSwiftMigration = 1130; 112 | }; 113 | }; 114 | }; 115 | buildConfigurationList = 66B79BC21C588336005F73FE /* Build configuration list for PBXProject "SwiftyGestureRecognition" */; 116 | compatibilityVersion = "Xcode 3.2"; 117 | developmentRegion = en; 118 | hasScannedForEncodings = 0; 119 | knownRegions = ( 120 | en, 121 | Base, 122 | ); 123 | mainGroup = 66B79BBE1C588336005F73FE; 124 | productRefGroup = 66B79BC91C588336005F73FE /* Products */; 125 | projectDirPath = ""; 126 | projectRoot = ""; 127 | targets = ( 128 | 66B79BC71C588336005F73FE /* SwiftyGestureRecognition */, 129 | ); 130 | }; 131 | /* End PBXProject section */ 132 | 133 | /* Begin PBXResourcesBuildPhase section */ 134 | 66B79BC61C588336005F73FE /* Resources */ = { 135 | isa = PBXResourcesBuildPhase; 136 | buildActionMask = 2147483647; 137 | files = ( 138 | ); 139 | runOnlyForDeploymentPostprocessing = 0; 140 | }; 141 | /* End PBXResourcesBuildPhase section */ 142 | 143 | /* Begin PBXSourcesBuildPhase section */ 144 | 66B79BC31C588336005F73FE /* Sources */ = { 145 | isa = PBXSourcesBuildPhase; 146 | buildActionMask = 2147483647; 147 | files = ( 148 | 66B79BD61C58834F005F73FE /* SwiftyGestureRecognition.swift in Sources */, 149 | ); 150 | runOnlyForDeploymentPostprocessing = 0; 151 | }; 152 | /* End PBXSourcesBuildPhase section */ 153 | 154 | /* Begin XCBuildConfiguration section */ 155 | 66B79BD01C588336005F73FE /* Debug */ = { 156 | isa = XCBuildConfiguration; 157 | buildSettings = { 158 | ALWAYS_SEARCH_USER_PATHS = NO; 159 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 160 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 161 | CLANG_CXX_LIBRARY = "libc++"; 162 | CLANG_ENABLE_MODULES = YES; 163 | CLANG_ENABLE_OBJC_ARC = YES; 164 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 165 | CLANG_WARN_BOOL_CONVERSION = YES; 166 | CLANG_WARN_COMMA = YES; 167 | CLANG_WARN_CONSTANT_CONVERSION = YES; 168 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 169 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 170 | CLANG_WARN_EMPTY_BODY = YES; 171 | CLANG_WARN_ENUM_CONVERSION = YES; 172 | CLANG_WARN_INFINITE_RECURSION = YES; 173 | CLANG_WARN_INT_CONVERSION = YES; 174 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 175 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 176 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 177 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 178 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 179 | CLANG_WARN_STRICT_PROTOTYPES = YES; 180 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 181 | CLANG_WARN_UNREACHABLE_CODE = YES; 182 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 183 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 184 | COPY_PHASE_STRIP = NO; 185 | CURRENT_PROJECT_VERSION = 1; 186 | DEBUG_INFORMATION_FORMAT = dwarf; 187 | ENABLE_STRICT_OBJC_MSGSEND = YES; 188 | ENABLE_TESTABILITY = YES; 189 | GCC_C_LANGUAGE_STANDARD = gnu99; 190 | GCC_DYNAMIC_NO_PIC = NO; 191 | GCC_NO_COMMON_BLOCKS = YES; 192 | GCC_OPTIMIZATION_LEVEL = 0; 193 | GCC_PREPROCESSOR_DEFINITIONS = ( 194 | "DEBUG=1", 195 | "$(inherited)", 196 | ); 197 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 198 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 199 | GCC_WARN_UNDECLARED_SELECTOR = YES; 200 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 201 | GCC_WARN_UNUSED_FUNCTION = YES; 202 | GCC_WARN_UNUSED_VARIABLE = YES; 203 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 204 | MTL_ENABLE_DEBUG_INFO = YES; 205 | ONLY_ACTIVE_ARCH = YES; 206 | SDKROOT = iphoneos; 207 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 208 | TARGETED_DEVICE_FAMILY = "1,2"; 209 | VERSIONING_SYSTEM = "apple-generic"; 210 | VERSION_INFO_PREFIX = ""; 211 | }; 212 | name = Debug; 213 | }; 214 | 66B79BD11C588336005F73FE /* Release */ = { 215 | isa = XCBuildConfiguration; 216 | buildSettings = { 217 | ALWAYS_SEARCH_USER_PATHS = NO; 218 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; 219 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 220 | CLANG_CXX_LIBRARY = "libc++"; 221 | CLANG_ENABLE_MODULES = YES; 222 | CLANG_ENABLE_OBJC_ARC = YES; 223 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 224 | CLANG_WARN_BOOL_CONVERSION = YES; 225 | CLANG_WARN_COMMA = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 228 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 229 | CLANG_WARN_EMPTY_BODY = YES; 230 | CLANG_WARN_ENUM_CONVERSION = YES; 231 | CLANG_WARN_INFINITE_RECURSION = YES; 232 | CLANG_WARN_INT_CONVERSION = YES; 233 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 234 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 235 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 236 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 237 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 238 | CLANG_WARN_STRICT_PROTOTYPES = YES; 239 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 240 | CLANG_WARN_UNREACHABLE_CODE = YES; 241 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 242 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 243 | COPY_PHASE_STRIP = NO; 244 | CURRENT_PROJECT_VERSION = 1; 245 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 246 | ENABLE_NS_ASSERTIONS = NO; 247 | ENABLE_STRICT_OBJC_MSGSEND = YES; 248 | GCC_C_LANGUAGE_STANDARD = gnu99; 249 | GCC_NO_COMMON_BLOCKS = YES; 250 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 251 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 252 | GCC_WARN_UNDECLARED_SELECTOR = YES; 253 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 254 | GCC_WARN_UNUSED_FUNCTION = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | IPHONEOS_DEPLOYMENT_TARGET = 9.2; 257 | MTL_ENABLE_DEBUG_INFO = NO; 258 | SDKROOT = iphoneos; 259 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 260 | TARGETED_DEVICE_FAMILY = "1,2"; 261 | VALIDATE_PRODUCT = YES; 262 | VERSIONING_SYSTEM = "apple-generic"; 263 | VERSION_INFO_PREFIX = ""; 264 | }; 265 | name = Release; 266 | }; 267 | 66B79BD31C588336005F73FE /* Debug */ = { 268 | isa = XCBuildConfiguration; 269 | buildSettings = { 270 | CLANG_ENABLE_MODULES = YES; 271 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 272 | DEFINES_MODULE = YES; 273 | DYLIB_COMPATIBILITY_VERSION = 1; 274 | DYLIB_CURRENT_VERSION = 1; 275 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 276 | INFOPLIST_FILE = SwiftyGestureRecognition/Info.plist; 277 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 278 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 279 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 280 | PRODUCT_BUNDLE_IDENTIFIER = ca.adambell.SwiftyGestureRecognition; 281 | PRODUCT_NAME = "$(TARGET_NAME)"; 282 | SKIP_INSTALL = YES; 283 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 284 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 285 | SWIFT_VERSION = 5.0; 286 | }; 287 | name = Debug; 288 | }; 289 | 66B79BD41C588336005F73FE /* Release */ = { 290 | isa = XCBuildConfiguration; 291 | buildSettings = { 292 | CLANG_ENABLE_MODULES = YES; 293 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 294 | DEFINES_MODULE = YES; 295 | DYLIB_COMPATIBILITY_VERSION = 1; 296 | DYLIB_CURRENT_VERSION = 1; 297 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 298 | INFOPLIST_FILE = SwiftyGestureRecognition/Info.plist; 299 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 300 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 301 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 302 | PRODUCT_BUNDLE_IDENTIFIER = ca.adambell.SwiftyGestureRecognition; 303 | PRODUCT_NAME = "$(TARGET_NAME)"; 304 | SKIP_INSTALL = YES; 305 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 306 | SWIFT_VERSION = 5.0; 307 | }; 308 | name = Release; 309 | }; 310 | /* End XCBuildConfiguration section */ 311 | 312 | /* Begin XCConfigurationList section */ 313 | 66B79BC21C588336005F73FE /* Build configuration list for PBXProject "SwiftyGestureRecognition" */ = { 314 | isa = XCConfigurationList; 315 | buildConfigurations = ( 316 | 66B79BD01C588336005F73FE /* Debug */, 317 | 66B79BD11C588336005F73FE /* Release */, 318 | ); 319 | defaultConfigurationIsVisible = 0; 320 | defaultConfigurationName = Release; 321 | }; 322 | 66B79BD21C588336005F73FE /* Build configuration list for PBXNativeTarget "SwiftyGestureRecognition" */ = { 323 | isa = XCConfigurationList; 324 | buildConfigurations = ( 325 | 66B79BD31C588336005F73FE /* Debug */, 326 | 66B79BD41C588336005F73FE /* Release */, 327 | ); 328 | defaultConfigurationIsVisible = 0; 329 | defaultConfigurationName = Release; 330 | }; 331 | /* End XCConfigurationList section */ 332 | }; 333 | rootObject = 66B79BBF1C588336005F73FE /* Project object */; 334 | } 335 | -------------------------------------------------------------------------------- /SwiftyGestureRecognition.xcodeproj/xcshareddata/xcschemes/SwiftyGestureRecognition.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 43 | 44 | 50 | 51 | 52 | 53 | 59 | 60 | 66 | 67 | 68 | 69 | 71 | 72 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /SwiftyGestureRecognition/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /SwiftyGestureRecognition/SwiftyGestureRecognition.h: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftyGestureRecognition.h 3 | // SwiftyGestureRecognition 4 | // 5 | // Created by Adam Bell on 1/26/16. 6 | // Copyright © 2016 Adam Bell. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for SwiftyGestureRecognition. 12 | FOUNDATION_EXPORT double SwiftyGestureRecognitionVersionNumber; 13 | 14 | //! Project version string for SwiftyGestureRecognition. 15 | FOUNDATION_EXPORT const unsigned char SwiftyGestureRecognitionVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /SwiftyGestureRecognition/SwiftyGestureRecognition.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftyGestureRecognition.swift 3 | // SwiftyGestureRecognition 4 | // 5 | // Created by Adam Bell on 1/26/16. 6 | // Copyright © 2016 Adam Bell. All rights reserved. 7 | // 8 | 9 | import ObjectiveC 10 | import UIKit 11 | 12 | public typealias UIGestureRecognizerStateChangeBlock = ((_ gestureRecognizer: UIGestureRecognizer) -> Void) 13 | 14 | private class UIGestureRecognizerStateChangeBlockHost { 15 | 16 | weak var gestureRecognizer: UIGestureRecognizer? 17 | 18 | var block: [UIGestureRecognizer.State: UIGestureRecognizerStateChangeBlock] = [:] 19 | 20 | init(gestureRecognizer: UIGestureRecognizer) { 21 | self.gestureRecognizer = gestureRecognizer 22 | gestureRecognizer.addTarget(self, action: #selector(gestureRecognizerStateChanged)) 23 | } 24 | 25 | deinit { 26 | gestureRecognizer?.removeTarget(self, action: #selector(gestureRecognizerStateChanged)) 27 | } 28 | 29 | @objc fileprivate func gestureRecognizerStateChanged(_ gestureRecognizer: UIGestureRecognizer) { 30 | if let stateChangeBlock = block[gestureRecognizer.state] { 31 | stateChangeBlock(gestureRecognizer) 32 | } 33 | } 34 | 35 | } 36 | 37 | public extension UIGestureRecognizer { 38 | 39 | fileprivate struct AssociatedBlockHost { 40 | static var blockHost = "blockHost" 41 | } 42 | 43 | fileprivate var blockHost: UIGestureRecognizerStateChangeBlockHost { 44 | get { 45 | if let blockHost = objc_getAssociatedObject(self, &AssociatedBlockHost.blockHost) as? UIGestureRecognizerStateChangeBlockHost { 46 | return blockHost 47 | } else { 48 | let blockHost = UIGestureRecognizerStateChangeBlockHost(gestureRecognizer: self) 49 | objc_setAssociatedObject(self, &AssociatedBlockHost.blockHost, blockHost, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 50 | return blockHost 51 | } 52 | } 53 | } 54 | 55 | convenience init(view: UIView) { 56 | self.init() 57 | view.addGestureRecognizer(self) 58 | } 59 | 60 | func didBegin(_ didBegin: UIGestureRecognizerStateChangeBlock?) -> UIGestureRecognizer { 61 | blockHost.block[.began] = didBegin 62 | return self 63 | } 64 | 65 | func didChange(_ didChange: UIGestureRecognizerStateChangeBlock?) -> UIGestureRecognizer { 66 | blockHost.block[.changed] = didChange 67 | return self 68 | } 69 | 70 | func didEnd(_ didEnd: UIGestureRecognizerStateChangeBlock?) -> UIGestureRecognizer { 71 | blockHost.block[.ended] = didEnd 72 | return self 73 | } 74 | 75 | func didCancel(_ didCancel: UIGestureRecognizerStateChangeBlock?) -> UIGestureRecognizer { 76 | blockHost.block[.cancelled] = didCancel 77 | return self 78 | } 79 | 80 | func didFail(_ didFail: UIGestureRecognizerStateChangeBlock?) -> UIGestureRecognizer { 81 | blockHost.block[.failed] = didFail 82 | return self 83 | } 84 | 85 | } 86 | --------------------------------------------------------------------------------