├── .gitignore ├── AnyDoor.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── AnyDoor ├── AnyDoor.swift ├── AppDelegate.swift ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── Rinku.swift ├── ViewController.swift └── bgHeader.h ├── AnyDoorTests ├── AnyDoorTests.swift └── Info.plist ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | -------------------------------------------------------------------------------- /AnyDoor.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E263E1A31A6B97990021128A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E263E1A21A6B97990021128A /* AppDelegate.swift */; }; 11 | E263E1A51A6B97990021128A /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E263E1A41A6B97990021128A /* ViewController.swift */; }; 12 | E263E1A81A6B97990021128A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E263E1A61A6B97990021128A /* Main.storyboard */; }; 13 | E263E1AA1A6B97990021128A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E263E1A91A6B97990021128A /* Images.xcassets */; }; 14 | E263E1AD1A6B97990021128A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = E263E1AB1A6B97990021128A /* LaunchScreen.xib */; }; 15 | E263E1B91A6B97990021128A /* AnyDoorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E263E1B81A6B97990021128A /* AnyDoorTests.swift */; }; 16 | E263E1C41A6B9A450021128A /* Rinku.swift in Sources */ = {isa = PBXBuildFile; fileRef = E263E1C31A6B9A450021128A /* Rinku.swift */; }; 17 | E263E1C71A6B9AAF0021128A /* AnyDoor.swift in Sources */ = {isa = PBXBuildFile; fileRef = E263E1C51A6B9AAF0021128A /* AnyDoor.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | E263E1B31A6B97990021128A /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = E263E1951A6B97990021128A /* Project object */; 24 | proxyType = 1; 25 | remoteGlobalIDString = E263E19C1A6B97990021128A; 26 | remoteInfo = AnyDoor; 27 | }; 28 | /* End PBXContainerItemProxy section */ 29 | 30 | /* Begin PBXFileReference section */ 31 | E263E19D1A6B97990021128A /* AnyDoor.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AnyDoor.app; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | E263E1A11A6B97990021128A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | E263E1A21A6B97990021128A /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 34 | E263E1A41A6B97990021128A /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 35 | E263E1A71A6B97990021128A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 36 | E263E1A91A6B97990021128A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 37 | E263E1AC1A6B97990021128A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 38 | E263E1B21A6B97990021128A /* AnyDoorTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AnyDoorTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 39 | E263E1B71A6B97990021128A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 40 | E263E1B81A6B97990021128A /* AnyDoorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnyDoorTests.swift; sourceTree = ""; }; 41 | E263E1C31A6B9A450021128A /* Rinku.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Rinku.swift; sourceTree = ""; }; 42 | E263E1C51A6B9AAF0021128A /* AnyDoor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyDoor.swift; sourceTree = ""; }; 43 | E263E1C61A6B9AAF0021128A /* bgHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bgHeader.h; sourceTree = ""; }; 44 | /* End PBXFileReference section */ 45 | 46 | /* Begin PBXFrameworksBuildPhase section */ 47 | E263E19A1A6B97990021128A /* Frameworks */ = { 48 | isa = PBXFrameworksBuildPhase; 49 | buildActionMask = 2147483647; 50 | files = ( 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | E263E1AF1A6B97990021128A /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | E263E1941A6B97990021128A = { 65 | isa = PBXGroup; 66 | children = ( 67 | E263E19F1A6B97990021128A /* AnyDoor */, 68 | E263E1B51A6B97990021128A /* AnyDoorTests */, 69 | E263E19E1A6B97990021128A /* Products */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | E263E19E1A6B97990021128A /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | E263E19D1A6B97990021128A /* AnyDoor.app */, 77 | E263E1B21A6B97990021128A /* AnyDoorTests.xctest */, 78 | ); 79 | name = Products; 80 | sourceTree = ""; 81 | }; 82 | E263E19F1A6B97990021128A /* AnyDoor */ = { 83 | isa = PBXGroup; 84 | children = ( 85 | E263E1C21A6B9A010021128A /* SRC */, 86 | E263E1A21A6B97990021128A /* AppDelegate.swift */, 87 | E263E1A41A6B97990021128A /* ViewController.swift */, 88 | E263E1A61A6B97990021128A /* Main.storyboard */, 89 | E263E1A91A6B97990021128A /* Images.xcassets */, 90 | E263E1AB1A6B97990021128A /* LaunchScreen.xib */, 91 | E263E1A01A6B97990021128A /* Supporting Files */, 92 | ); 93 | path = AnyDoor; 94 | sourceTree = ""; 95 | }; 96 | E263E1A01A6B97990021128A /* Supporting Files */ = { 97 | isa = PBXGroup; 98 | children = ( 99 | E263E1A11A6B97990021128A /* Info.plist */, 100 | ); 101 | name = "Supporting Files"; 102 | sourceTree = ""; 103 | }; 104 | E263E1B51A6B97990021128A /* AnyDoorTests */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | E263E1B81A6B97990021128A /* AnyDoorTests.swift */, 108 | E263E1B61A6B97990021128A /* Supporting Files */, 109 | ); 110 | path = AnyDoorTests; 111 | sourceTree = ""; 112 | }; 113 | E263E1B61A6B97990021128A /* Supporting Files */ = { 114 | isa = PBXGroup; 115 | children = ( 116 | E263E1B71A6B97990021128A /* Info.plist */, 117 | ); 118 | name = "Supporting Files"; 119 | sourceTree = ""; 120 | }; 121 | E263E1C21A6B9A010021128A /* SRC */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | E263E1C51A6B9AAF0021128A /* AnyDoor.swift */, 125 | E263E1C61A6B9AAF0021128A /* bgHeader.h */, 126 | E263E1C31A6B9A450021128A /* Rinku.swift */, 127 | ); 128 | name = SRC; 129 | sourceTree = ""; 130 | }; 131 | /* End PBXGroup section */ 132 | 133 | /* Begin PBXNativeTarget section */ 134 | E263E19C1A6B97990021128A /* AnyDoor */ = { 135 | isa = PBXNativeTarget; 136 | buildConfigurationList = E263E1BC1A6B97990021128A /* Build configuration list for PBXNativeTarget "AnyDoor" */; 137 | buildPhases = ( 138 | E263E1991A6B97990021128A /* Sources */, 139 | E263E19A1A6B97990021128A /* Frameworks */, 140 | E263E19B1A6B97990021128A /* Resources */, 141 | ); 142 | buildRules = ( 143 | ); 144 | dependencies = ( 145 | ); 146 | name = AnyDoor; 147 | productName = AnyDoor; 148 | productReference = E263E19D1A6B97990021128A /* AnyDoor.app */; 149 | productType = "com.apple.product-type.application"; 150 | }; 151 | E263E1B11A6B97990021128A /* AnyDoorTests */ = { 152 | isa = PBXNativeTarget; 153 | buildConfigurationList = E263E1BF1A6B97990021128A /* Build configuration list for PBXNativeTarget "AnyDoorTests" */; 154 | buildPhases = ( 155 | E263E1AE1A6B97990021128A /* Sources */, 156 | E263E1AF1A6B97990021128A /* Frameworks */, 157 | E263E1B01A6B97990021128A /* Resources */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | E263E1B41A6B97990021128A /* PBXTargetDependency */, 163 | ); 164 | name = AnyDoorTests; 165 | productName = AnyDoorTests; 166 | productReference = E263E1B21A6B97990021128A /* AnyDoorTests.xctest */; 167 | productType = "com.apple.product-type.bundle.unit-test"; 168 | }; 169 | /* End PBXNativeTarget section */ 170 | 171 | /* Begin PBXProject section */ 172 | E263E1951A6B97990021128A /* Project object */ = { 173 | isa = PBXProject; 174 | attributes = { 175 | LastUpgradeCheck = 0610; 176 | ORGANIZATIONNAME = liming; 177 | TargetAttributes = { 178 | E263E19C1A6B97990021128A = { 179 | CreatedOnToolsVersion = 6.1.1; 180 | }; 181 | E263E1B11A6B97990021128A = { 182 | CreatedOnToolsVersion = 6.1.1; 183 | TestTargetID = E263E19C1A6B97990021128A; 184 | }; 185 | }; 186 | }; 187 | buildConfigurationList = E263E1981A6B97990021128A /* Build configuration list for PBXProject "AnyDoor" */; 188 | compatibilityVersion = "Xcode 3.2"; 189 | developmentRegion = English; 190 | hasScannedForEncodings = 0; 191 | knownRegions = ( 192 | en, 193 | Base, 194 | ); 195 | mainGroup = E263E1941A6B97990021128A; 196 | productRefGroup = E263E19E1A6B97990021128A /* Products */; 197 | projectDirPath = ""; 198 | projectRoot = ""; 199 | targets = ( 200 | E263E19C1A6B97990021128A /* AnyDoor */, 201 | E263E1B11A6B97990021128A /* AnyDoorTests */, 202 | ); 203 | }; 204 | /* End PBXProject section */ 205 | 206 | /* Begin PBXResourcesBuildPhase section */ 207 | E263E19B1A6B97990021128A /* Resources */ = { 208 | isa = PBXResourcesBuildPhase; 209 | buildActionMask = 2147483647; 210 | files = ( 211 | E263E1A81A6B97990021128A /* Main.storyboard in Resources */, 212 | E263E1AD1A6B97990021128A /* LaunchScreen.xib in Resources */, 213 | E263E1AA1A6B97990021128A /* Images.xcassets in Resources */, 214 | ); 215 | runOnlyForDeploymentPostprocessing = 0; 216 | }; 217 | E263E1B01A6B97990021128A /* Resources */ = { 218 | isa = PBXResourcesBuildPhase; 219 | buildActionMask = 2147483647; 220 | files = ( 221 | ); 222 | runOnlyForDeploymentPostprocessing = 0; 223 | }; 224 | /* End PBXResourcesBuildPhase section */ 225 | 226 | /* Begin PBXSourcesBuildPhase section */ 227 | E263E1991A6B97990021128A /* Sources */ = { 228 | isa = PBXSourcesBuildPhase; 229 | buildActionMask = 2147483647; 230 | files = ( 231 | E263E1C71A6B9AAF0021128A /* AnyDoor.swift in Sources */, 232 | E263E1A51A6B97990021128A /* ViewController.swift in Sources */, 233 | E263E1C41A6B9A450021128A /* Rinku.swift in Sources */, 234 | E263E1A31A6B97990021128A /* AppDelegate.swift in Sources */, 235 | ); 236 | runOnlyForDeploymentPostprocessing = 0; 237 | }; 238 | E263E1AE1A6B97990021128A /* Sources */ = { 239 | isa = PBXSourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | E263E1B91A6B97990021128A /* AnyDoorTests.swift in Sources */, 243 | ); 244 | runOnlyForDeploymentPostprocessing = 0; 245 | }; 246 | /* End PBXSourcesBuildPhase section */ 247 | 248 | /* Begin PBXTargetDependency section */ 249 | E263E1B41A6B97990021128A /* PBXTargetDependency */ = { 250 | isa = PBXTargetDependency; 251 | target = E263E19C1A6B97990021128A /* AnyDoor */; 252 | targetProxy = E263E1B31A6B97990021128A /* PBXContainerItemProxy */; 253 | }; 254 | /* End PBXTargetDependency section */ 255 | 256 | /* Begin PBXVariantGroup section */ 257 | E263E1A61A6B97990021128A /* Main.storyboard */ = { 258 | isa = PBXVariantGroup; 259 | children = ( 260 | E263E1A71A6B97990021128A /* Base */, 261 | ); 262 | name = Main.storyboard; 263 | sourceTree = ""; 264 | }; 265 | E263E1AB1A6B97990021128A /* LaunchScreen.xib */ = { 266 | isa = PBXVariantGroup; 267 | children = ( 268 | E263E1AC1A6B97990021128A /* Base */, 269 | ); 270 | name = LaunchScreen.xib; 271 | sourceTree = ""; 272 | }; 273 | /* End PBXVariantGroup section */ 274 | 275 | /* Begin XCBuildConfiguration section */ 276 | E263E1BA1A6B97990021128A /* Debug */ = { 277 | isa = XCBuildConfiguration; 278 | buildSettings = { 279 | ALWAYS_SEARCH_USER_PATHS = NO; 280 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 281 | CLANG_CXX_LIBRARY = "libc++"; 282 | CLANG_ENABLE_MODULES = YES; 283 | CLANG_ENABLE_OBJC_ARC = YES; 284 | CLANG_WARN_BOOL_CONVERSION = YES; 285 | CLANG_WARN_CONSTANT_CONVERSION = YES; 286 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 287 | CLANG_WARN_EMPTY_BODY = YES; 288 | CLANG_WARN_ENUM_CONVERSION = YES; 289 | CLANG_WARN_INT_CONVERSION = YES; 290 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 291 | CLANG_WARN_UNREACHABLE_CODE = YES; 292 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 293 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 294 | COPY_PHASE_STRIP = NO; 295 | ENABLE_STRICT_OBJC_MSGSEND = YES; 296 | GCC_C_LANGUAGE_STANDARD = gnu99; 297 | GCC_DYNAMIC_NO_PIC = NO; 298 | GCC_OPTIMIZATION_LEVEL = 0; 299 | GCC_PREPROCESSOR_DEFINITIONS = ( 300 | "DEBUG=1", 301 | "$(inherited)", 302 | ); 303 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 304 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 305 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 306 | GCC_WARN_UNDECLARED_SELECTOR = YES; 307 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 308 | GCC_WARN_UNUSED_FUNCTION = YES; 309 | GCC_WARN_UNUSED_VARIABLE = YES; 310 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 311 | MTL_ENABLE_DEBUG_INFO = YES; 312 | ONLY_ACTIVE_ARCH = YES; 313 | SDKROOT = iphoneos; 314 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 315 | }; 316 | name = Debug; 317 | }; 318 | E263E1BB1A6B97990021128A /* Release */ = { 319 | isa = XCBuildConfiguration; 320 | buildSettings = { 321 | ALWAYS_SEARCH_USER_PATHS = NO; 322 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 323 | CLANG_CXX_LIBRARY = "libc++"; 324 | CLANG_ENABLE_MODULES = YES; 325 | CLANG_ENABLE_OBJC_ARC = YES; 326 | CLANG_WARN_BOOL_CONVERSION = YES; 327 | CLANG_WARN_CONSTANT_CONVERSION = YES; 328 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 329 | CLANG_WARN_EMPTY_BODY = YES; 330 | CLANG_WARN_ENUM_CONVERSION = YES; 331 | CLANG_WARN_INT_CONVERSION = YES; 332 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 333 | CLANG_WARN_UNREACHABLE_CODE = YES; 334 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 335 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 336 | COPY_PHASE_STRIP = YES; 337 | ENABLE_NS_ASSERTIONS = NO; 338 | ENABLE_STRICT_OBJC_MSGSEND = YES; 339 | GCC_C_LANGUAGE_STANDARD = gnu99; 340 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 341 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 342 | GCC_WARN_UNDECLARED_SELECTOR = YES; 343 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 344 | GCC_WARN_UNUSED_FUNCTION = YES; 345 | GCC_WARN_UNUSED_VARIABLE = YES; 346 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 347 | MTL_ENABLE_DEBUG_INFO = NO; 348 | SDKROOT = iphoneos; 349 | VALIDATE_PRODUCT = YES; 350 | }; 351 | name = Release; 352 | }; 353 | E263E1BD1A6B97990021128A /* Debug */ = { 354 | isa = XCBuildConfiguration; 355 | buildSettings = { 356 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 357 | INFOPLIST_FILE = AnyDoor/Info.plist; 358 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 359 | PRODUCT_NAME = "$(TARGET_NAME)"; 360 | SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/AnyDoor/bgHeader.h"; 361 | }; 362 | name = Debug; 363 | }; 364 | E263E1BE1A6B97990021128A /* Release */ = { 365 | isa = XCBuildConfiguration; 366 | buildSettings = { 367 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 368 | INFOPLIST_FILE = AnyDoor/Info.plist; 369 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 370 | PRODUCT_NAME = "$(TARGET_NAME)"; 371 | SWIFT_OBJC_BRIDGING_HEADER = "$(SRCROOT)/AnyDoor/bgHeader.h"; 372 | }; 373 | name = Release; 374 | }; 375 | E263E1C01A6B97990021128A /* Debug */ = { 376 | isa = XCBuildConfiguration; 377 | buildSettings = { 378 | BUNDLE_LOADER = "$(TEST_HOST)"; 379 | FRAMEWORK_SEARCH_PATHS = ( 380 | "$(SDKROOT)/Developer/Library/Frameworks", 381 | "$(inherited)", 382 | ); 383 | GCC_PREPROCESSOR_DEFINITIONS = ( 384 | "DEBUG=1", 385 | "$(inherited)", 386 | ); 387 | INFOPLIST_FILE = AnyDoorTests/Info.plist; 388 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 389 | PRODUCT_NAME = "$(TARGET_NAME)"; 390 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AnyDoor.app/AnyDoor"; 391 | }; 392 | name = Debug; 393 | }; 394 | E263E1C11A6B97990021128A /* Release */ = { 395 | isa = XCBuildConfiguration; 396 | buildSettings = { 397 | BUNDLE_LOADER = "$(TEST_HOST)"; 398 | FRAMEWORK_SEARCH_PATHS = ( 399 | "$(SDKROOT)/Developer/Library/Frameworks", 400 | "$(inherited)", 401 | ); 402 | INFOPLIST_FILE = AnyDoorTests/Info.plist; 403 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 404 | PRODUCT_NAME = "$(TARGET_NAME)"; 405 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AnyDoor.app/AnyDoor"; 406 | }; 407 | name = Release; 408 | }; 409 | /* End XCBuildConfiguration section */ 410 | 411 | /* Begin XCConfigurationList section */ 412 | E263E1981A6B97990021128A /* Build configuration list for PBXProject "AnyDoor" */ = { 413 | isa = XCConfigurationList; 414 | buildConfigurations = ( 415 | E263E1BA1A6B97990021128A /* Debug */, 416 | E263E1BB1A6B97990021128A /* Release */, 417 | ); 418 | defaultConfigurationIsVisible = 0; 419 | defaultConfigurationName = Release; 420 | }; 421 | E263E1BC1A6B97990021128A /* Build configuration list for PBXNativeTarget "AnyDoor" */ = { 422 | isa = XCConfigurationList; 423 | buildConfigurations = ( 424 | E263E1BD1A6B97990021128A /* Debug */, 425 | E263E1BE1A6B97990021128A /* Release */, 426 | ); 427 | defaultConfigurationIsVisible = 0; 428 | defaultConfigurationName = Release; 429 | }; 430 | E263E1BF1A6B97990021128A /* Build configuration list for PBXNativeTarget "AnyDoorTests" */ = { 431 | isa = XCConfigurationList; 432 | buildConfigurations = ( 433 | E263E1C01A6B97990021128A /* Debug */, 434 | E263E1C11A6B97990021128A /* Release */, 435 | ); 436 | defaultConfigurationIsVisible = 0; 437 | defaultConfigurationName = Release; 438 | }; 439 | /* End XCConfigurationList section */ 440 | }; 441 | rootObject = E263E1951A6B97990021128A /* Project object */; 442 | } 443 | -------------------------------------------------------------------------------- /AnyDoor.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /AnyDoor/AnyDoor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DreamUtility.swift 3 | // testRecodeVideo 4 | // 5 | // Created by LiMing on 15/1/17. 6 | // Copyright (c) 2015年 miaomi. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | /// Sign method enum for hmac 13 | public enum HMACAlgorithm { 14 | case MD5, SHA1, SHA224, SHA256, SHA384, SHA512 15 | 16 | func toCCHmacAlgorithm() -> CCHmacAlgorithm { 17 | var result: Int = 0 18 | switch self { 19 | case .MD5: 20 | result = kCCHmacAlgMD5 21 | case .SHA1: 22 | result = kCCHmacAlgSHA1 23 | case .SHA224: 24 | result = kCCHmacAlgSHA224 25 | case .SHA256: 26 | result = kCCHmacAlgSHA256 27 | case .SHA384: 28 | result = kCCHmacAlgSHA384 29 | case .SHA512: 30 | result = kCCHmacAlgSHA512 31 | } 32 | return CCHmacAlgorithm(result) 33 | } 34 | 35 | func digestLength() -> Int { 36 | var result: CInt = 0 37 | switch self { 38 | case .MD5: 39 | result = CC_MD5_DIGEST_LENGTH 40 | case .SHA1: 41 | result = CC_SHA1_DIGEST_LENGTH 42 | case .SHA224: 43 | result = CC_SHA224_DIGEST_LENGTH 44 | case .SHA256: 45 | result = CC_SHA256_DIGEST_LENGTH 46 | case .SHA384: 47 | result = CC_SHA384_DIGEST_LENGTH 48 | case .SHA512: 49 | result = CC_SHA512_DIGEST_LENGTH 50 | } 51 | return Int(result) 52 | } 53 | } 54 | 55 | /// Access Dictionary or array with no pain 56 | public struct ADAccessor { 57 | 58 | private let value:AnyObject! 59 | 60 | ///:init a accessor 61 | ///:params: AnyObject 62 | ///:return:Accessor Object 63 | public init(_ data:AnyObject){ 64 | value = data 65 | } 66 | 67 | /// Access Array item 68 | /// sample: accessor[0] 69 | ///:params: index 70 | ///:return: Accessor wrap the item in array 71 | subscript(index:Int)->ADAccessor{ 72 | return ADAccessor((value as! NSArray).objectAtIndex(index)) 73 | } 74 | 75 | /// Access range of aray item 76 | /// sample: accessor[1...3] 77 | ///:params: range object 78 | ///:return: Accessor array wrap the item in array 79 | subscript(range:NSRange)->Array{ 80 | let arr:NSArray = (value as! NSArray).subarrayWithRange(range) 81 | //let result:NSMutableArray = NSMutableArray(capacity: arr.count) 82 | var result:Array = Array() 83 | for item:AnyObject in arr{ 84 | var acc:ADAccessor = ADAccessor(item) 85 | result += [acc] 86 | } 87 | return result 88 | } 89 | 90 | /// Access Dictionary item 91 | /// sample: accessor["key"] 92 | ///:params: any hashable object 93 | ///:return: Accessor wrap the item in dictionary 94 | subscript(index:AnyObject)->ADAccessor{ 95 | let v:AnyObject = (value as! NSDictionary).objectForKey(index)! 96 | return ADAccessor(v) 97 | } 98 | 99 | func val(_:T.Type)->T{ 100 | return (value as! T) 101 | } 102 | 103 | /// Get wrapped Array value 104 | public var array:[Any]!{ 105 | get{ 106 | return map((value as! [AnyObject]), {ADAccessor($0)}) 107 | } 108 | } 109 | 110 | /// Get wrapped dictionary value 111 | public var dictionary:Dictionary{ 112 | get{ 113 | let dt:[String:AnyObject] = (value as! [String:AnyObject]) 114 | var result:Dictionary = Dictionary(minimumCapacity:dt.count) 115 | for (k, val) in dt{ 116 | result[k] = ADAccessor(val) 117 | } 118 | return result 119 | } 120 | } 121 | 122 | /** 123 | check if a key in dictionary value 124 | 125 | :param: key key of dictionary 126 | 127 | :returns: Accessor object wrap the dictionary value 128 | */ 129 | func hasKey(key:String)->Bool{ 130 | if (self.value is Dictionary){ 131 | if (self.value as! Dictionary)[key] != nil{ 132 | return true 133 | } 134 | } 135 | return false 136 | } 137 | 138 | } 139 | 140 | /// Operator to repeat string "a"*5 return "aaaaa" 141 | func * (pt0: String, pt1: Int) -> String { 142 | var arr:[String] = [pt0] 143 | for i in 1.. String { 159 | get{ 160 | if (range.count>2){ 161 | assertionFailure({ () -> String in 162 | "Wrong argument, must 2 bug got \(range.count)" 163 | }()) 164 | } 165 | let length: Int = count(self) 166 | let startIdx = (range[0]<0 ? (length + range[0]) : range[0]) 167 | let endIdx = (range[1]<0 ? (length + range[1]) : range[1]) 168 | if (startIdx>endIdx){ 169 | assertionFailure({ () -> String in 170 | "Index out of range (\(startIdx):\(endIdx))" 171 | }()) 172 | } 173 | let indexRange:Range = Range(start: startIdx,end: endIdx) 174 | return self.substringWithRange(Range(start: advance(self.startIndex, indexRange.startIndex), end: advance(self.startIndex, indexRange.endIndex))) 175 | } 176 | } 177 | 178 | /// Get String length 179 | public var length:Int { 180 | get{ 181 | return count(self) 182 | } 183 | } 184 | 185 | /// Check if some string contains another 186 | ///:params:sub string 187 | ///:return: Bool for string in it 188 | func adContains(searchString:String)->Bool{ 189 | let textRange = self.rangeOfString(searchString) 190 | return textRange != nil 191 | } 192 | 193 | 194 | /// Get string in another string's start index int value 195 | ///:params:sub string 196 | ///:return: int value 197 | func adStartAt(searchString:String)->Int{ 198 | let textRange = self.rangeOfString(searchString) 199 | if (textRange != nil){ 200 | return (textRange!.startIndex.getMirror().value as? Int)! 201 | } 202 | return -1 203 | } 204 | 205 | //#MARK: - JSON extension 206 | 207 | /// json dictionary wrapped by Accessor 208 | public var adJsonObject:ADAccessor{ 209 | get{ 210 | return self.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)!.adJsonObject 211 | } 212 | } 213 | 214 | //#MARK: - file extension 215 | /// self as a file path, check if it exists 216 | public var adFileExists:Bool{ 217 | get{ 218 | return NSFileManager.defaultManager().fileExistsAtPath(self) 219 | } 220 | } 221 | 222 | 223 | /// self as a file path, get file data as NSData 224 | public var adFileData:NSData{ 225 | get{ 226 | return NSData(contentsOfFile: self)! 227 | } 228 | } 229 | 230 | /// self as a file path, delete it 231 | func adFileDelete()->Bool{ 232 | return NSFileManager.defaultManager().removeItemAtPath(self, error: nil) 233 | } 234 | 235 | 236 | //#MARK: - URL extension 237 | /// self as a Qiniu Yun file key, get a Rinku object to fetch resource 238 | func adQiniuFileData(domain:String)->Rinku{ 239 | var url = "http://\(domain)/\(self)" 240 | return Rinku.get(url) 241 | } 242 | 243 | 244 | 245 | //#MARK: - URL extension 246 | /// self as a YouPai Yun file key, get a Rinku object to fetch resource 247 | func adYouPaiYunFileData(domain:String)->Rinku{ 248 | var url = "http://\(domain)/\(self)" 249 | return Rinku.get(url) 250 | } 251 | 252 | 253 | /// self as a url, to NSURL object 254 | func adToURL()->NSURL{ 255 | return NSURL(string: self)! 256 | } 257 | 258 | 259 | /// self as a File url, to NSURL object 260 | func adFileURL()->NSURL{ 261 | return NSURL(fileURLWithPath: self)! 262 | } 263 | 264 | /// self as a filename , get path string if it in system directory 265 | func adFileInFolderString(catalog:NSSearchPathDirectory)->String{ 266 | let path = NSSearchPathForDirectoriesInDomains(catalog, NSSearchPathDomainMask.UserDomainMask, true) 267 | return "\(path[0])/\(self)" 268 | } 269 | 270 | /// self as a filename , get NSURL object if it in system directory 271 | func adFileInFolderURL(catalog:NSSearchPathDirectory)->NSURL{ 272 | let path = self.adFileInFolderString(catalog) 273 | return NSURL(fileURLWithPath: path)! 274 | } 275 | 276 | //#MARK: - base64 extension 277 | /// get urlsafe base64 string 278 | func adToUrlSafeBase64String()->String{ 279 | let utf8str: NSData = self.dataUsingEncoding(NSUTF8StringEncoding)! 280 | let base64Encoded:NSString = utf8str.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)) 281 | 282 | return String(base64Encoded).stringByReplacingOccurrencesOfString("+", withString: "-", options: NSStringCompareOptions.LiteralSearch, range: nil).stringByReplacingOccurrencesOfString("/", withString: "_", options: NSStringCompareOptions.LiteralSearch, range: nil) 283 | } 284 | 285 | /// get string from a base64 string 286 | func adFromUrlSafeBase64String()->String{ 287 | let b64Str:String = self.stringByReplacingOccurrencesOfString("-", withString: "+", options: NSStringCompareOptions.LiteralSearch, range: nil).stringByReplacingOccurrencesOfString("_", withString: "/", options: NSStringCompareOptions.LiteralSearch, range: nil) 288 | 289 | let data = NSData(base64EncodedString: b64Str, options:NSDataBase64DecodingOptions.IgnoreUnknownCharacters) 290 | let base64Decoded = NSString(data: data!, encoding: NSUTF8StringEncoding) 291 | return "\(base64Decoded)" 292 | } 293 | 294 | //#MARK: - hash extension 295 | /// get hmac hash hex string 296 | func adHmacEncrptHex(algorithm: HMACAlgorithm, key:String)->String{ 297 | let str = self.cStringUsingEncoding(NSUTF8StringEncoding) 298 | let strLen = Int(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) 299 | let digestLen = algorithm.digestLength() 300 | let result = UnsafeMutablePointer.alloc(digestLen) 301 | let objcKey = key as NSString 302 | let keyStr = objcKey.cStringUsingEncoding(NSUTF8StringEncoding) 303 | let keyLen = Int(objcKey.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) 304 | 305 | 306 | CCHmac(algorithm.toCCHmacAlgorithm(), keyStr, keyLen, str!, strLen, result) 307 | var hash = NSMutableString() 308 | for i in 0..NSData{ 317 | let str = self.cStringUsingEncoding(NSUTF8StringEncoding) 318 | let strLen = Int(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) 319 | let digestLen = algorithm.digestLength() 320 | let result = UnsafeMutablePointer.alloc(digestLen) 321 | let objcKey = key as NSString 322 | let keyStr = objcKey.cStringUsingEncoding(NSUTF8StringEncoding) 323 | let keyLen = Int(objcKey.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)) 324 | CCHmac(algorithm.toCCHmacAlgorithm(), keyStr, keyLen, str!, strLen, result) 325 | let resultData:NSData = NSData(bytes: UnsafePointer(result), length: digestLen) 326 | return resultData 327 | } 328 | 329 | 330 | /// get md5 hash hex 331 | func adMD5Hex() -> String { 332 | let data = (self as NSString).dataUsingEncoding(NSUTF8StringEncoding) 333 | let result = NSMutableData(length: Int(CC_MD5_DIGEST_LENGTH)) 334 | let resultBytes = UnsafeMutablePointer(result!.bytes) 335 | CC_MD5(data!.bytes, CC_LONG(data!.length), resultBytes) 336 | 337 | let a = UnsafeBufferPointer(start: resultBytes, count: result!.length) 338 | let hash = NSMutableString() 339 | 340 | for i in a { 341 | hash.appendFormat("%02x", i) 342 | } 343 | return hash as String 344 | } 345 | 346 | //#MARK: - Image extension 347 | /// self as a image name, return UIImage object 348 | func adImage()->UIImage{ 349 | return UIImage(named: self)! 350 | } 351 | 352 | /// self as a image name, return resizeable UIImage 353 | func adResizableImage(corner:Float...)->UIImage{ 354 | if (corner.count != 4){ 355 | assertionFailure({ () -> String in 356 | "Wrong argument, must be 4 but \(corner.count) input" 357 | }()) 358 | } 359 | let img = UIImage(named: self)! 360 | return img.resizableImageWithCapInsets(UIEdgeInsetsMake(CGFloat(corner[0]), CGFloat(corner[1]), CGFloat(corner[2]), CGFloat(corner[3]))) 361 | } 362 | 363 | } 364 | 365 | public extension NSData{ 366 | 367 | /// get json dictionary wrapped by accessor object 368 | public var adJsonObject:ADAccessor{ 369 | get{ 370 | return ADAccessor(NSJSONSerialization.JSONObjectWithData(self, options: NSJSONReadingOptions.AllowFragments, error: nil)!) 371 | } 372 | } 373 | 374 | /// to utf8 string 375 | public var adUtf8String:String{ 376 | get{ 377 | return "\(NSString(data: self, encoding: NSUTF8StringEncoding))" 378 | } 379 | } 380 | 381 | /// to url safe base64 string 382 | func adToUrlSafeB64String()->String{ 383 | let base64Encoded:NSString = self.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(rawValue: 0)) 384 | return String(base64Encoded).stringByReplacingOccurrencesOfString("+", withString: "-", options: NSStringCompareOptions.LiteralSearch, range: nil).stringByReplacingOccurrencesOfString("/", withString: "_", options: NSStringCompareOptions.LiteralSearch, range: nil) 385 | } 386 | 387 | /// get Byte Array 388 | func adAsArray(_:T.Type)->Array{ 389 | let pointer = UnsafePointer(self.bytes) 390 | let buffer = UnsafeBufferPointer(start:pointer, count:self.length/sizeof(T)) 391 | return [T](buffer) 392 | } 393 | 394 | /// upload data to Qiniu Yun 395 | ///:params: filename, accessKey, accessSecret, scope 396 | ///:return: Rinku object 397 | func adUploadToQiniu(filename:String, accessKey:String, accessSecret:String, scope:String)->Rinku{ 398 | let ts = Int(NSDate().timeIntervalSince1970) + 3600*12 399 | let policyStr = "{\"scope\":\"\(scope)\",\"deadline\":\(ts)}" 400 | let encodedPutPolicy = policyStr.adToUrlSafeBase64String() 401 | let encodedSign = encodedPutPolicy.adHmacEncrptData(HMACAlgorithm.SHA1, key: accessSecret).adToUrlSafeB64String() 402 | let policyToken = ":".join([accessKey, encodedSign, encodedPutPolicy]) 403 | return Rinku.post("http://upload.qiniu.com").file(self, filefield: "file", filename: filename, extForm: ["token":policyToken, "key": filename]) 404 | } 405 | 406 | 407 | /// upload file to YouPai Yun 408 | ///:params:filename, bucket, securyKey, ext-form 409 | ///:return:Rinku object 410 | func adUploadToYouPaiYun(filename:String, bucket:String, securyKey:String, form:Dictionary)->Rinku{ 411 | let ts = Int(NSDate().timeIntervalSince1970) + 3600*12 412 | let policy = "{\"bucket\":\"\(bucket)\",\"expiration\":\(ts),\"save-key\":\"\(filename)\"}" 413 | let sign = "\(policy.adToUrlSafeBase64String())&\(securyKey)".adMD5Hex() 414 | var params = ["bucket":bucket,"save-key":"\(filename)", "expiration":"\(ts)", "policy":policy.adToUrlSafeBase64String(), "signature":sign] 415 | for (k, val) in form{ 416 | params.updateValue((val as! String), forKey: k) 417 | } 418 | return Rinku.post("http://v0.api.upyun.com/\(bucket)").file(self, filefield: "file", filename: filename, extForm: params) 419 | } 420 | 421 | 422 | 423 | /// save to system directory 424 | func adSaveTo(catalog:NSSearchPathDirectory, filename:String)->Void{ 425 | let path = filename.adFileInFolderString(catalog) 426 | self.writeToFile(path, atomically: true) 427 | } 428 | 429 | /// read file from system directory 430 | class func adReadFile(catalog:NSSearchPathDirectory, filename:String)->NSData{ 431 | let path = filename.adFileInFolderString(catalog) 432 | return NSData(contentsOfFile: path, options: NSDataReadingOptions.UncachedRead, error: nil)! 433 | } 434 | 435 | } 436 | -------------------------------------------------------------------------------- /AnyDoor/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // AnyDoor 4 | // 5 | // Created by LiMing on 15/1/18. 6 | // Copyright (c) 2015年 liming. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 18 | // Override point for customization after application launch. 19 | return true 20 | } 21 | 22 | func applicationWillResignActive(application: UIApplication) { 23 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 24 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 25 | } 26 | 27 | func applicationDidEnterBackground(application: UIApplication) { 28 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 29 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 30 | } 31 | 32 | func applicationWillEnterForeground(application: UIApplication) { 33 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 34 | } 35 | 36 | func applicationDidBecomeActive(application: UIApplication) { 37 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 38 | } 39 | 40 | func applicationWillTerminate(application: UIApplication) { 41 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 42 | } 43 | 44 | 45 | } 46 | 47 | -------------------------------------------------------------------------------- /AnyDoor/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /AnyDoor/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /AnyDoor/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /AnyDoor/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | me.liming.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /AnyDoor/Rinku.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Rinku.swift 3 | // Rinku 4 | // 5 | // Created by Rui Peres on 12/06/2014. 6 | // Edit by Alexander Li on 12/23/2014. 7 | // Copyright (c) 2014 Aphely. All rights reserved. 8 | // 9 | 10 | import Foundation 11 | 12 | let RinkuPost : String = "POST" 13 | let RinkuGet : String = "GET" 14 | 15 | public class Rinku { 16 | 17 | let request : NSMutableURLRequest 18 | 19 | init(httpMethod: String, endpointURL : String, httpHeaders : Dictionary?) { 20 | 21 | let url = NSURL(string: endpointURL) 22 | request = NSMutableURLRequest(URL: url!) 23 | request.HTTPMethod = httpMethod 24 | 25 | if let httpHeadersUnWrapped = httpHeaders { 26 | request.allHTTPHeaderFields = httpHeadersUnWrapped 27 | } 28 | } 29 | 30 | // Class Methods 31 | 32 | class func post(url :String) -> Rinku { 33 | return Rinku(httpMethod: RinkuPost, endpointURL: url, httpHeaders: nil) 34 | } 35 | 36 | class func get(url :String) -> Rinku { 37 | return Rinku(httpMethod: RinkuGet, endpointURL: url, httpHeaders: nil) 38 | } 39 | 40 | // Instance Methods 41 | 42 | func headers(headers : Dictionary) ->Rinku { 43 | request.allHTTPHeaderFields = headers 44 | return self 45 | } 46 | 47 | func auth(username:String, password:String) ->Rinku{ 48 | let authData:NSData = "\(username):\(password)".dataUsingEncoding(NSASCIIStringEncoding, allowLossyConversion: true)! 49 | let authStr:String = "Basic \(authData.base64EncodedStringWithOptions(NSDataBase64EncodingOptions.Encoding76CharacterLineLength))" 50 | request.setValue(authStr, forHTTPHeaderField: "Authorization") 51 | return self 52 | } 53 | 54 | func body(httpBody : NSData) -> Rinku { 55 | request.HTTPBody = httpBody 56 | return self 57 | } 58 | 59 | func form(dict: Dictionary) -> Rinku{ 60 | let postData:NSData = prepareForm(dict) 61 | request.setValue("application/x-www-form-urlencoded;charset=utf-8", forHTTPHeaderField: "Content-Type") 62 | request.setValue("\(postData.length)", forHTTPHeaderField: "Content-Length") 63 | request.HTTPBody = postData 64 | return self 65 | } 66 | 67 | func json(jsonString:String) -> Rinku{ 68 | let postData:NSData = jsonString.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! 69 | request.setValue("\(postData.length)", forHTTPHeaderField: "Content-Length") 70 | request.HTTPBody = postData 71 | return self 72 | } 73 | 74 | func file(fileData:NSData,filefield:String, filename:String, extForm:Dictionary) -> Rinku{ 75 | let boundary:String = "---------------------------\(randStr())" 76 | let contentType:String = "multipart/form-data; boundary=\(boundary)" 77 | request.setValue(contentType, forHTTPHeaderField: "Content-Type") 78 | let postData:NSMutableData = NSMutableData() 79 | postData.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 80 | 81 | for (field, value) in extForm{ 82 | //Content-Disposition: form-data; name=\"message\"\r\n\r\n%@ 83 | postData.appendData("Content-Disposition: form-data; name=\"\(field)\"\r\n\r\n\(value)".dataUsingEncoding(NSUTF8StringEncoding)!) 84 | postData.appendData("\r\n--\(boundary)\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 85 | } 86 | 87 | postData.appendData("Content-Disposition: form-data; name=\"\(filefield)\"; filename=\"\(filename)\"\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 88 | postData.appendData("Content-Type: application/octet-stream\r\n\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 89 | postData.appendData(fileData) 90 | postData.appendData("\r\n--\(boundary)--\r\n".dataUsingEncoding(NSUTF8StringEncoding)!) 91 | 92 | 93 | request.setValue("\(postData.length)", forHTTPHeaderField: "Content-Length") 94 | request.HTTPBody = postData 95 | return self 96 | } 97 | 98 | func completion(completion : (NSData!, NSURLResponse!, NSError!) -> ()) -> () { 99 | 100 | var session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil 101 | , delegateQueue: NSOperationQueue.mainQueue()) 102 | 103 | session.dataTaskWithRequest(self.request, completionHandler: completion).resume() 104 | } 105 | 106 | private func randStr()->String{ 107 | let pool:String = "qazxswedcvfrtgbnhyujmkiolp0987654321" 108 | let poolArr:Array = Array(pool) 109 | let tmp:NSMutableArray = NSMutableArray(capacity: 10) 110 | for idx in 0...10{ 111 | let random:Int = Int(arc4random_uniform(36)) 112 | tmp.addObject(String(poolArr[random])) 113 | } 114 | return tmp.componentsJoinedByString("") 115 | } 116 | 117 | private func prepareForm(dict: Dictionary) ->NSData{ 118 | let frames:NSMutableArray = NSMutableArray() 119 | for (key, value) in dict{ 120 | let encodedString:String = value.stringByAddingPercentEncodingWithAllowedCharacters(.URLFragmentAllowedCharacterSet())! 121 | frames.addObject(("\(key)=\(encodedString)")) 122 | } 123 | let postData:NSData = frames.componentsJoinedByString("&").dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)! 124 | return postData 125 | } 126 | 127 | } 128 | -------------------------------------------------------------------------------- /AnyDoor/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // AnyDoor 4 | // 5 | // Created by LiMing on 15/1/18. 6 | // Copyright (c) 2015年 liming. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController { 12 | 13 | override func viewDidLoad() { 14 | super.viewDidLoad() 15 | // Do any additional setup after loading the view, typically from a nib. 16 | 17 | 18 | } 19 | 20 | override func didReceiveMemoryWarning() { 21 | super.didReceiveMemoryWarning() 22 | // Dispose of any resources that can be recreated. 23 | } 24 | 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /AnyDoor/bgHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // bgHeader.h 3 | // testRecodeVideo 4 | // 5 | // Created by LiMing on 15/1/16. 6 | // Copyright (c) 2015年 miaomi. All rights reserved. 7 | // 8 | 9 | #ifndef testRecodeVideo_bgHeader_h 10 | #define testRecodeVideo_bgHeader_h 11 | 12 | #import 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /AnyDoorTests/AnyDoorTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AnyDoorTests.swift 3 | // AnyDoorTests 4 | // 5 | // Created by LiMing on 15/1/18. 6 | // Copyright (c) 2015年 liming. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class AnyDoorTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /AnyDoorTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | me.liming.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 压力很大同志 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 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AnyDoor (任意门)# 2 | Swift with no pain (让Swift不再蛋痛) 3 | 4 | ![door](http://homepage.ntu.edu.tw/~b01302158/images/01.jpg) 5 | 6 | >> what's new? YouPaiYun(又拍云) support added to NSData extension 7 | 8 | Swift is easy to use, but sometimes get some pain with it's strict type checking and optional type. How ever, we can extent origin types with extension, so i wrote some for String, NSData and a little wrapper for dictionary and array, make it easier to access items in dictionary or array 9 | 10 | Http access depends on Rinku from a very easy to use http lib. 11 | 12 | Because need import cocoa lib to support hmac algorithm, you need to add Objective-C bridge header file in project with next content: 13 | 14 | #import 15 | 16 | Extension for String 17 | ----------------------- 18 | a String extension 19 | 20 | ###Operator for String### 21 | 22 | let s = "a" * 5 // s = "aaaaa" 23 | 24 | ###Get substring by range:### 25 | 26 | abcde"[1, 3] 27 | 28 | it will return "bcd". 29 | 30 | and you can use negative index: 31 | 32 | "abcde"[1, -2] 33 | 34 | will return "bc" 35 | 36 | 37 | ###Check one string contains another string### 38 | 39 | "abcde".adContains("bc") 40 | 41 | will return true 42 | 43 | ###Get the index of a string be contained in another string### 44 | 45 | "abcde".adStartAt("bc") 46 | 47 | will return 1 and if substring not in it, will return -1 48 | 49 | ###Get JSON object### 50 | 51 | "{\"key\":123}".adJsonObject 52 | 53 | will return a wrapper object of the json Dictionary, we will talk about it later 54 | 55 | ###Check File exists### 56 | 57 | if String is a absolute path of a file, you can check if it exists in file system 58 | 59 | "path".adFileExists 60 | 61 | ###Get file data### 62 | 63 | if String is a absolute path of a file, you can get NSData like this: 64 | 65 | "path".adFileData 66 | 67 | ###Delete file### 68 | 69 | if String is a absolute path of a file, you can delete the file like this: 70 | 71 | "path".adFileDelete() 72 | 73 | ###Get File in QiNiu Yun(七牛云存储)### 74 | 75 | if the string is a key of public resouces in QiNiu Yun, you can get the file like: 76 | 77 | "qi niu key".adQiniuFileData("your qiniu domain").complete({(data, response, error)->Void in 78 | data.adSaveTo('file path') 79 | }) 80 | 81 | ###Get File in YouPai Yun(又拍云存储)### 82 | 83 | if the string is a key of public resouces in QiNiu Yun, you can get the file like: 84 | 85 | "you pai key".adYouPaiFileData("your YouPai domain").complete({(data, response, error)->Void in 86 | data.adSaveTo('file path') 87 | }) 88 | 89 | 90 | ###Transform to NSURL### 91 | 92 | if the string is an url, you can get NSURL object like this: 93 | 94 | "http://#".adToURL() 95 | 96 | ###Transform to File NSURL### 97 | 98 | if the string is a file url, you can get NSURL object like this: 99 | 100 | "file://#".adFileURL() 101 | 102 | ###Get absolute path string in system folder of a filename### 103 | 104 | if the string is a filename, you can get absolute path by this: 105 | 106 | "voice.wav".adFileInFolderString(NSSearchPathDirectory.DocumentDirectory) 107 | 108 | ###Get NSURL in system folder of a filename### 109 | 110 | if the string is a filename, you can get NSURL by this: 111 | 112 | "voice.wav".adFileInFolderURL(NSSearchPathDirectory.DocumentDirectory) 113 | 114 | ###Encrypt to urlsafe base64 string### 115 | 116 | "abcdefg".adToUrlSafeBase64String() 117 | 118 | will return a string encrypt to urlsafe base64 119 | 120 | ###Decrypt an urlsafe base64 string to origin string### 121 | 122 | "xafeWFrfrg==".adFromUrlSafeBase64String() 123 | 124 | will return the origin string of it 125 | 126 | ###HMAC hash a string with key### 127 | 128 | "abcdefg".adHmacEncrptHex(HMACAlgorithm.sha1) 129 | 130 | will return the hex string of hash result 131 | 132 | "abcdefg".adHmacEncrptData(HMACAlgorithm.sha1) 133 | 134 | will return the NSData object for furthor process 135 | 136 | ###Get UIImage by name### 137 | 138 | "avatar".adImage() 139 | 140 | ###Get resizableUIImage by name### 141 | 142 | "background".adResizableImage(10, 20, 5, 3) 143 | 144 | Extension of NSData 145 | --------------------------- 146 | a NSData extension 147 | 148 | ###Get wrapped json object### 149 | 150 | if you got this NSData object,maybe from http lib, or file,you can do like: 151 | 152 | data.adJsonObject 153 | 154 | ###Get UTF8 String### 155 | 156 | data.adUtf8String 157 | 158 | ###Get urlsafe base64 string### 159 | 160 | data.adToUrlSafeB64String() 161 | 162 | ##Transform to a Array### 163 | 164 | data.adAsArray(Byte) 165 | 166 | will return Array 167 | 168 | ###Upload File data to QiNiu Yun(七牛云存储)### 169 | 170 | data.adUploadToQiniu("avatar.jpg", accessKey:'access key', accessSecret:'access secret', scope:'scope name').complete({(data, response, error)->Void in 171 | let returnJson = data.adJsonObject 172 | let resourceKey:String = returnJson["key"].val(String) 173 | }) 174 | 175 | ###Upload File data to YouPai Yun(又拍云存储)### 176 | 177 | data.adUploadToYouPaiYun("avatar.jpg",bucket:'bucket name', securyKey:'access secret', form:[:]).complete({(data, response, error)->Void in 178 | let returnJson = data.adJsonObject 179 | }) 180 | 181 | more detail in : 182 | 183 | 184 | ###Safe NSData to a file### 185 | 186 | data.adSaveTo("file path") 187 | 188 | ###Get a file### 189 | 190 | NSData.adReadFile("file path") 191 | 192 | Array and Dictionary with no pain 193 | ----------------------- 194 | 195 | when you access a Dictionary or Array, you mostly thing to do is to fight with optional type not the data it self. Something like : 196 | 197 | let dict = ["aDict": ["aString": "string"], "anArray":[1,2,3,4]] 198 | let str:String = (dict["aDict"]! as Dictionary)["aString"]! 199 | let intvalue:Int = (dict["anArray"] as Array)[2] 200 | 201 | It's hard to write and hard to read. 202 | 203 | So i wrapped the Array and Dictionary with class ADAccessor to make it easier. 204 | 205 | extension adJsonObject in String and NSData will return the ADAccessor object wrapped the data(Array or Dictionary) 206 | 207 | let dict = ADAccessor(["aDict": ["aString": "string"], "anArray":[1,2,3,4]]) 208 | let str = dict["aDict"]["aString"].val(String) 209 | let intvalue:Int = dict["anArray"][2].val(Int) 210 | let intvalue:Int = dict["anArray"][2].val(NSNumber) 211 | 212 | than it's friendly to write and read 213 | --------------------------------------------------------------------------------