├── .gitignore ├── DRKonamiCode-Info.plist ├── DRKonamiCode-Prefix.pch ├── DRKonamiCode.podspec ├── DRKonamiCode.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── Default-568h@2x.png ├── README.md ├── Resources ├── DRViewController.xib ├── nes.png └── nes@2x.png ├── Sources ├── DRAppDelegate.h ├── DRAppDelegate.m ├── DRKonamiGestureRecognizer.h ├── DRKonamiGestureRecognizer.m ├── DRViewController.h ├── DRViewController.m └── main.m └── license /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode Noise 2 | *build 3 | *xcuserdata 4 | *.pbxuser 5 | *.mode1v3 6 | *.mode2v3 7 | 8 | # OS X Noise 9 | *.DS_Store 10 | -------------------------------------------------------------------------------- /DRKonamiCode-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIconFiles 12 | 13 | CFBundleIdentifier 14 | us.theredb.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1.0 27 | LSRequiresIPhoneOS 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /DRKonamiCode-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'DRKonamiCode' target in the 'DRKonamiCode' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | -------------------------------------------------------------------------------- /DRKonamiCode.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'DRKonamiCode' 3 | s.version = '1.1.1' 4 | s.platform = :ios 5 | s.ios.deployment_target = '5.0' 6 | s.license = 'MIT' 7 | s.summary = 'The Konami Code gesture recognizer for iOS.' 8 | s.homepage = 'https://github.com/objectiveSee/DRKonamiCode' 9 | s.author = { "Danny Ricciotti" => "dan.ricciotti@gmail.com" } 10 | 11 | s.source = { :git => 'https://github.com/objectiveSee/DRKonamiCode.git', :tag=>'v1.1.1' } 12 | s.source_files = 'Sources/DRKonamiGestureRecognizer.*' 13 | 14 | s.requires_arc = true 15 | end 16 | -------------------------------------------------------------------------------- /DRKonamiCode.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 304949CC1579A63C0045FB4B /* DRAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 304949C71579A63C0045FB4B /* DRAppDelegate.m */; }; 11 | 304949CD1579A63C0045FB4B /* DRKonamiGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 304949C91579A63C0045FB4B /* DRKonamiGestureRecognizer.m */; }; 12 | 304949CE1579A63C0045FB4B /* DRViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 304949CB1579A63C0045FB4B /* DRViewController.m */; }; 13 | 304949D21579A6670045FB4B /* DRViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 304949D11579A6670045FB4B /* DRViewController.xib */; }; 14 | 304949D51579A6910045FB4B /* nes.png in Resources */ = {isa = PBXBuildFile; fileRef = 304949D31579A6910045FB4B /* nes.png */; }; 15 | 304949D61579A6910045FB4B /* nes@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 304949D41579A6910045FB4B /* nes@2x.png */; }; 16 | 304949D81579A6B60045FB4B /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 304949D71579A6B60045FB4B /* main.m */; }; 17 | 305E5B8118DC6FCA00CE5892 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 305E5B8018DC6FCA00CE5892 /* Default-568h@2x.png */; }; 18 | 3098B2CD1504515300F743BD /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3098B2CC1504515300F743BD /* UIKit.framework */; }; 19 | 3098B2CF1504515300F743BD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3098B2CE1504515300F743BD /* Foundation.framework */; }; 20 | 3098B2D11504515300F743BD /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3098B2D01504515300F743BD /* CoreGraphics.framework */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 304949C61579A63C0045FB4B /* DRAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DRAppDelegate.h; sourceTree = ""; }; 25 | 304949C71579A63C0045FB4B /* DRAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DRAppDelegate.m; sourceTree = ""; }; 26 | 304949C81579A63C0045FB4B /* DRKonamiGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DRKonamiGestureRecognizer.h; sourceTree = ""; }; 27 | 304949C91579A63C0045FB4B /* DRKonamiGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DRKonamiGestureRecognizer.m; sourceTree = ""; }; 28 | 304949CA1579A63C0045FB4B /* DRViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DRViewController.h; sourceTree = ""; }; 29 | 304949CB1579A63C0045FB4B /* DRViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DRViewController.m; sourceTree = ""; }; 30 | 304949D11579A6670045FB4B /* DRViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DRViewController.xib; sourceTree = ""; }; 31 | 304949D31579A6910045FB4B /* nes.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = nes.png; sourceTree = ""; }; 32 | 304949D41579A6910045FB4B /* nes@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "nes@2x.png"; sourceTree = ""; }; 33 | 304949D71579A6B60045FB4B /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 304949DB1579A73A0045FB4B /* DRKonamiCode-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "DRKonamiCode-Info.plist"; sourceTree = ""; }; 35 | 304949DD1579A7560045FB4B /* DRKonamiCode-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "DRKonamiCode-Prefix.pch"; sourceTree = ""; }; 36 | 305E5B8018DC6FCA00CE5892 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 37 | 3098B2C81504515300F743BD /* DRKonamiCode.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DRKonamiCode.app; sourceTree = BUILT_PRODUCTS_DIR; }; 38 | 3098B2CC1504515300F743BD /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 39 | 3098B2CE1504515300F743BD /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 40 | 3098B2D01504515300F743BD /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 41 | /* End PBXFileReference section */ 42 | 43 | /* Begin PBXFrameworksBuildPhase section */ 44 | 3098B2C51504515300F743BD /* Frameworks */ = { 45 | isa = PBXFrameworksBuildPhase; 46 | buildActionMask = 2147483647; 47 | files = ( 48 | 3098B2CD1504515300F743BD /* UIKit.framework in Frameworks */, 49 | 3098B2CF1504515300F743BD /* Foundation.framework in Frameworks */, 50 | 3098B2D11504515300F743BD /* CoreGraphics.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | 304949C51579A63C0045FB4B /* Sources */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 304949D71579A6B60045FB4B /* main.m */, 61 | 304949C61579A63C0045FB4B /* DRAppDelegate.h */, 62 | 304949C71579A63C0045FB4B /* DRAppDelegate.m */, 63 | 304949C81579A63C0045FB4B /* DRKonamiGestureRecognizer.h */, 64 | 304949C91579A63C0045FB4B /* DRKonamiGestureRecognizer.m */, 65 | 304949CA1579A63C0045FB4B /* DRViewController.h */, 66 | 304949CB1579A63C0045FB4B /* DRViewController.m */, 67 | ); 68 | path = Sources; 69 | sourceTree = ""; 70 | }; 71 | 304949D01579A6670045FB4B /* Resources */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | 304949D31579A6910045FB4B /* nes.png */, 75 | 304949D41579A6910045FB4B /* nes@2x.png */, 76 | 304949D11579A6670045FB4B /* DRViewController.xib */, 77 | ); 78 | path = Resources; 79 | sourceTree = ""; 80 | }; 81 | 3098B2BD1504515200F743BD = { 82 | isa = PBXGroup; 83 | children = ( 84 | 305E5B8018DC6FCA00CE5892 /* Default-568h@2x.png */, 85 | 304949DD1579A7560045FB4B /* DRKonamiCode-Prefix.pch */, 86 | 304949DB1579A73A0045FB4B /* DRKonamiCode-Info.plist */, 87 | 304949C51579A63C0045FB4B /* Sources */, 88 | 304949D01579A6670045FB4B /* Resources */, 89 | 3098B2CB1504515300F743BD /* Frameworks */, 90 | 3098B2C91504515300F743BD /* Products */, 91 | ); 92 | sourceTree = ""; 93 | }; 94 | 3098B2C91504515300F743BD /* Products */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 3098B2C81504515300F743BD /* DRKonamiCode.app */, 98 | ); 99 | name = Products; 100 | sourceTree = ""; 101 | }; 102 | 3098B2CB1504515300F743BD /* Frameworks */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 3098B2CC1504515300F743BD /* UIKit.framework */, 106 | 3098B2CE1504515300F743BD /* Foundation.framework */, 107 | 3098B2D01504515300F743BD /* CoreGraphics.framework */, 108 | ); 109 | name = Frameworks; 110 | sourceTree = ""; 111 | }; 112 | /* End PBXGroup section */ 113 | 114 | /* Begin PBXNativeTarget section */ 115 | 3098B2C71504515300F743BD /* DRKonamiCode */ = { 116 | isa = PBXNativeTarget; 117 | buildConfigurationList = 3098B2E61504515300F743BD /* Build configuration list for PBXNativeTarget "DRKonamiCode" */; 118 | buildPhases = ( 119 | 3098B2C41504515300F743BD /* Sources */, 120 | 3098B2C51504515300F743BD /* Frameworks */, 121 | 3098B2C61504515300F743BD /* Resources */, 122 | ); 123 | buildRules = ( 124 | ); 125 | dependencies = ( 126 | ); 127 | name = DRKonamiCode; 128 | productName = DRKonamiCode; 129 | productReference = 3098B2C81504515300F743BD /* DRKonamiCode.app */; 130 | productType = "com.apple.product-type.application"; 131 | }; 132 | /* End PBXNativeTarget section */ 133 | 134 | /* Begin PBXProject section */ 135 | 3098B2BF1504515200F743BD /* Project object */ = { 136 | isa = PBXProject; 137 | attributes = { 138 | LastUpgradeCheck = 0500; 139 | ORGANIZATIONNAME = "CouchSurfing International"; 140 | }; 141 | buildConfigurationList = 3098B2C21504515200F743BD /* Build configuration list for PBXProject "DRKonamiCode" */; 142 | compatibilityVersion = "Xcode 3.2"; 143 | developmentRegion = English; 144 | hasScannedForEncodings = 0; 145 | knownRegions = ( 146 | en, 147 | ); 148 | mainGroup = 3098B2BD1504515200F743BD; 149 | productRefGroup = 3098B2C91504515300F743BD /* Products */; 150 | projectDirPath = ""; 151 | projectRoot = ""; 152 | targets = ( 153 | 3098B2C71504515300F743BD /* DRKonamiCode */, 154 | ); 155 | }; 156 | /* End PBXProject section */ 157 | 158 | /* Begin PBXResourcesBuildPhase section */ 159 | 3098B2C61504515300F743BD /* Resources */ = { 160 | isa = PBXResourcesBuildPhase; 161 | buildActionMask = 2147483647; 162 | files = ( 163 | 304949D21579A6670045FB4B /* DRViewController.xib in Resources */, 164 | 305E5B8118DC6FCA00CE5892 /* Default-568h@2x.png in Resources */, 165 | 304949D51579A6910045FB4B /* nes.png in Resources */, 166 | 304949D61579A6910045FB4B /* nes@2x.png in Resources */, 167 | ); 168 | runOnlyForDeploymentPostprocessing = 0; 169 | }; 170 | /* End PBXResourcesBuildPhase section */ 171 | 172 | /* Begin PBXSourcesBuildPhase section */ 173 | 3098B2C41504515300F743BD /* Sources */ = { 174 | isa = PBXSourcesBuildPhase; 175 | buildActionMask = 2147483647; 176 | files = ( 177 | 304949CC1579A63C0045FB4B /* DRAppDelegate.m in Sources */, 178 | 304949CD1579A63C0045FB4B /* DRKonamiGestureRecognizer.m in Sources */, 179 | 304949CE1579A63C0045FB4B /* DRViewController.m in Sources */, 180 | 304949D81579A6B60045FB4B /* main.m in Sources */, 181 | ); 182 | runOnlyForDeploymentPostprocessing = 0; 183 | }; 184 | /* End PBXSourcesBuildPhase section */ 185 | 186 | /* Begin XCBuildConfiguration section */ 187 | 3098B2E41504515300F743BD /* Debug */ = { 188 | isa = XCBuildConfiguration; 189 | buildSettings = { 190 | ALWAYS_SEARCH_USER_PATHS = NO; 191 | CLANG_WARN_BOOL_CONVERSION = YES; 192 | CLANG_WARN_CONSTANT_CONVERSION = YES; 193 | CLANG_WARN_EMPTY_BODY = YES; 194 | CLANG_WARN_ENUM_CONVERSION = YES; 195 | CLANG_WARN_INT_CONVERSION = YES; 196 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 197 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 198 | COPY_PHASE_STRIP = NO; 199 | GCC_C_LANGUAGE_STANDARD = gnu99; 200 | GCC_DYNAMIC_NO_PIC = NO; 201 | GCC_OPTIMIZATION_LEVEL = 0; 202 | GCC_PREPROCESSOR_DEFINITIONS = ( 203 | "DEBUG=1", 204 | "$(inherited)", 205 | ); 206 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 207 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 208 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 209 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 210 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 211 | GCC_WARN_UNDECLARED_SELECTOR = YES; 212 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 213 | GCC_WARN_UNUSED_FUNCTION = YES; 214 | GCC_WARN_UNUSED_VARIABLE = YES; 215 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 216 | ONLY_ACTIVE_ARCH = YES; 217 | SDKROOT = iphoneos; 218 | }; 219 | name = Debug; 220 | }; 221 | 3098B2E51504515300F743BD /* Release */ = { 222 | isa = XCBuildConfiguration; 223 | buildSettings = { 224 | ALWAYS_SEARCH_USER_PATHS = NO; 225 | CLANG_WARN_BOOL_CONVERSION = YES; 226 | CLANG_WARN_CONSTANT_CONVERSION = YES; 227 | CLANG_WARN_EMPTY_BODY = YES; 228 | CLANG_WARN_ENUM_CONVERSION = YES; 229 | CLANG_WARN_INT_CONVERSION = YES; 230 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 231 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 232 | COPY_PHASE_STRIP = YES; 233 | GCC_C_LANGUAGE_STANDARD = gnu99; 234 | GCC_VERSION = com.apple.compilers.llvm.clang.1_0; 235 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 236 | GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; 237 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 238 | GCC_WARN_UNDECLARED_SELECTOR = YES; 239 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 240 | GCC_WARN_UNUSED_FUNCTION = YES; 241 | GCC_WARN_UNUSED_VARIABLE = YES; 242 | IPHONEOS_DEPLOYMENT_TARGET = 5.0; 243 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 244 | SDKROOT = iphoneos; 245 | VALIDATE_PRODUCT = YES; 246 | }; 247 | name = Release; 248 | }; 249 | 3098B2E71504515300F743BD /* Debug */ = { 250 | isa = XCBuildConfiguration; 251 | buildSettings = { 252 | CLANG_ENABLE_OBJC_ARC = YES; 253 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 254 | GCC_PREFIX_HEADER = "DRKonamiCode-Prefix.pch"; 255 | INFOPLIST_FILE = "DRKonamiCode-Info.plist"; 256 | PRODUCT_NAME = "$(TARGET_NAME)"; 257 | WRAPPER_EXTENSION = app; 258 | }; 259 | name = Debug; 260 | }; 261 | 3098B2E81504515300F743BD /* Release */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | CLANG_ENABLE_OBJC_ARC = YES; 265 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 266 | GCC_PREFIX_HEADER = "DRKonamiCode-Prefix.pch"; 267 | INFOPLIST_FILE = "DRKonamiCode-Info.plist"; 268 | PRODUCT_NAME = "$(TARGET_NAME)"; 269 | WRAPPER_EXTENSION = app; 270 | }; 271 | name = Release; 272 | }; 273 | /* End XCBuildConfiguration section */ 274 | 275 | /* Begin XCConfigurationList section */ 276 | 3098B2C21504515200F743BD /* Build configuration list for PBXProject "DRKonamiCode" */ = { 277 | isa = XCConfigurationList; 278 | buildConfigurations = ( 279 | 3098B2E41504515300F743BD /* Debug */, 280 | 3098B2E51504515300F743BD /* Release */, 281 | ); 282 | defaultConfigurationIsVisible = 0; 283 | defaultConfigurationName = Release; 284 | }; 285 | 3098B2E61504515300F743BD /* Build configuration list for PBXNativeTarget "DRKonamiCode" */ = { 286 | isa = XCConfigurationList; 287 | buildConfigurations = ( 288 | 3098B2E71504515300F743BD /* Debug */, 289 | 3098B2E81504515300F743BD /* Release */, 290 | ); 291 | defaultConfigurationIsVisible = 0; 292 | defaultConfigurationName = Release; 293 | }; 294 | /* End XCConfigurationList section */ 295 | }; 296 | rootObject = 3098B2BF1504515200F743BD /* Project object */; 297 | } 298 | -------------------------------------------------------------------------------- /DRKonamiCode.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objectiveSee/DRKonamiCode/98a00b3b4b57601e0b0cfb9bb783159297cb83f2/Default-568h@2x.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | DRKonamiCode 2 | ============ 3 |

4 | DRKonamiCode 5 |

6 | 7 | [Konami code](http://en.wikipedia.org/wiki/Konami_Code) gesture recognizer for iOS. The recognizer is a subclass of UIGestureRecognizer has can be used in the same way as any other recognizer. Swipe gestures correspond to the Up/Down/Left/Right parts of the sequence. An optional feature allows you to implement a custom B+A+Enter action. 8 | 9 | Contact me via Github issue or comment. 10 | 11 | ### Installation with CocoaPods 12 | 13 | [CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like AFNetworking in your projects. See the ["Getting Started" guide for more information](https://github.com/AFNetworking/AFNetworking/wiki/Getting-Started-with-AFNetworking). 14 | 15 | ```ruby 16 | pod "DRKonamiCode", "~> 1.1.0" 17 | ``` 18 | 19 | If you don't use CocoaPods, then add DRKonamiGestureRecognizer.h and DRKonamiGestureRecognizer.m to your project. 20 | 21 | 22 | ### Using DRKonamiCode in your App ### 23 | 24 | Add the gesture recognizer to a UIView using the following code. 25 | 26 | ```objective-c 27 | 28 | #import "DRKonamiGestureRecognizer.h" 29 | 30 | - (void)addKonami 31 | { 32 | konami = [[DRKonamiGestureRecognizer alloc] initWithTarget:self action:@selector(_konamiHappened:)]; 33 | [self.view addGestureRecognizer:konami]; 34 | } 35 | 36 | - (void)_konamiHappened:(DRKonamiGestureRecognizer *)recognizer 37 | { 38 | // NOTE: Test the state to make sure the recognizer is finished. 39 | if ( [recognizer konamiState] == DRKonamiGestureStateRecognized ) { 40 | NSLog(@"Konami Code Recognized!"); 41 | } 42 | } 43 | 44 | ``` 45 | 46 | ### B+A+Unlock (OPTIONAL) ### 47 | 48 | Optionally, you can require the user to enter B+A+Enter in order for the gesture to be recognized. You will need to implement the DRKonamiGestureProtocol which has required methods that let your UI respond to the request for the A, B, or Enter action. If you are not using the B+A+Enter feature than you do not need to set the recognizer's delegate. 49 | 50 | ```objective-c 51 | 52 | - (void)addKonami 53 | { 54 | konami = [[DRKonamiGestureRecognizer alloc] initWithTarget:self action:@selector(_konamiHappened:)]; 55 | [konami setKonamiDelegate:self]; 56 | [konami setRequiresABEnterToUnlock:YES]; 57 | [self.view addGestureRecognizer:konami]; 58 | } 59 | 60 | - (void)_konamiHappened:(DRKonamiGestureRecognizer *)recognizer 61 | { 62 | NSLog(@"Konami Code Recognized!"); 63 | } 64 | 65 | #pragma mark - 66 | #pragma mark DRKonamiGestureProtocol 67 | 68 | - (void)DRKonamiGestureRecognizerNeedsABEnterSequence:(DRKonamiGestureRecognizer*)gesture 69 | { 70 | /// your code here. 71 | } 72 | 73 | - (void)DRKonamiGestureRecognizer:(DRKonamiGestureRecognizer*)gesture didFinishNeedingABEnterSequenceWithError:(BOOL)error 74 | { 75 | /// your code here. 76 | } 77 | ``` 78 | 79 | ### DRKonamiGestureProtocol ### 80 | 81 | The DRKonamiGestureProtocol protocol is required only if you are using the B+A+Enter feature. The recognizer will inform its delegate when the B+A+Enter sequence is needed and when the sequence is no longer needed (due to gesture failing or succeeding). 82 | 83 | ### Tips ### 84 | 85 | * TIP 1: NSLog() statements are disabled inside of DRKonamiGestureRecognizer.m. You can enable them at the top of the file and then the console will print the konami state. 86 | * TIP 2: Practice actually doing the konami gesture with the sample app. Some people have a hard time figuring out how to actually get it going. 87 | -------------------------------------------------------------------------------- /Resources/DRViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1280 5 | 14A361c 6 | 6245 7 | 1339 8 | 755.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 6238 12 | 13 | 14 | IBProxyObject 15 | IBUIButton 16 | IBUIImageView 17 | IBUILabel 18 | IBUISwitch 19 | IBUIView 20 | 21 | 22 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 23 | 24 | 25 | PluginDependencyRecalculationVersion 26 | 27 | 28 | 29 | 30 | IBFilesOwner 31 | IBCocoaTouchFramework 32 | 33 | 34 | IBFirstResponder 35 | IBCocoaTouchFramework 36 | 37 | 38 | 39 | 274 40 | 41 | 42 | 43 | 292 44 | 45 | 46 | 47 | 256 48 | {270, 138} 49 | 50 | 51 | 52 | NO 53 | YES 54 | 4 55 | YES 56 | IBCocoaTouchFramework 57 | 58 | NSImage 59 | nes.png 60 | 61 | 62 | 63 | 64 | 292 65 | {270, 138} 66 | 67 | 68 | 69 | _NS:225 70 | 71 | 3 72 | MCAwAA 73 | 74 | NO 75 | IBCocoaTouchFramework 76 | 0 77 | 0 78 | 79 | 1 80 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 81 | 82 | 83 | 3 84 | MQA 85 | 86 | 87 | 3 88 | MC41AA 89 | 90 | 91 | 2 92 | 15 93 | 94 | 95 | HelveticaNeue-Bold 96 | 15 97 | 16 98 | 99 | 100 | 101 | 102 | 292 103 | {{209, 73}, {28, 28}} 104 | 105 | 106 | 107 | _NS:225 108 | NO 109 | IBCocoaTouchFramework 110 | 0 111 | 0 112 | 113 | 1 114 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 292 124 | {{94, 73}, {72, 28}} 125 | 126 | 127 | 128 | _NS:225 129 | NO 130 | IBCocoaTouchFramework 131 | 0 132 | 0 133 | 134 | 1 135 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 292 145 | {{176, 73}, {28, 28}} 146 | 147 | 148 | 149 | _NS:225 150 | NO 151 | IBCocoaTouchFramework 152 | 0 153 | 0 154 | 155 | 1 156 | MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | {{33, 130}, {270, 138}} 165 | 166 | 167 | 168 | _NS:10 169 | 170 | IBCocoaTouchFramework 171 | 172 | 173 | 174 | 292 175 | {{200, 20}, {94, 27}} 176 | 177 | 178 | 179 | _NS:9 180 | NO 181 | IBCocoaTouchFramework 182 | 0 183 | 0 184 | YES 185 | 186 | 187 | 188 | 292 189 | {{37, 23}, {151, 21}} 190 | 191 | 192 | 193 | _NS:9 194 | NO 195 | YES 196 | 7 197 | NO 198 | IBCocoaTouchFramework 199 | B+A+Enter required 200 | 201 | 1 202 | MCAwIDAAA 203 | darkTextColor 204 | 205 | 206 | 0 207 | 10 208 | 209 | 1 210 | 17 211 | 212 | 213 | HelveticaNeue 214 | 17 215 | 16 216 | 217 | YES 218 | 219 | 220 | 221 | 292 222 | {{0, 55}, {320, 40}} 223 | 224 | 225 | 226 | _NS:9 227 | NO 228 | YES 229 | 7 230 | NO 231 | IBCocoaTouchFramework 232 | Status 233 | 234 | 235 | 0 236 | 10 237 | 1 238 | 239 | 1 240 | 25 241 | 242 | 243 | HelveticaNeue 244 | 25 245 | 16 246 | 247 | YES 248 | 249 | 250 | 251 | 292 252 | {{0, 89}, {320, 40}} 253 | 254 | 255 | 256 | _NS:9 257 | NO 258 | YES 259 | 7 260 | NO 261 | IBCocoaTouchFramework 262 | ↑↑↓↓←→←→BA 263 | 264 | 3 265 | MC4zMzMzMzMzMzMzAA 266 | 267 | 268 | 0 269 | 10 270 | 1 271 | 272 | 273 | YES 274 | 275 | 276 | 277 | 293 278 | {{0, 342}, {320, 118}} 279 | 280 | 281 | _NS:9 282 | NO 283 | YES 284 | 7 285 | NO 286 | IBCocoaTouchFramework 287 | Test it out! Start with a swipe up. You will see arrow characters that indicate your progress 288 | 289 | 290 | 0 291 | 0 292 | 1 293 | 294 | 295 | NO 296 | 320 297 | 298 | 299 | {{0, 20}, {320, 460}} 300 | 301 | 302 | 303 | 304 | 3 305 | MC45MgA 306 | 307 | NO 308 | 309 | 310 | IBUISimulatedFreeformSizeMetricsSentinel 311 | Freeform 312 | 313 | IBCocoaTouchFramework 314 | 315 | 316 | 317 | 318 | 319 | 320 | view 321 | 322 | 323 | 324 | 7 325 | 326 | 327 | 328 | NESControllerView 329 | 330 | 331 | 332 | 24 333 | 334 | 335 | 336 | statusLabel 337 | 338 | 339 | 340 | 26 341 | 342 | 343 | 344 | guideLabel 345 | 346 | 347 | 348 | 30 349 | 350 | 351 | 352 | aButtonWasPressed: 353 | 354 | 355 | 7 356 | 357 | 13 358 | 359 | 360 | 361 | bButtonWasPressed: 362 | 363 | 364 | 7 365 | 366 | 14 367 | 368 | 369 | 370 | enterButtonWasPressed: 371 | 372 | 373 | 7 374 | 375 | 15 376 | 377 | 378 | 379 | nesControllerWasPressed: 380 | 381 | 382 | 7 383 | 384 | 19 385 | 386 | 387 | 388 | advancedModeSwitchValueChanged: 389 | 390 | 391 | 13 392 | 393 | 22 394 | 395 | 396 | 397 | 398 | 399 | 0 400 | 401 | 402 | 403 | 404 | 405 | -1 406 | 407 | 408 | File's Owner 409 | 410 | 411 | -2 412 | 413 | 414 | 415 | 416 | 6 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 11 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 8 442 | 443 | 444 | 445 | 446 | 10 447 | 448 | 449 | 450 | 451 | 9 452 | 453 | 454 | 455 | 456 | 16 457 | 458 | 459 | 460 | 461 | 17 462 | 463 | 464 | 465 | 466 | 20 467 | 468 | 469 | 470 | 471 | 21 472 | 473 | 474 | 475 | 476 | 25 477 | 478 | 479 | 480 | 481 | 27 482 | 483 | 484 | 485 | 486 | 29 487 | 488 | 489 | 490 | 491 | 492 | 493 | DRViewController 494 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 495 | UIResponder 496 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 497 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 498 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 499 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 500 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 501 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 502 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 503 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 504 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 505 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 506 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 507 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 508 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 509 | 510 | 511 | 512 | 513 | 514 | 30 515 | 516 | 517 | 518 | 519 | DRViewController 520 | UIViewController 521 | 522 | id 523 | id 524 | id 525 | id 526 | id 527 | 528 | 529 | 530 | aButtonWasPressed: 531 | id 532 | 533 | 534 | advancedModeSwitchValueChanged: 535 | id 536 | 537 | 538 | bButtonWasPressed: 539 | id 540 | 541 | 542 | enterButtonWasPressed: 543 | id 544 | 545 | 546 | nesControllerWasPressed: 547 | id 548 | 549 | 550 | 551 | UIView 552 | UILabel 553 | UILabel 554 | 555 | 556 | 557 | NESControllerView 558 | UIView 559 | 560 | 561 | guideLabel 562 | UILabel 563 | 564 | 565 | statusLabel 566 | UILabel 567 | 568 | 569 | 570 | IBProjectSource 571 | ../Sources/DRViewController.h 572 | 573 | 574 | 575 | DRViewController 576 | 577 | id 578 | id 579 | id 580 | id 581 | id 582 | 583 | 584 | 585 | aButtonWasPressed: 586 | id 587 | 588 | 589 | advancedModeSwitchValueChanged: 590 | id 591 | 592 | 593 | bButtonWasPressed: 594 | id 595 | 596 | 597 | enterButtonWasPressed: 598 | id 599 | 600 | 601 | nesControllerWasPressed: 602 | id 603 | 604 | 605 | 606 | IBProjectSource 607 | ../Sources/DRViewController.m 608 | 609 | 610 | 611 | 612 | 613 | UIButton 614 | UIControl 615 | 616 | IBFrameworkSource 617 | UIKit.framework/Headers/UIButton.h 618 | 619 | 620 | 621 | UIControl 622 | UIView 623 | 624 | IBFrameworkSource 625 | UIKit.framework/Headers/UIControl.h 626 | 627 | 628 | 629 | UIGestureRecognizer 630 | NSObject 631 | 632 | IBFrameworkSource 633 | UIKit.framework/Headers/UIGestureRecognizer.h 634 | 635 | 636 | 637 | UIImageView 638 | UIView 639 | 640 | IBFrameworkSource 641 | UIKit.framework/Headers/UIImageView.h 642 | 643 | 644 | 645 | UILabel 646 | UIView 647 | 648 | IBFrameworkSource 649 | UIKit.framework/Headers/UILabel.h 650 | 651 | 652 | 653 | UIResponder 654 | NSObject 655 | 656 | IBFrameworkSource 657 | UIKit.framework/Headers/UIResponder.h 658 | 659 | 660 | 661 | UISearchBar 662 | UIView 663 | 664 | IBFrameworkSource 665 | UIKit.framework/Headers/UISearchBar.h 666 | 667 | 668 | 669 | UISearchDisplayController 670 | NSObject 671 | 672 | IBFrameworkSource 673 | UIKit.framework/Headers/UISearchDisplayController.h 674 | 675 | 676 | 677 | UISwitch 678 | UIControl 679 | 680 | IBFrameworkSource 681 | UIKit.framework/Headers/UISwitch.h 682 | 683 | 684 | 685 | UIView 686 | UIResponder 687 | 688 | IBFrameworkSource 689 | UIKit.framework/Headers/UIView.h 690 | 691 | 692 | 693 | UIViewController 694 | UIResponder 695 | 696 | IBFrameworkSource 697 | UIKit.framework/Headers/UIViewController.h 698 | 699 | 700 | 701 | 702 | 0 703 | IBCocoaTouchFramework 704 | NO 705 | 706 | com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS 707 | 708 | 709 | 710 | com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 711 | 712 | 713 | YES 714 | 3 715 | 716 | nes.png 717 | {270, 138} 718 | 719 | 720 | 721 | -------------------------------------------------------------------------------- /Resources/nes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objectiveSee/DRKonamiCode/98a00b3b4b57601e0b0cfb9bb783159297cb83f2/Resources/nes.png -------------------------------------------------------------------------------- /Resources/nes@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/objectiveSee/DRKonamiCode/98a00b3b4b57601e0b0cfb9bb783159297cb83f2/Resources/nes@2x.png -------------------------------------------------------------------------------- /Sources/DRAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // DRAppDelegate.h 3 | // DRKonamiCode 4 | // 5 | // Created by Danny Ricciotti on 3/4/12. 6 | // 7 | 8 | @class DRViewController; 9 | 10 | @interface DRAppDelegate : UIResponder 11 | 12 | @property (strong, nonatomic) UIWindow *window; 13 | 14 | @property (strong, nonatomic) DRViewController *viewController; 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /Sources/DRAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // DRAppDelegate.m 3 | // DRKonamiCode 4 | // 5 | // Created by Danny Ricciotti on 3/4/12. 6 | // 7 | 8 | #import "DRAppDelegate.h" 9 | #import "DRViewController.h" 10 | 11 | @implementation DRAppDelegate 12 | 13 | @synthesize window = _window; 14 | @synthesize viewController = _viewController; 15 | 16 | 17 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 18 | { 19 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 20 | 21 | self.viewController = [[DRViewController alloc] initWithNibName:@"DRViewController" bundle:nil]; 22 | self.window.rootViewController = self.viewController; 23 | [self.window makeKeyAndVisible]; 24 | return YES; 25 | } 26 | 27 | - (void)applicationWillResignActive:(UIApplication *)application 28 | { 29 | /* 30 | 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. 31 | 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. 32 | */ 33 | } 34 | 35 | - (void)applicationDidEnterBackground:(UIApplication *)application 36 | { 37 | /* 38 | 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. 39 | If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 40 | */ 41 | } 42 | 43 | - (void)applicationWillEnterForeground:(UIApplication *)application 44 | { 45 | /* 46 | 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. 47 | */ 48 | } 49 | 50 | - (void)applicationDidBecomeActive:(UIApplication *)application 51 | { 52 | /* 53 | 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. 54 | */ 55 | } 56 | 57 | - (void)applicationWillTerminate:(UIApplication *)application 58 | { 59 | /* 60 | Called when the application is about to terminate. 61 | Save data if appropriate. 62 | See also applicationDidEnterBackground:. 63 | */ 64 | } 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /Sources/DRKonamiGestureRecognizer.h: -------------------------------------------------------------------------------- 1 | // 2 | // DRKonamiGestureRecognizer.h 3 | // DRKonamiCode 4 | // 5 | // Created by Danny Ricciotti on 3/4/12. 6 | // 7 | 8 | /** 9 | The delegate (DRKonamiGestureProtocol) is optional! If you are using the delegate, however, then you must implement all of the required methods. The delegate is only needed if you wish to include A+B+Enter as the final steps of the Konami sequence. 10 | The Konami Gesture protocol implements communication between the gesture recognizer and the delegate when the A+B+Enter action is required to complete the gesture. If the A+B+Enter sequence is not used then none of the protocol methods are required. 11 | */ 12 | @class DRKonamiGestureRecognizer; 13 | @protocol DRKonamiGestureProtocol 14 | @required 15 | 16 | /** 17 | Informs the delegate that the gesture recognizer has reached the point where the B+A+Enter sequence is requied to complete the gesture. This is when your code would add UI on the screen to represent the B+A+Enter options. 18 | */ 19 | - (void)DRKonamiGestureRecognizerNeedsABEnterSequence:(DRKonamiGestureRecognizer*)gesture; 20 | 21 | /** 22 | Informs the delegate that the gesture recognizer no longers requires the B+A+Enter sequence. This will happen either because the sequence has succeeded or failed. This is where you can remove the B+A+Enter options from the screen. 23 | */ 24 | - (void)DRKonamiGestureRecognizer:(DRKonamiGestureRecognizer*)gesture didFinishNeedingABEnterSequenceWithError:(BOOL)error; 25 | 26 | @end 27 | 28 | ////////////////////////////////////////////////////////////////////// 29 | 30 | /** 31 | Konami code states. Mostly used internally, but you will need to use 'DRKonamiGestureStateRecognized'. 32 | */ 33 | typedef NS_ENUM(NSInteger, DRKonamiGestureState) 34 | { 35 | DRKonamiGestureStateNone = 0, 36 | DRKonamiGestureStateBegan, 37 | DRKonamiGestureStateUp1, 38 | DRKonamiGestureStateUp2, 39 | DRKonamiGestureStateDown1, 40 | DRKonamiGestureStateDown2, 41 | DRKonamiGestureStateLeft1, 42 | DRKonamiGestureStateRight1, 43 | DRKonamiGestureStateLeft2, 44 | DRKonamiGestureStateRight2, // 9 45 | DRKonamiGestureStateB, // 10 46 | DRKonamiGestureStateA, // 11 47 | DRKonamiGestureStateRecognized // 12 48 | }; 49 | 50 | /** 51 | @class DRKonamiGestureRecognizer 52 | @brief A custom UIGestureRecognizer which recognized the Konami Code. 53 | @todo Reset the state of self.konamiState on gesture fails due to timeout between swipes in sequence. 54 | */ 55 | @interface DRKonamiGestureRecognizer : UIGestureRecognizer 56 | 57 | /** 58 | Indicates whether the konami sequence requires B+A+Enter to finish the sequence. If NO then the sequence is finished successfully after the final RIGHT gesture. Default value is NO. 59 | */ 60 | @property (nonatomic, readwrite) BOOL requiresABEnterToUnlock; 61 | 62 | /** 63 | The current state of the konami gesture. 64 | */ 65 | @property (nonatomic, readonly) DRKonamiGestureState konamiState; 66 | 67 | /** 68 | The delegate of the gesture. If the delegate is set then the delegate must conform to DRKonamiGestureRecognizer. The delegate does not need to be used if requiresABEnterToUnlock is set to NO. 69 | */ 70 | @property (nonatomic, weak, readwrite) id konamiDelegate; 71 | 72 | /** 73 | Methods used by the delegate (if delegate exists) to specify when the A, B, and Enter actions occur. 74 | */ 75 | - (void) AButtonAction; 76 | - (void) BButtonAction; 77 | - (void) enterButtonAction; 78 | 79 | /** 80 | Cancels the gesture recognizer from waiting on the A+B+Enter sequence. Also sets the gesture recognizer state to failed. 81 | Used by the delegate (if delegate exists). 82 | */ 83 | - (void) cancelSequence; 84 | 85 | @end 86 | -------------------------------------------------------------------------------- /Sources/DRKonamiGestureRecognizer.m: -------------------------------------------------------------------------------- 1 | // 2 | // DRKonamiGestureRecognizer.m 3 | // DRKonamiCode 4 | // 5 | // Created by Danny Ricciotti on 3/4/12. 6 | // 7 | 8 | #import "DRKonamiGestureRecognizer.h" 9 | #import // required for subclassing UIGestureRecognizer 10 | 11 | /////////////////////////////////////////////////////////////// 12 | 13 | // Line below disables logging if uncommented 14 | #define NSLog(...); 15 | 16 | // Constant Declarations 17 | static const CGFloat kKonamiSwipeDistanceTolerance = 50.0f; // Max tolerence in direction perpendicular to expected swipe state 18 | static const CGFloat kKonamiSwipeDistanceMin = 50.0f; // Min distance to detect a swipe gesture 19 | static const NSTimeInterval kKonamiGestureMaxTimeBetweenGestures = 1.0f; // The max time allowed between swipe gestures. 20 | static const NSTimeInterval kKonamiGestureMaxTimeDuringGesture = 1.0f; // The max time allowed during swipe gestures. 21 | 22 | /////////////////////////////////////////////////////////////// 23 | 24 | // Some helper functions 25 | void getCheckValuesAfterTouchesEnded(DRKonamiGestureState konamiState, BOOL* pCheckXLeft, BOOL* pCheckXRight, BOOL* pCheckYUp, BOOL* pCheckYDown); 26 | 27 | void getCheckValuesDuringDrag(DRKonamiGestureState konamiState, BOOL* pCheckX, BOOL* pCheckY); 28 | 29 | 30 | /////////////////////////////////////////////////////////////// 31 | 32 | @interface DRKonamiGestureRecognizer () 33 | @property (nonatomic, readwrite) DRKonamiGestureState konamiState; 34 | @property (nonatomic, strong, readwrite) NSDate* lastGestureDate; 35 | @property (nonatomic, readwrite) CGPoint lastGestureStartPoint; 36 | @end 37 | 38 | /////////////////////////////////////////////////////////////// 39 | 40 | @implementation DRKonamiGestureRecognizer 41 | 42 | #pragma mark - 43 | #pragma mark Lifecycle 44 | 45 | - (id) initWithTarget:(id)target action:(SEL)action 46 | { 47 | self = [super initWithTarget:target action:action]; 48 | if ( self != nil ) 49 | { 50 | self.konamiState = DRKonamiGestureStateNone; 51 | self.lastGestureDate = [NSDate new]; 52 | self.lastGestureStartPoint = CGPointZero; 53 | self.requiresABEnterToUnlock = NO; 54 | self.cancelsTouchesInView = NO; 55 | } 56 | return self; 57 | } 58 | 59 | #pragma mark - 60 | #pragma mark Touches 61 | 62 | - (void)reset 63 | { 64 | self.konamiState = DRKonamiGestureStateNone; 65 | } 66 | 67 | - (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer 68 | { 69 | // basically we don't prevent any other recognizer from being recoginzed. 70 | // TODO: Explore the idea of returning YES if self.konamiState != DRKonamiGestureStateNone. 71 | return NO; 72 | } 73 | 74 | - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 75 | { 76 | // Fail when more than 1 finger detected. 77 | if ([[event touchesForGestureRecognizer:self] count] > 1) 78 | { 79 | [self setState:UIGestureRecognizerStateFailed]; 80 | } 81 | else 82 | { 83 | if ( self.state == UIGestureRecognizerStateChanged ) 84 | { 85 | // If an existing touch already exists (ie. state is UIGestureRecognizerStateChanged) then see if the pause between gestures took too long. However, if the konami code state has reached DRKonamiGestureStateRight2 then the timeout between gestures no longer applies. DRKonamiGestureRecognizer is either waiting for A+B+Enter or a logic error has occured. 86 | if ( self.konamiState < DRKonamiGestureStateRight2 ) 87 | { 88 | // Check whether the time between now and the previous gesture was too long. 89 | NSDate* now = [NSDate date]; 90 | if ( [now timeIntervalSinceDate:self.lastGestureDate] > kKonamiGestureMaxTimeBetweenGestures ) 91 | { 92 | NSLog(@"Waited too long between gestures. Re-starting the konami sequence."); 93 | self.konamiState = DRKonamiGestureStateBegan; 94 | } 95 | } 96 | } 97 | else if ( self.state == UIGestureRecognizerStatePossible ) // default beginning state. 98 | { 99 | NSLog(@"Starting the konami sequence"); 100 | [self setState:UIGestureRecognizerStateBegan]; 101 | self.konamiState = DRKonamiGestureStateBegan; 102 | } 103 | else 104 | { 105 | // unexpected case. Handle with failure and return. 106 | NSLog(@"Invalid UIGestureRecognizerState: %d", self.state); 107 | [self setState:UIGestureRecognizerStateFailed]; 108 | return; 109 | } 110 | 111 | self.lastGestureDate = [NSDate new]; 112 | UITouch *touch = [touches anyObject]; 113 | self.lastGestureStartPoint = [touch locationInView:self.view]; 114 | } 115 | } 116 | 117 | /** 118 | Determine whether the gesture is still happening during a swipe event. 119 | */ 120 | - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 121 | { 122 | if ( self.konamiState >= DRKonamiGestureStateRight2 ) 123 | { 124 | // in this case the touch-based part of the sequence is done. We either have recognized Konami or are waiting on the B+A inputs. 125 | return; 126 | } 127 | 128 | // Check whether the gesture is being completed fast enough 129 | NSDate* now = [NSDate date]; 130 | if ( [now timeIntervalSinceDate:self.lastGestureDate] > kKonamiGestureMaxTimeDuringGesture ) 131 | { 132 | NSLog(@"Failed to swipe quick enough!"); 133 | [self setState:UIGestureRecognizerStateFailed]; 134 | return; 135 | } 136 | 137 | // Check if user has dragged finger too far away from the gesture axis 138 | BOOL checkY = NO; 139 | BOOL checkX = NO; 140 | getCheckValuesDuringDrag(self.konamiState + 1, &checkX, &checkY); // use the next konami state since we are detecting that one. 141 | 142 | // TODO add timeout on swipe gestures 143 | 144 | // Check if the X and/or Y distance of the swipe was so far that the gesture if considered failed 145 | if (( checkX == YES) || (checkY == YES)) 146 | { 147 | // Only 1 touch object is possible. 148 | BOOL cancelGesture = NO; 149 | UITouch *touch = [touches anyObject]; 150 | UIView *view = [self view]; 151 | CGPoint currentTouchPoint = [touch locationInView:view]; 152 | 153 | if ( checkX == YES ) 154 | { 155 | CGFloat xdifference = fabs( currentTouchPoint.x - self.lastGestureStartPoint.x ); 156 | if ( xdifference > kKonamiSwipeDistanceTolerance ) 157 | { 158 | // finger moved too far (in the X direction) from the expected vertical swipe. 159 | NSLog(@"Cancelling gesture. Xdifference = %2.2f", xdifference); 160 | cancelGesture = YES; 161 | } 162 | } 163 | else 164 | { 165 | // CheckY == YES 166 | CGFloat ydifference = fabs( currentTouchPoint.y - self.lastGestureStartPoint.y ); 167 | if ( ydifference > kKonamiSwipeDistanceTolerance ) 168 | { 169 | // finger moved too far (in the Y direction) from the expected horizontal swipe. 170 | NSLog(@"Cancelling gesture. Ydifference = %2.2f", ydifference); 171 | cancelGesture = YES; 172 | } 173 | } 174 | if ( cancelGesture == YES ) 175 | { 176 | [self setState:UIGestureRecognizerStateFailed]; // Use cancelled or failed state? 177 | } 178 | } 179 | } 180 | 181 | /** 182 | At the end of each swipe event determine if the gesture failed or not. 183 | */ 184 | - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 185 | { 186 | if ( self.konamiState >= DRKonamiGestureStateRight2 ) 187 | { 188 | // if in DRKonamiGestureStateRight2 or higher than B+A sequence is being waited upon. We no longer are concerned with touch gestures. 189 | return; 190 | } 191 | 192 | // Perform final check to make sure a tap was not misinterpreted. 193 | if ( self.state != UIGestureRecognizerStateChanged ) { 194 | 195 | NSLog(@"Gesture failed. touchesEnded state is not UIGestureRecognizerStateChanged"); 196 | [self setState:UIGestureRecognizerStateFailed]; 197 | return; 198 | } 199 | 200 | // Check whether the correct gesture happened 201 | BOOL checkYUp = NO; 202 | BOOL checkYDown = NO; 203 | BOOL checkXLeft = NO; 204 | BOOL checkXRight = NO; 205 | getCheckValuesAfterTouchesEnded(self.konamiState + 1, &checkXLeft, &checkXRight, &checkYUp, &checkYDown); 206 | if ( checkXLeft || checkXRight || checkYDown || checkYUp ) 207 | { 208 | // Only 1 touch object is possible. 209 | BOOL cancelGesture = NO; 210 | UITouch *touch = [touches anyObject]; 211 | UIView *view = [self view]; 212 | CGPoint currentTouchPoint = [touch locationInView:view]; 213 | if ( checkXLeft || checkXRight ) 214 | { 215 | CGFloat xdifference = currentTouchPoint.x - self.lastGestureStartPoint.x; 216 | if ( (checkXLeft == YES) && (xdifference < -1 * kKonamiSwipeDistanceMin) ) 217 | { 218 | NSLog(@"Konami X-Left passed!"); 219 | } 220 | else if ( (checkXRight == YES) && (xdifference > kKonamiSwipeDistanceMin) ) 221 | { 222 | NSLog(@"Konami X-Right passed!"); 223 | } 224 | else 225 | { 226 | NSLog(@"Konami X failed!. xdifference = %2.2f", xdifference); 227 | cancelGesture = YES; 228 | } 229 | } 230 | else 231 | { 232 | // checkYUP or checkYDown 233 | CGFloat ydifference = currentTouchPoint.y - self.lastGestureStartPoint.y; 234 | if ( (checkYUp == YES) && (ydifference < -1 * kKonamiSwipeDistanceMin) ) 235 | { 236 | NSLog(@"Konami Y-Up passed!"); 237 | } 238 | else if ( (checkYDown == YES) && (ydifference > kKonamiSwipeDistanceMin) ) 239 | { 240 | NSLog(@"Konami Y-Down passed!"); 241 | } 242 | else 243 | { 244 | NSLog(@"Konami Y failed!. ydifference = %2.2f", ydifference); 245 | cancelGesture = YES; 246 | } 247 | } 248 | if ( cancelGesture == YES ) 249 | { 250 | NSLog(@"Konami Failed on state %d", self.konamiState); 251 | [self setState:UIGestureRecognizerStateFailed]; 252 | return; 253 | } 254 | } 255 | 256 | self.konamiState++; 257 | self.lastGestureDate = [NSDate new]; 258 | 259 | [self setState:UIGestureRecognizerStateChanged]; 260 | 261 | if ( self.konamiState >= DRKonamiGestureStateRight2 ) 262 | { 263 | // if we need B+A+Enter to finish, then do so. Else, gesture is success. 264 | if ( self.requiresABEnterToUnlock == YES ) 265 | { 266 | if ( self.konamiDelegate == nil ) 267 | { 268 | NSLog(@"Warning: Konami Gesture delegate was not set."); 269 | [self setState:UIGestureRecognizerStateFailed]; 270 | return; 271 | } 272 | [self.konamiDelegate DRKonamiGestureRecognizerNeedsABEnterSequence:self]; 273 | } 274 | else 275 | { 276 | // Gesture complete! 277 | NSLog(@"Konami Gesture recognized!"); 278 | self.konamiState = DRKonamiGestureStateRecognized; 279 | [self setState:UIGestureRecognizerStateRecognized]; 280 | } 281 | } 282 | } 283 | 284 | - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event 285 | { 286 | [self setState:UIGestureRecognizerStateFailed]; 287 | } 288 | 289 | #pragma mark - 290 | #pragma mark Button actions 291 | 292 | - (void) AButtonAction 293 | { 294 | if ( self.konamiState == DRKonamiGestureStateB ) 295 | { 296 | self.konamiState ++; 297 | [self setState:UIGestureRecognizerStateChanged]; 298 | NSLog(@"A-Button was pressed. Konami state is now %d", self.konamiState); 299 | } 300 | else 301 | { 302 | NSLog(@"Konami gesture failed due to pressing A-Button at incorrect time. State was %d", self.konamiState); 303 | [self setState:UIGestureRecognizerStateFailed]; 304 | [self.konamiDelegate DRKonamiGestureRecognizer:self didFinishNeedingABEnterSequenceWithError:YES]; 305 | } 306 | } 307 | 308 | - (void) BButtonAction 309 | { 310 | if ( self.konamiState == DRKonamiGestureStateRight2 ) 311 | { 312 | self.konamiState ++; 313 | [self setState:UIGestureRecognizerStateChanged]; 314 | } 315 | else 316 | { 317 | NSLog(@"Konami gesture failed due to pressing B-Button at incorrect time. State was %d", self.konamiState); 318 | [self setState:UIGestureRecognizerStateFailed]; 319 | [self.konamiDelegate DRKonamiGestureRecognizer:self didFinishNeedingABEnterSequenceWithError:YES]; 320 | } 321 | } 322 | 323 | - (void) enterButtonAction 324 | { 325 | if ( self.konamiState == DRKonamiGestureStateA ) 326 | { 327 | self.konamiState ++; 328 | NSLog(@"Enter-Button was pressed. Konami state is now %d. Gesture complete!", self.konamiState); 329 | [self setState:UIGestureRecognizerStateRecognized]; 330 | [self.konamiDelegate DRKonamiGestureRecognizer:self didFinishNeedingABEnterSequenceWithError:NO]; 331 | } 332 | else 333 | { 334 | NSLog(@"Konami gesture failed due to pressing Enter-Button at incorrect time. State was %d", self.konamiState); 335 | [self setState:UIGestureRecognizerStateFailed]; 336 | [self.konamiDelegate DRKonamiGestureRecognizer:self didFinishNeedingABEnterSequenceWithError:YES]; 337 | } 338 | } 339 | 340 | - (void) cancelSequence 341 | { 342 | NSLog(@"Konami gesture failed due to calling cancelSequence"); 343 | [self setState:UIGestureRecognizerStateFailed]; 344 | [self.konamiDelegate DRKonamiGestureRecognizer:self didFinishNeedingABEnterSequenceWithError:YES]; 345 | } 346 | 347 | @end 348 | 349 | #pragma mark - 350 | #pragma mark C Helper Functiona 351 | 352 | /** 353 | Determines whether the gesture recognizer needs to check the X and Y touch coordinates depending on the gesture state. 354 | */ 355 | void getCheckValuesAfterTouchesEnded(DRKonamiGestureState konamiState, BOOL* pCheckXLeft, BOOL* pCheckXRight, BOOL* pCheckYUp, BOOL* pCheckYDown) 356 | { 357 | switch (konamiState) 358 | { 359 | case DRKonamiGestureStateBegan: 360 | case DRKonamiGestureStateUp1: 361 | case DRKonamiGestureStateUp2: 362 | *pCheckYUp = YES; 363 | break; 364 | case DRKonamiGestureStateDown1: 365 | case DRKonamiGestureStateDown2: 366 | *pCheckYDown = YES; 367 | break; 368 | 369 | case DRKonamiGestureStateLeft1: 370 | case DRKonamiGestureStateLeft2: 371 | *pCheckXLeft = YES; 372 | break; 373 | 374 | case DRKonamiGestureStateRight1: 375 | case DRKonamiGestureStateRight2: 376 | *pCheckXRight = YES; 377 | break; 378 | 379 | case DRKonamiGestureStateB: 380 | case DRKonamiGestureStateA: 381 | break; 382 | 383 | case DRKonamiGestureStateRecognized: 384 | case DRKonamiGestureStateNone: 385 | default: 386 | NSLog(@"unexpected gesture state %d (in %s)", konamiState, __FUNCTION__); 387 | break; 388 | 389 | } 390 | } 391 | 392 | /** 393 | Determines whether the gesture recognizer needs to check the X and Y touch coordinates depending on the gesture state. 394 | */ 395 | void getCheckValuesDuringDrag(DRKonamiGestureState konamiState, BOOL* pCheckX, BOOL* pCheckY) 396 | { 397 | switch (konamiState) 398 | { 399 | case DRKonamiGestureStateBegan: 400 | case DRKonamiGestureStateUp1: 401 | case DRKonamiGestureStateUp2: 402 | case DRKonamiGestureStateDown1: 403 | case DRKonamiGestureStateDown2: 404 | *pCheckX = YES; 405 | break; 406 | 407 | case DRKonamiGestureStateLeft1: 408 | case DRKonamiGestureStateRight1: 409 | case DRKonamiGestureStateLeft2: 410 | case DRKonamiGestureStateRight2: 411 | *pCheckY = YES; 412 | break; 413 | 414 | case DRKonamiGestureStateB: 415 | case DRKonamiGestureStateA: 416 | break; 417 | 418 | case DRKonamiGestureStateRecognized: 419 | case DRKonamiGestureStateNone: 420 | default: 421 | NSLog(@"unexpected gesture state %d (in %s)", konamiState, __FUNCTION__); 422 | break; 423 | } 424 | } 425 | 426 | -------------------------------------------------------------------------------- /Sources/DRViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DRViewController.h 3 | // DRKonamiCode 4 | // 5 | // Created by Danny Ricciotti on 3/4/12. 6 | // 7 | 8 | #import "DRKonamiGestureRecognizer.h" 9 | 10 | @interface DRViewController : UIViewController 11 | { 12 | @protected 13 | DRKonamiGestureRecognizer* _konamiGestureRecognizer; 14 | 15 | @protected 16 | UIView* __weak _NESControllerView; 17 | UILabel *__weak _statusLabel; 18 | } 19 | 20 | @property (weak, nonatomic, readonly) IBOutlet UIView *NESControllerView; 21 | @property (weak, nonatomic, readonly) IBOutlet UILabel *statusLabel; 22 | @property (weak, nonatomic, readonly) IBOutlet UILabel *guideLabel; 23 | @property (nonatomic, readonly) DRKonamiGestureRecognizer* konamiGestureRecognizer; 24 | 25 | - (IBAction)aButtonWasPressed:(id)sender; 26 | 27 | - (IBAction)bButtonWasPressed:(id)sender; 28 | 29 | - (IBAction)enterButtonWasPressed:(id)sender; 30 | 31 | - (IBAction)nesControllerWasPressed:(id)sender; 32 | 33 | - (IBAction)advancedModeSwitchValueChanged:(id)sender; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Sources/DRViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DRViewController.m 3 | // DRKonamiCode 4 | // 5 | // Created by Danny Ricciotti on 3/4/12. 6 | // 7 | 8 | #import "DRViewController.h" 9 | 10 | @interface DRViewController() 11 | - (void)_konamiGestureRecognized:(DRKonamiGestureRecognizer*)gesture; 12 | @property (nonatomic) UILabel *nesLabel; 13 | @end 14 | 15 | #pragma mark - 16 | 17 | @implementation DRViewController 18 | @synthesize NESControllerView = _NESControllerView; 19 | @synthesize konamiGestureRecognizer = _konamiGestureRecognizer; 20 | @synthesize statusLabel = _statusLabel; 21 | 22 | 23 | static NSString * konamiProgressString = @"↑↑↓↓←→←→BA"; 24 | 25 | 26 | #pragma mark - 27 | #pragma mark UIViewController 28 | 29 | - (void)viewDidLoad 30 | { 31 | [super viewDidLoad]; 32 | 33 | _konamiGestureRecognizer = [[DRKonamiGestureRecognizer alloc] initWithTarget:self action:@selector(_konamiGestureRecognized:)]; 34 | [self.konamiGestureRecognizer setKonamiDelegate:self]; 35 | [self.konamiGestureRecognizer setRequiresABEnterToUnlock:YES]; 36 | [self.view addGestureRecognizer:self.konamiGestureRecognizer]; 37 | 38 | if ( !self.nesLabel ) 39 | { 40 | UILabel *nesLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, CGRectGetMaxY(self.NESControllerView.frame), CGRectGetWidth(self.view.bounds)-20, 66)]; 41 | nesLabel.text = @"Hit B, then A, then the enter button (right button in middle of NES controller) to finish Konami sequence."; 42 | nesLabel.numberOfLines = 0; 43 | [nesLabel setFont:[UIFont systemFontOfSize:15]]; 44 | nesLabel.textAlignment = NSTextAlignmentCenter; 45 | [self.view addSubview:nesLabel]; 46 | nesLabel.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin; 47 | self.nesLabel = nesLabel; 48 | } 49 | 50 | // initially hidden. Shown when user has completed the Konami sequence up to the A+B+Enter part. 51 | self.NESControllerView.alpha = 0; 52 | self.NESControllerView.transform = CGAffineTransformMakeScale(.8, .8); 53 | self.nesLabel.alpha = 0; 54 | 55 | self.statusLabel.text = nil; 56 | } 57 | 58 | - (void)viewDidUnload 59 | { 60 | [self.view removeGestureRecognizer:self.konamiGestureRecognizer]; 61 | _konamiGestureRecognizer = nil; 62 | [super viewDidUnload]; 63 | } 64 | 65 | #pragma mark - 66 | #pragma mark DRKonamiGestureProtocol 67 | 68 | - (void)DRKonamiGestureRecognizerNeedsABEnterSequence:(DRKonamiGestureRecognizer*)gesture 69 | { 70 | [self setControllerHidden:NO animated:YES]; 71 | } 72 | 73 | - (void)DRKonamiGestureRecognizer:(DRKonamiGestureRecognizer*)gesture didFinishNeedingABEnterSequenceWithError:(BOOL)error 74 | { 75 | [self setControllerHidden:YES animated:YES]; 76 | } 77 | 78 | - (void)setControllerHidden:(BOOL)hidden animated:(BOOL)animated { 79 | 80 | [self OSSafeAnimateWithDuration:animated?.7:0 delay:0 usingSpringWithDamping:.5 initialSpringVelocity:0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ 81 | 82 | self.NESControllerView.alpha = hidden ? 0:1; 83 | self.NESControllerView.transform = hidden ? CGAffineTransformMakeScale(.7, .7) : CGAffineTransformIdentity; 84 | self.nesLabel.alpha = hidden ? 0:1; 85 | 86 | } completion:nil]; 87 | } 88 | 89 | #pragma mark - 90 | #pragma mark Public 91 | 92 | - (IBAction)advancedModeSwitchValueChanged:(id)sender 93 | { 94 | NSAssert([sender isKindOfClass:[UISwitch class]] == YES, @"Invalid class."); 95 | UISwitch *theSwitch = (UISwitch *)sender; 96 | 97 | self.konamiGestureRecognizer.requiresABEnterToUnlock = [theSwitch isOn]; 98 | 99 | [self setGuideString]; // call after setting requiresABEnterToUnlock 100 | } 101 | 102 | - (IBAction)aButtonWasPressed:(id)sender 103 | { 104 | [self.konamiGestureRecognizer AButtonAction]; 105 | } 106 | 107 | - (IBAction)bButtonWasPressed:(id)sender 108 | { 109 | [self.konamiGestureRecognizer BButtonAction]; 110 | } 111 | 112 | - (IBAction)enterButtonWasPressed:(id)sender 113 | { 114 | [self.konamiGestureRecognizer enterButtonAction]; 115 | } 116 | 117 | - (IBAction)nesControllerWasPressed:(id)sender 118 | { 119 | [self.konamiGestureRecognizer cancelSequence]; 120 | } 121 | 122 | #pragma mark - 123 | #pragma mark Private 124 | 125 | - (void)_konamiGestureRecognized:(DRKonamiGestureRecognizer*)gesture 126 | { 127 | if ( gesture.state == UIGestureRecognizerStateRecognized ) 128 | { 129 | UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Konami!" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Dismiss",nil]; 130 | [alert show]; 131 | } 132 | else if ( gesture.state == UIGestureRecognizerStateChanged ) 133 | { 134 | DRKonamiGestureState konamiState = gesture.konamiState; 135 | NSInteger indexOfSubString = konamiState - DRKonamiGestureStateUp1 + 1; 136 | 137 | if ( indexOfSubString > 0 ) 138 | { 139 | NSString *progressString = [konamiProgressString substringToIndex:indexOfSubString]; 140 | self.statusLabel.text = progressString; 141 | } 142 | else 143 | { 144 | self.statusLabel.text = nil; 145 | } 146 | } 147 | else 148 | { 149 | self.statusLabel.text = nil; 150 | } 151 | } 152 | 153 | - (void)setGuideString 154 | { 155 | BOOL baaaaa = self.konamiGestureRecognizer.requiresABEnterToUnlock; 156 | self.guideLabel.text = [konamiProgressString substringToIndex:baaaaa?10:8]; 157 | } 158 | 159 | // lets you use dynamics if available 160 | - (void)OSSafeAnimateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(6_0) 161 | { 162 | if ( [[UIView class] respondsToSelector:@selector(animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:completion:)] ) { 163 | 164 | [UIView animateWithDuration:duration delay:delay usingSpringWithDamping:dampingRatio initialSpringVelocity:velocity options:options animations:animations completion:completion]; 165 | 166 | } else { 167 | 168 | [UIView animateWithDuration:duration delay:delay options:options animations:animations completion:completion]; 169 | 170 | } 171 | } 172 | 173 | @end 174 | -------------------------------------------------------------------------------- /Sources/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // DRKonamiCode 4 | // 5 | // Created by Danny Ricciotti on 3/4/12. 6 | // 7 | 8 | #import 9 | 10 | #import "DRAppDelegate.h" 11 | 12 | int main(int argc, char *argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([DRAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | DRKonamiCode is licensed under the MIT license 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2015 Daniel Ricciotti 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in 15 | all copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | THE SOFTWARE. 24 | --------------------------------------------------------------------------------