├── HanCamera.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── hanchang.xcuserdatad │ │ ├── UserInterfaceState.xcuserstate │ │ └── WorkspaceSettings.xcsettings └── xcuserdata │ └── hanchang.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── HanCamera.xcscheme │ └── xcschememanagement.plist ├── HanCamera ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── EditManager.h ├── EditManager.m ├── EditViewController.h ├── EditViewController.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── ViewController.h ├── ViewController.m ├── flashlightAuto.png ├── flashlightOff.png ├── flashlightOn.png ├── iTunesArtwork.png ├── main.m ├── snap.png ├── switchCamera.png ├── swtichCamera.png └── xxl.jpg └── HanCameraTests ├── HanCameraTests.m └── Info.plist /HanCamera.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 311B7F751A0BBA9F002083C9 /* iTunesArtwork.png in Resources */ = {isa = PBXBuildFile; fileRef = 311B7F741A0BBA9F002083C9 /* iTunesArtwork.png */; }; 11 | 3163BFDC1A0DB609008D75B4 /* flashlightAuto.png in Resources */ = {isa = PBXBuildFile; fileRef = 3163BFD91A0DB609008D75B4 /* flashlightAuto.png */; }; 12 | 3163BFDD1A0DB609008D75B4 /* flashlightOff.png in Resources */ = {isa = PBXBuildFile; fileRef = 3163BFDA1A0DB609008D75B4 /* flashlightOff.png */; }; 13 | 3163BFDE1A0DB609008D75B4 /* flashlightOn.png in Resources */ = {isa = PBXBuildFile; fileRef = 3163BFDB1A0DB609008D75B4 /* flashlightOn.png */; }; 14 | 3163BFE01A0DB64A008D75B4 /* snap.png in Resources */ = {isa = PBXBuildFile; fileRef = 3163BFDF1A0DB64A008D75B4 /* snap.png */; }; 15 | 3163BFE21A0DE649008D75B4 /* switchCamera.png in Resources */ = {isa = PBXBuildFile; fileRef = 3163BFE11A0DE648008D75B4 /* switchCamera.png */; }; 16 | 31BA4F861A11149C008089FC /* EditViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 31BA4F851A11149C008089FC /* EditViewController.m */; }; 17 | 31E2ED381A0B1B78008FB715 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 31E2ED371A0B1B78008FB715 /* main.m */; }; 18 | 31E2ED3B1A0B1B78008FB715 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 31E2ED3A1A0B1B78008FB715 /* AppDelegate.m */; }; 19 | 31E2ED3E1A0B1B78008FB715 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 31E2ED3D1A0B1B78008FB715 /* ViewController.m */; }; 20 | 31E2ED411A0B1B78008FB715 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 31E2ED3F1A0B1B78008FB715 /* Main.storyboard */; }; 21 | 31E2ED431A0B1B78008FB715 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 31E2ED421A0B1B78008FB715 /* Images.xcassets */; }; 22 | 31E2ED461A0B1B78008FB715 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 31E2ED441A0B1B78008FB715 /* LaunchScreen.xib */; }; 23 | 31E2ED521A0B1B78008FB715 /* HanCameraTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 31E2ED511A0B1B78008FB715 /* HanCameraTests.m */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | 31E2ED4C1A0B1B78008FB715 /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = 31E2ED2A1A0B1B78008FB715 /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = 31E2ED311A0B1B78008FB715; 32 | remoteInfo = HanCamera; 33 | }; 34 | /* End PBXContainerItemProxy section */ 35 | 36 | /* Begin PBXFileReference section */ 37 | 311B7F741A0BBA9F002083C9 /* iTunesArtwork.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = iTunesArtwork.png; sourceTree = ""; }; 38 | 3163BFD91A0DB609008D75B4 /* flashlightAuto.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flashlightAuto.png; sourceTree = ""; }; 39 | 3163BFDA1A0DB609008D75B4 /* flashlightOff.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flashlightOff.png; sourceTree = ""; }; 40 | 3163BFDB1A0DB609008D75B4 /* flashlightOn.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = flashlightOn.png; sourceTree = ""; }; 41 | 3163BFDF1A0DB64A008D75B4 /* snap.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = snap.png; sourceTree = ""; }; 42 | 3163BFE11A0DE648008D75B4 /* switchCamera.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = switchCamera.png; sourceTree = ""; }; 43 | 31BA4F841A11149C008089FC /* EditViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EditViewController.h; sourceTree = ""; }; 44 | 31BA4F851A11149C008089FC /* EditViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EditViewController.m; sourceTree = ""; }; 45 | 31E2ED321A0B1B78008FB715 /* HanCamera.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HanCamera.app; sourceTree = BUILT_PRODUCTS_DIR; }; 46 | 31E2ED361A0B1B78008FB715 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | 31E2ED371A0B1B78008FB715 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 48 | 31E2ED391A0B1B78008FB715 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 49 | 31E2ED3A1A0B1B78008FB715 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 50 | 31E2ED3C1A0B1B78008FB715 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 51 | 31E2ED3D1A0B1B78008FB715 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 52 | 31E2ED401A0B1B78008FB715 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 53 | 31E2ED421A0B1B78008FB715 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 54 | 31E2ED451A0B1B78008FB715 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 55 | 31E2ED4B1A0B1B78008FB715 /* HanCameraTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HanCameraTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 56 | 31E2ED501A0B1B78008FB715 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 31E2ED511A0B1B78008FB715 /* HanCameraTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HanCameraTests.m; sourceTree = ""; }; 58 | /* End PBXFileReference section */ 59 | 60 | /* Begin PBXFrameworksBuildPhase section */ 61 | 31E2ED2F1A0B1B78008FB715 /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 2147483647; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | 31E2ED481A0B1B78008FB715 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | ); 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | /* End PBXFrameworksBuildPhase section */ 76 | 77 | /* Begin PBXGroup section */ 78 | 3163BFD81A0DB5E4008D75B4 /* buttonImage */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | 3163BFE11A0DE648008D75B4 /* switchCamera.png */, 82 | 3163BFDF1A0DB64A008D75B4 /* snap.png */, 83 | 3163BFD91A0DB609008D75B4 /* flashlightAuto.png */, 84 | 3163BFDA1A0DB609008D75B4 /* flashlightOff.png */, 85 | 3163BFDB1A0DB609008D75B4 /* flashlightOn.png */, 86 | ); 87 | name = buttonImage; 88 | sourceTree = ""; 89 | }; 90 | 31E2ED291A0B1B78008FB715 = { 91 | isa = PBXGroup; 92 | children = ( 93 | 31E2ED341A0B1B78008FB715 /* HanCamera */, 94 | 31E2ED4E1A0B1B78008FB715 /* HanCameraTests */, 95 | 31E2ED331A0B1B78008FB715 /* Products */, 96 | ); 97 | sourceTree = ""; 98 | }; 99 | 31E2ED331A0B1B78008FB715 /* Products */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 31E2ED321A0B1B78008FB715 /* HanCamera.app */, 103 | 31E2ED4B1A0B1B78008FB715 /* HanCameraTests.xctest */, 104 | ); 105 | name = Products; 106 | sourceTree = ""; 107 | }; 108 | 31E2ED341A0B1B78008FB715 /* HanCamera */ = { 109 | isa = PBXGroup; 110 | children = ( 111 | 31E2ED391A0B1B78008FB715 /* AppDelegate.h */, 112 | 31E2ED3A1A0B1B78008FB715 /* AppDelegate.m */, 113 | 31E2ED3C1A0B1B78008FB715 /* ViewController.h */, 114 | 31E2ED3D1A0B1B78008FB715 /* ViewController.m */, 115 | 31BA4F841A11149C008089FC /* EditViewController.h */, 116 | 31BA4F851A11149C008089FC /* EditViewController.m */, 117 | 31E2ED3F1A0B1B78008FB715 /* Main.storyboard */, 118 | 31E2ED421A0B1B78008FB715 /* Images.xcassets */, 119 | 31E2ED441A0B1B78008FB715 /* LaunchScreen.xib */, 120 | 31E2ED351A0B1B78008FB715 /* Supporting Files */, 121 | ); 122 | path = HanCamera; 123 | sourceTree = ""; 124 | }; 125 | 31E2ED351A0B1B78008FB715 /* Supporting Files */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 3163BFD81A0DB5E4008D75B4 /* buttonImage */, 129 | 311B7F741A0BBA9F002083C9 /* iTunesArtwork.png */, 130 | 31E2ED361A0B1B78008FB715 /* Info.plist */, 131 | 31E2ED371A0B1B78008FB715 /* main.m */, 132 | ); 133 | name = "Supporting Files"; 134 | sourceTree = ""; 135 | }; 136 | 31E2ED4E1A0B1B78008FB715 /* HanCameraTests */ = { 137 | isa = PBXGroup; 138 | children = ( 139 | 31E2ED511A0B1B78008FB715 /* HanCameraTests.m */, 140 | 31E2ED4F1A0B1B78008FB715 /* Supporting Files */, 141 | ); 142 | path = HanCameraTests; 143 | sourceTree = ""; 144 | }; 145 | 31E2ED4F1A0B1B78008FB715 /* Supporting Files */ = { 146 | isa = PBXGroup; 147 | children = ( 148 | 31E2ED501A0B1B78008FB715 /* Info.plist */, 149 | ); 150 | name = "Supporting Files"; 151 | sourceTree = ""; 152 | }; 153 | /* End PBXGroup section */ 154 | 155 | /* Begin PBXNativeTarget section */ 156 | 31E2ED311A0B1B78008FB715 /* HanCamera */ = { 157 | isa = PBXNativeTarget; 158 | buildConfigurationList = 31E2ED551A0B1B78008FB715 /* Build configuration list for PBXNativeTarget "HanCamera" */; 159 | buildPhases = ( 160 | 31E2ED2E1A0B1B78008FB715 /* Sources */, 161 | 31E2ED2F1A0B1B78008FB715 /* Frameworks */, 162 | 31E2ED301A0B1B78008FB715 /* Resources */, 163 | ); 164 | buildRules = ( 165 | ); 166 | dependencies = ( 167 | ); 168 | name = HanCamera; 169 | productName = HanCamera; 170 | productReference = 31E2ED321A0B1B78008FB715 /* HanCamera.app */; 171 | productType = "com.apple.product-type.application"; 172 | }; 173 | 31E2ED4A1A0B1B78008FB715 /* HanCameraTests */ = { 174 | isa = PBXNativeTarget; 175 | buildConfigurationList = 31E2ED581A0B1B78008FB715 /* Build configuration list for PBXNativeTarget "HanCameraTests" */; 176 | buildPhases = ( 177 | 31E2ED471A0B1B78008FB715 /* Sources */, 178 | 31E2ED481A0B1B78008FB715 /* Frameworks */, 179 | 31E2ED491A0B1B78008FB715 /* Resources */, 180 | ); 181 | buildRules = ( 182 | ); 183 | dependencies = ( 184 | 31E2ED4D1A0B1B78008FB715 /* PBXTargetDependency */, 185 | ); 186 | name = HanCameraTests; 187 | productName = HanCameraTests; 188 | productReference = 31E2ED4B1A0B1B78008FB715 /* HanCameraTests.xctest */; 189 | productType = "com.apple.product-type.bundle.unit-test"; 190 | }; 191 | /* End PBXNativeTarget section */ 192 | 193 | /* Begin PBXProject section */ 194 | 31E2ED2A1A0B1B78008FB715 /* Project object */ = { 195 | isa = PBXProject; 196 | attributes = { 197 | LastUpgradeCheck = 0610; 198 | ORGANIZATIONNAME = "韩畅"; 199 | TargetAttributes = { 200 | 31E2ED311A0B1B78008FB715 = { 201 | CreatedOnToolsVersion = 6.1; 202 | }; 203 | 31E2ED4A1A0B1B78008FB715 = { 204 | CreatedOnToolsVersion = 6.1; 205 | TestTargetID = 31E2ED311A0B1B78008FB715; 206 | }; 207 | }; 208 | }; 209 | buildConfigurationList = 31E2ED2D1A0B1B78008FB715 /* Build configuration list for PBXProject "HanCamera" */; 210 | compatibilityVersion = "Xcode 3.2"; 211 | developmentRegion = English; 212 | hasScannedForEncodings = 0; 213 | knownRegions = ( 214 | en, 215 | Base, 216 | ); 217 | mainGroup = 31E2ED291A0B1B78008FB715; 218 | productRefGroup = 31E2ED331A0B1B78008FB715 /* Products */; 219 | projectDirPath = ""; 220 | projectRoot = ""; 221 | targets = ( 222 | 31E2ED311A0B1B78008FB715 /* HanCamera */, 223 | 31E2ED4A1A0B1B78008FB715 /* HanCameraTests */, 224 | ); 225 | }; 226 | /* End PBXProject section */ 227 | 228 | /* Begin PBXResourcesBuildPhase section */ 229 | 31E2ED301A0B1B78008FB715 /* Resources */ = { 230 | isa = PBXResourcesBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | 31E2ED411A0B1B78008FB715 /* Main.storyboard in Resources */, 234 | 3163BFDC1A0DB609008D75B4 /* flashlightAuto.png in Resources */, 235 | 31E2ED461A0B1B78008FB715 /* LaunchScreen.xib in Resources */, 236 | 3163BFDD1A0DB609008D75B4 /* flashlightOff.png in Resources */, 237 | 3163BFE21A0DE649008D75B4 /* switchCamera.png in Resources */, 238 | 311B7F751A0BBA9F002083C9 /* iTunesArtwork.png in Resources */, 239 | 3163BFE01A0DB64A008D75B4 /* snap.png in Resources */, 240 | 31E2ED431A0B1B78008FB715 /* Images.xcassets in Resources */, 241 | 3163BFDE1A0DB609008D75B4 /* flashlightOn.png in Resources */, 242 | ); 243 | runOnlyForDeploymentPostprocessing = 0; 244 | }; 245 | 31E2ED491A0B1B78008FB715 /* Resources */ = { 246 | isa = PBXResourcesBuildPhase; 247 | buildActionMask = 2147483647; 248 | files = ( 249 | ); 250 | runOnlyForDeploymentPostprocessing = 0; 251 | }; 252 | /* End PBXResourcesBuildPhase section */ 253 | 254 | /* Begin PBXSourcesBuildPhase section */ 255 | 31E2ED2E1A0B1B78008FB715 /* Sources */ = { 256 | isa = PBXSourcesBuildPhase; 257 | buildActionMask = 2147483647; 258 | files = ( 259 | 31E2ED3E1A0B1B78008FB715 /* ViewController.m in Sources */, 260 | 31E2ED3B1A0B1B78008FB715 /* AppDelegate.m in Sources */, 261 | 31BA4F861A11149C008089FC /* EditViewController.m in Sources */, 262 | 31E2ED381A0B1B78008FB715 /* main.m in Sources */, 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | 31E2ED471A0B1B78008FB715 /* Sources */ = { 267 | isa = PBXSourcesBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | 31E2ED521A0B1B78008FB715 /* HanCameraTests.m in Sources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | /* End PBXSourcesBuildPhase section */ 275 | 276 | /* Begin PBXTargetDependency section */ 277 | 31E2ED4D1A0B1B78008FB715 /* PBXTargetDependency */ = { 278 | isa = PBXTargetDependency; 279 | target = 31E2ED311A0B1B78008FB715 /* HanCamera */; 280 | targetProxy = 31E2ED4C1A0B1B78008FB715 /* PBXContainerItemProxy */; 281 | }; 282 | /* End PBXTargetDependency section */ 283 | 284 | /* Begin PBXVariantGroup section */ 285 | 31E2ED3F1A0B1B78008FB715 /* Main.storyboard */ = { 286 | isa = PBXVariantGroup; 287 | children = ( 288 | 31E2ED401A0B1B78008FB715 /* Base */, 289 | ); 290 | name = Main.storyboard; 291 | sourceTree = ""; 292 | }; 293 | 31E2ED441A0B1B78008FB715 /* LaunchScreen.xib */ = { 294 | isa = PBXVariantGroup; 295 | children = ( 296 | 31E2ED451A0B1B78008FB715 /* Base */, 297 | ); 298 | name = LaunchScreen.xib; 299 | sourceTree = ""; 300 | }; 301 | /* End PBXVariantGroup section */ 302 | 303 | /* Begin XCBuildConfiguration section */ 304 | 31E2ED531A0B1B78008FB715 /* Debug */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | ALWAYS_SEARCH_USER_PATHS = NO; 308 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 309 | CLANG_CXX_LIBRARY = "libc++"; 310 | CLANG_ENABLE_MODULES = YES; 311 | CLANG_ENABLE_OBJC_ARC = YES; 312 | CLANG_WARN_BOOL_CONVERSION = YES; 313 | CLANG_WARN_CONSTANT_CONVERSION = YES; 314 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 315 | CLANG_WARN_EMPTY_BODY = YES; 316 | CLANG_WARN_ENUM_CONVERSION = YES; 317 | CLANG_WARN_INT_CONVERSION = YES; 318 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 319 | CLANG_WARN_UNREACHABLE_CODE = YES; 320 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 321 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 322 | COPY_PHASE_STRIP = NO; 323 | ENABLE_STRICT_OBJC_MSGSEND = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu99; 325 | GCC_DYNAMIC_NO_PIC = NO; 326 | GCC_OPTIMIZATION_LEVEL = 0; 327 | GCC_PREPROCESSOR_DEFINITIONS = ( 328 | "DEBUG=1", 329 | "$(inherited)", 330 | ); 331 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 332 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 333 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 334 | GCC_WARN_UNDECLARED_SELECTOR = YES; 335 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 336 | GCC_WARN_UNUSED_FUNCTION = YES; 337 | GCC_WARN_UNUSED_VARIABLE = YES; 338 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 339 | MTL_ENABLE_DEBUG_INFO = YES; 340 | ONLY_ACTIVE_ARCH = YES; 341 | SDKROOT = iphoneos; 342 | }; 343 | name = Debug; 344 | }; 345 | 31E2ED541A0B1B78008FB715 /* Release */ = { 346 | isa = XCBuildConfiguration; 347 | buildSettings = { 348 | ALWAYS_SEARCH_USER_PATHS = NO; 349 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 350 | CLANG_CXX_LIBRARY = "libc++"; 351 | CLANG_ENABLE_MODULES = YES; 352 | CLANG_ENABLE_OBJC_ARC = YES; 353 | CLANG_WARN_BOOL_CONVERSION = YES; 354 | CLANG_WARN_CONSTANT_CONVERSION = YES; 355 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 356 | CLANG_WARN_EMPTY_BODY = YES; 357 | CLANG_WARN_ENUM_CONVERSION = YES; 358 | CLANG_WARN_INT_CONVERSION = YES; 359 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 360 | CLANG_WARN_UNREACHABLE_CODE = YES; 361 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 362 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 363 | COPY_PHASE_STRIP = YES; 364 | ENABLE_NS_ASSERTIONS = NO; 365 | ENABLE_STRICT_OBJC_MSGSEND = YES; 366 | GCC_C_LANGUAGE_STANDARD = gnu99; 367 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 368 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 369 | GCC_WARN_UNDECLARED_SELECTOR = YES; 370 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 371 | GCC_WARN_UNUSED_FUNCTION = YES; 372 | GCC_WARN_UNUSED_VARIABLE = YES; 373 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 374 | MTL_ENABLE_DEBUG_INFO = NO; 375 | SDKROOT = iphoneos; 376 | VALIDATE_PRODUCT = YES; 377 | }; 378 | name = Release; 379 | }; 380 | 31E2ED561A0B1B78008FB715 /* Debug */ = { 381 | isa = XCBuildConfiguration; 382 | buildSettings = { 383 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 384 | INFOPLIST_FILE = HanCamera/Info.plist; 385 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 386 | PRODUCT_NAME = "$(TARGET_NAME)"; 387 | }; 388 | name = Debug; 389 | }; 390 | 31E2ED571A0B1B78008FB715 /* Release */ = { 391 | isa = XCBuildConfiguration; 392 | buildSettings = { 393 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 394 | INFOPLIST_FILE = HanCamera/Info.plist; 395 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 396 | PRODUCT_NAME = "$(TARGET_NAME)"; 397 | }; 398 | name = Release; 399 | }; 400 | 31E2ED591A0B1B78008FB715 /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | BUNDLE_LOADER = "$(TEST_HOST)"; 404 | FRAMEWORK_SEARCH_PATHS = ( 405 | "$(SDKROOT)/Developer/Library/Frameworks", 406 | "$(inherited)", 407 | ); 408 | GCC_PREPROCESSOR_DEFINITIONS = ( 409 | "DEBUG=1", 410 | "$(inherited)", 411 | ); 412 | INFOPLIST_FILE = HanCameraTests/Info.plist; 413 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 414 | PRODUCT_NAME = "$(TARGET_NAME)"; 415 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HanCamera.app/HanCamera"; 416 | }; 417 | name = Debug; 418 | }; 419 | 31E2ED5A1A0B1B78008FB715 /* Release */ = { 420 | isa = XCBuildConfiguration; 421 | buildSettings = { 422 | BUNDLE_LOADER = "$(TEST_HOST)"; 423 | FRAMEWORK_SEARCH_PATHS = ( 424 | "$(SDKROOT)/Developer/Library/Frameworks", 425 | "$(inherited)", 426 | ); 427 | INFOPLIST_FILE = HanCameraTests/Info.plist; 428 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 429 | PRODUCT_NAME = "$(TARGET_NAME)"; 430 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/HanCamera.app/HanCamera"; 431 | }; 432 | name = Release; 433 | }; 434 | /* End XCBuildConfiguration section */ 435 | 436 | /* Begin XCConfigurationList section */ 437 | 31E2ED2D1A0B1B78008FB715 /* Build configuration list for PBXProject "HanCamera" */ = { 438 | isa = XCConfigurationList; 439 | buildConfigurations = ( 440 | 31E2ED531A0B1B78008FB715 /* Debug */, 441 | 31E2ED541A0B1B78008FB715 /* Release */, 442 | ); 443 | defaultConfigurationIsVisible = 0; 444 | defaultConfigurationName = Release; 445 | }; 446 | 31E2ED551A0B1B78008FB715 /* Build configuration list for PBXNativeTarget "HanCamera" */ = { 447 | isa = XCConfigurationList; 448 | buildConfigurations = ( 449 | 31E2ED561A0B1B78008FB715 /* Debug */, 450 | 31E2ED571A0B1B78008FB715 /* Release */, 451 | ); 452 | defaultConfigurationIsVisible = 0; 453 | defaultConfigurationName = Release; 454 | }; 455 | 31E2ED581A0B1B78008FB715 /* Build configuration list for PBXNativeTarget "HanCameraTests" */ = { 456 | isa = XCConfigurationList; 457 | buildConfigurations = ( 458 | 31E2ED591A0B1B78008FB715 /* Debug */, 459 | 31E2ED5A1A0B1B78008FB715 /* Release */, 460 | ); 461 | defaultConfigurationIsVisible = 0; 462 | defaultConfigurationName = Release; 463 | }; 464 | /* End XCConfigurationList section */ 465 | }; 466 | rootObject = 31E2ED2A1A0B1B78008FB715 /* Project object */; 467 | } 468 | -------------------------------------------------------------------------------- /HanCamera.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /HanCamera.xcodeproj/project.xcworkspace/xcuserdata/hanchang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera.xcodeproj/project.xcworkspace/xcuserdata/hanchang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /HanCamera.xcodeproj/project.xcworkspace/xcuserdata/hanchang.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /HanCamera.xcodeproj/xcuserdata/hanchang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 18 | 19 | 20 | 22 | 34 | 35 | 36 | 38 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /HanCamera.xcodeproj/xcuserdata/hanchang.xcuserdatad/xcschemes/HanCamera.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /HanCamera.xcodeproj/xcuserdata/hanchang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | HanCamera.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 31E2ED311A0B1B78008FB715 16 | 17 | primary 18 | 19 | 20 | 31E2ED4A1A0B1B78008FB715 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /HanCamera/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/6. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /HanCamera/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/6. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | - (void)applicationWillResignActive:(UIApplication *)application { 24 | // 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. 25 | // 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. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application { 29 | // 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. 30 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 31 | } 32 | 33 | - (void)applicationWillEnterForeground:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | - (void)applicationDidBecomeActive:(UIApplication *)application { 38 | // 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. 39 | } 40 | 41 | - (void)applicationWillTerminate:(UIApplication *)application { 42 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 43 | } 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /HanCamera/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /HanCamera/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 | 32 | 41 | 49 | 58 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | -------------------------------------------------------------------------------- /HanCamera/EditManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // EditManager.h 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/10. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface EditManager : NSObject 13 | @property UIImage *imageToEdit; 14 | @end 15 | -------------------------------------------------------------------------------- /HanCamera/EditManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // EditManager.m 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/10. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import "EditManager.h" 10 | 11 | @implementation EditManager 12 | @synthesize imageToEdit; 13 | @end 14 | -------------------------------------------------------------------------------- /HanCamera/EditViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // EditViewController.h 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/10. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface EditViewController : UIViewController 12 | @property UIImage* originalImage; 13 | @property UIImage* image; 14 | @property(nonatomic,retain) NSArray *pickerViewData; 15 | + (UIImage *) effectImage: (UIImage *)uIImage byFilterName:(NSString *)filterName; 16 | @end 17 | -------------------------------------------------------------------------------- /HanCamera/EditViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // EditViewController.m 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/10. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import "EditViewController.h" 10 | 11 | @interface EditViewController () 12 | @property (weak, nonatomic) IBOutlet UIImageView *editImageView; 13 | @property (weak, nonatomic) IBOutlet UIPickerView *effectPickerView; 14 | 15 | @end 16 | 17 | @implementation EditViewController 18 | 19 | - (void)viewDidLoad { 20 | [super viewDidLoad]; 21 | 22 | self.editImageView.contentMode = UIViewContentModeScaleAspectFit; 23 | self.editImageView.userInteractionEnabled = YES; 24 | 25 | self.effectPickerView.delegate = (id)self; 26 | self.editImageView.image = self.image; 27 | 28 | // 似乎只有一部分可以在 iOS 中使用 29 | NSArray *array=[[NSArray alloc] initWithObjects: 30 | @"None", 31 | // @"CIColorCrossPolynomial", 32 | // @"CIColorCube", 33 | // @"CIColorCubeWithColorSpace", 34 | // @"CIColorInvert", 35 | // @"CIColorMap", 36 | // @"CIColorMonochrome", 37 | // @"CIColorPosterize", 38 | @"CIFalseColor", 39 | // @"CIMaskToAlpha", 40 | // @"CIMaximumComponent", 41 | // @"CIMinimumComponent", 42 | @"CIPhotoEffectChrome", 43 | @"CIPhotoEffectFade", 44 | // @"CIPhotoEffectInstant", 45 | // @"CIPhotoEffectMono", 46 | // @"CIPhotoEffectNoir", 47 | // @"CIPhotoEffectProcess", 48 | // @"CIPhotoEffectTonal", 49 | // @"CIPhotoEffectTransfer", 50 | // @"CISepiaTone", 51 | // @"CIVignette", 52 | // @"CIVignetteEffect", 53 | nil]; 54 | [self setPickerViewData:array]; 55 | } 56 | 57 | -(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView 58 | { 59 | return 1; 60 | } 61 | 62 | -(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component 63 | { 64 | return [[self pickerViewData] count]; 65 | } 66 | 67 | -(UIView *)pickerView:(UIPickerView *)pickerView 68 | titleForRow:(NSInteger)row 69 | forComponent:(NSInteger)component 70 | { 71 | 72 | return [[self pickerViewData] objectAtIndex:row]; 73 | } 74 | 75 | 76 | // 选中 pickerview 的某行时会调用该函数。 77 | - (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 78 | NSString *filterName = [[self pickerViewData]objectAtIndex:row]; 79 | UIImage *newImage = [EditViewController effectImage:[self originalImage] byFilterName:filterName]; 80 | 81 | [self setImage:newImage]; 82 | [[self editImageView] setImage:newImage]; 83 | } 84 | 85 | // Cancel 按钮 86 | - (IBAction)clickCancelButton:(id)sender { 87 | [self dismissViewControllerAnimated:YES completion:^{ 88 | }]; 89 | } 90 | 91 | // Done 按钮 92 | - (IBAction)clickDoneButton:(id)sender { 93 | [self dismissViewControllerAnimated:YES completion:^{ 94 | }]; 95 | 96 | UIImageWriteToSavedPhotosAlbum([self image], self, nil, nil); // TODO 异常处理 97 | } 98 | 99 | - (void)didReceiveMemoryWarning { 100 | [super didReceiveMemoryWarning]; 101 | // Dispose of any resources that can be recreated. 102 | } 103 | 104 | // 滤镜 105 | + (UIImage *) effectImage: (UIImage *)uIImage byFilterName:(NSString *)filterName; 106 | { 107 | if ([filterName isEqualToString:@"None"]) { 108 | return uIImage; 109 | } 110 | 111 | UIImage *tempImage = [EditViewController scaleAndRotateImage:uIImage]; 112 | 113 | CIContext *context = [CIContext contextWithOptions:nil]; 114 | 115 | CIImage *ciImage = [[CIImage alloc] initWithImage:tempImage]; // 解决滤镜后图片方向不对的问题 116 | 117 | CIFilter *filter = [CIFilter filterWithName:filterName]; 118 | [filter setValue:ciImage forKey:kCIInputImageKey]; 119 | 120 | CIImage *result = [filter valueForKey:kCIOutputImageKey]; 121 | 122 | CGRect extent = [result extent]; 123 | 124 | CGImageRef cgImage = [context createCGImage:result fromRect:extent]; 125 | UIImage *filteredImage = [[UIImage alloc] initWithCGImage:cgImage]; 126 | CGImageRelease(cgImage); 127 | 128 | return filteredImage; 129 | } 130 | 131 | // Code from: http://discussions.apple.com/thread.jspa?messageID=7949889 132 | + (UIImage *)scaleAndRotateImage:(UIImage *)image { 133 | int kMaxResolution = 640; // Or whatever 134 | 135 | CGImageRef imgRef = image.CGImage; 136 | 137 | CGFloat width = CGImageGetWidth(imgRef); 138 | CGFloat height = CGImageGetHeight(imgRef); 139 | 140 | 141 | CGAffineTransform transform = CGAffineTransformIdentity; 142 | CGRect bounds = CGRectMake(0, 0, width, height); 143 | if (width > kMaxResolution || height > kMaxResolution) { 144 | CGFloat ratio = width/height; 145 | if (ratio > 1) { 146 | bounds.size.width = kMaxResolution; 147 | bounds.size.height = roundf(bounds.size.width / ratio); 148 | } 149 | else { 150 | bounds.size.height = kMaxResolution; 151 | bounds.size.width = roundf(bounds.size.height * ratio); 152 | } 153 | } 154 | 155 | CGFloat scaleRatio = bounds.size.width / width; 156 | CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); 157 | CGFloat boundHeight; 158 | UIImageOrientation orient = image.imageOrientation; 159 | switch(orient) { 160 | 161 | case UIImageOrientationUp: //EXIF = 1 162 | transform = CGAffineTransformIdentity; 163 | break; 164 | 165 | case UIImageOrientationUpMirrored: //EXIF = 2 166 | transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0); 167 | transform = CGAffineTransformScale(transform, -1.0, 1.0); 168 | break; 169 | 170 | case UIImageOrientationDown: //EXIF = 3 171 | transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); 172 | transform = CGAffineTransformRotate(transform, M_PI); 173 | break; 174 | 175 | case UIImageOrientationDownMirrored: //EXIF = 4 176 | transform = CGAffineTransformMakeTranslation(0.0, imageSize.height); 177 | transform = CGAffineTransformScale(transform, 1.0, -1.0); 178 | break; 179 | 180 | case UIImageOrientationLeftMirrored: //EXIF = 5 181 | boundHeight = bounds.size.height; 182 | bounds.size.height = bounds.size.width; 183 | bounds.size.width = boundHeight; 184 | transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width); 185 | transform = CGAffineTransformScale(transform, -1.0, 1.0); 186 | transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0); 187 | break; 188 | 189 | case UIImageOrientationLeft: //EXIF = 6 190 | boundHeight = bounds.size.height; 191 | bounds.size.height = bounds.size.width; 192 | bounds.size.width = boundHeight; 193 | transform = CGAffineTransformMakeTranslation(0.0, imageSize.width); 194 | transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0); 195 | break; 196 | 197 | case UIImageOrientationRightMirrored: //EXIF = 7 198 | boundHeight = bounds.size.height; 199 | bounds.size.height = bounds.size.width; 200 | bounds.size.width = boundHeight; 201 | transform = CGAffineTransformMakeScale(-1.0, 1.0); 202 | transform = CGAffineTransformRotate(transform, M_PI / 2.0); 203 | break; 204 | 205 | case UIImageOrientationRight: //EXIF = 8 206 | boundHeight = bounds.size.height; 207 | bounds.size.height = bounds.size.width; 208 | bounds.size.width = boundHeight; 209 | transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0); 210 | transform = CGAffineTransformRotate(transform, M_PI / 2.0); 211 | break; 212 | 213 | default: 214 | [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; 215 | 216 | } 217 | 218 | UIGraphicsBeginImageContext(bounds.size); 219 | 220 | CGContextRef context = UIGraphicsGetCurrentContext(); 221 | 222 | if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { 223 | CGContextScaleCTM(context, -scaleRatio, scaleRatio); 224 | CGContextTranslateCTM(context, -height, 0); 225 | } 226 | else { 227 | CGContextScaleCTM(context, scaleRatio, -scaleRatio); 228 | CGContextTranslateCTM(context, 0, -height); 229 | } 230 | 231 | CGContextConcatCTM(context, transform); 232 | 233 | CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef); 234 | UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); 235 | UIGraphicsEndImageContext(); 236 | 237 | return imageCopy; 238 | } 239 | /* 240 | #pragma mark - Navigation 241 | 242 | // In a storyboard-based application, you will often want to do a little preparation before navigation 243 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 244 | // Get the new view controller using [segue destinationViewController]. 245 | // Pass the selected object to the new view controller. 246 | } 247 | */ 248 | 249 | @end 250 | -------------------------------------------------------------------------------- /HanCamera/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 | } -------------------------------------------------------------------------------- /HanCamera/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | UIStatusBarHidden 6 | 7 | UIViewControllerBasedStatusBarAppearance 8 | 9 | CFBundleIconFiles 10 | 11 | iTunesArtwork 12 | 13 | CFBundleDevelopmentRegion 14 | en 15 | CFBundleExecutable 16 | $(EXECUTABLE_NAME) 17 | CFBundleIdentifier 18 | com.example.$(PRODUCT_NAME:rfc1034identifier) 19 | CFBundleInfoDictionaryVersion 20 | 6.0 21 | CFBundleName 22 | $(PRODUCT_NAME) 23 | CFBundlePackageType 24 | APPL 25 | CFBundleShortVersionString 26 | 1.0 27 | CFBundleSignature 28 | ???? 29 | CFBundleVersion 30 | 1 31 | LSRequiresIPhoneOS 32 | 33 | UILaunchStoryboardName 34 | LaunchScreen 35 | UIMainStoryboardFile 36 | Main 37 | UIRequiredDeviceCapabilities 38 | 39 | armv7 40 | 41 | UISupportedInterfaceOrientations 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationLandscapeLeft 45 | UIInterfaceOrientationLandscapeRight 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /HanCamera/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/6. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef enum : NSUInteger { 13 | hcCameraMode9to16, 14 | hcCameraMode1to1, 15 | hcCameraMode3to4, 16 | } hcCameraMode; 17 | 18 | @interface ViewController : UIViewController 19 | 20 | @property (nonatomic,retain) AVCaptureSession *session; 21 | @property AVCaptureStillImageOutput *imageOutput; 22 | @property AVCaptureVideoPreviewLayer *previewSubLayer; 23 | @property hcCameraMode cameraMode; 24 | 25 | #pragma mark Actions 26 | - (IBAction)clickSnapImageButton:(id)sender; 27 | - (IBAction)clickCameraRollButton:(id)sender; 28 | - (IBAction)clickSwitchCameraButton:(id)sender; 29 | - (IBAction)clickFlashlightButton:(id)sender; 30 | - (IBAction)clickProportionButton:(id)sender; 31 | 32 | @end 33 | 34 | -------------------------------------------------------------------------------- /HanCamera/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/6. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import "ViewController.h" 13 | #import "EditViewController.h" 14 | 15 | @interface ViewController () 16 | @property (weak, nonatomic) IBOutlet UIButton *proportionButton; 17 | @property (weak, nonatomic) IBOutlet UIButton *switchCameraButton; 18 | @property (weak, nonatomic) IBOutlet UIButton *snapButton; 19 | @property (weak, nonatomic) IBOutlet UIButton *flashlightButton; 20 | @property (weak, nonatomic) IBOutlet UIView *preview; 21 | @end 22 | 23 | @implementation ViewController 24 | 25 | @synthesize session; 26 | @synthesize imageOutput; 27 | @synthesize cameraMode; 28 | 29 | - (void)viewDidLoad { 30 | [super viewDidLoad]; 31 | 32 | [self setCameraMode:hcCameraMode9to16]; 33 | 34 | [[[self preview] layer] setBackgroundColor:[[UIColor blackColor]CGColor]]; 35 | 36 | // session 连接到 captureDevive 37 | [self setSession:[[AVCaptureSession alloc] init]]; 38 | 39 | AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 40 | AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:nil]; 41 | 42 | if ([[self session] canAddInput:deviceInput]) 43 | [[self session] addInput:deviceInput]; 44 | 45 | // 初始化界面按键 46 | [self initViewsOfButtons:captureDevice.flashMode]; 47 | 48 | // 预览 session 49 | [self loadPreviewLayer]; 50 | 51 | // output 52 | [self setImageOutput:[[AVCaptureStillImageOutput alloc] init]]; 53 | 54 | NSDictionary *setting = [[NSDictionary alloc]initWithObjectsAndKeys:AVVideoCodecJPEG, AVVideoCodecKey, nil]; 55 | [[self imageOutput] setOutputSettings:setting]; 56 | 57 | [session addOutput:self.imageOutput]; 58 | 59 | [[self session] startRunning]; 60 | } 61 | 62 | // 预览 session 63 | - (void) loadPreviewLayer { 64 | AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:[self session]]; 65 | 66 | CGFloat proportion = [self getPoportionByHcCameraMode:[self cameraMode]]; 67 | [previewLayer setFrame:[self getFrameByProportion:proportion]]; 68 | 69 | [previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill]; 70 | 71 | [[[self preview] layer] setMasksToBounds:YES]; 72 | [[[self preview] layer] insertSublayer:previewLayer atIndex:0]; 73 | } 74 | 75 | // 根据比例裁剪图片 76 | - (UIImage*) cropImageWithImage:(UIImage*) image proportion:(CGFloat)proportion { 77 | 78 | CGSize newSize = [self sizeWithSize:image.size poportion:proportion]; 79 | 80 | CGRect rect = CGRectMake(image.scale * (image.size.height / 2 - newSize.height / 2), 81 | image.scale * (image.size.width / 2 - newSize.width / 2), 82 | image.scale * newSize.height, 83 | image.scale * newSize.width); 84 | 85 | CGImageRef imageRef = CGImageCreateWithImageInRect(image.CGImage, rect); 86 | UIImage *newImage = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation]; 87 | 88 | CGImageRelease(imageRef); 89 | 90 | return newImage; 91 | } 92 | 93 | // 按照 size 缩放图片 94 | - (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize; 95 | { 96 | // Create a graphics image context 97 | UIGraphicsBeginImageContext(newSize); 98 | 99 | // Tell the old image to draw in this new context, with the desired 100 | // new size 101 | [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; 102 | 103 | // Get the new image from the context 104 | UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 105 | 106 | // End the context 107 | UIGraphicsEndImageContext(); 108 | 109 | // Return the new image. 110 | return newImage; 111 | } 112 | 113 | - (void)didReceiveMemoryWarning { 114 | [super didReceiveMemoryWarning]; 115 | // Dispose of any resources that can be recreated. 116 | } 117 | 118 | // 拍照按钮 119 | - (IBAction)clickSnapImageButton:(id)sender { 120 | 121 | // 闪光效果 122 | UIView *flashView = [[UIView alloc] initWithFrame:[[self preview] frame]]; 123 | [flashView setBackgroundColor:[UIColor blackColor]]; 124 | [[[self preview] window] addSubview:flashView]; 125 | 126 | [UIView animateWithDuration:.4f 127 | animations:^{ 128 | [flashView setAlpha:0.f]; 129 | } 130 | completion:^(BOOL finished){ 131 | [flashView removeFromSuperview]; 132 | }]; 133 | 134 | // 获取相机的连接 135 | AVCaptureConnection *connection = nil; 136 | for (AVCaptureConnection *tempConnection in self.imageOutput.connections) { 137 | for (AVCaptureInputPort *port in [tempConnection inputPorts]) { 138 | if ([[port mediaType] isEqual:AVMediaTypeVideo]) { 139 | connection = tempConnection; 140 | break; 141 | } 142 | } 143 | if (connection) { 144 | break; 145 | } 146 | } 147 | 148 | // 保存图片 149 | [self.imageOutput captureStillImageAsynchronouslyFromConnection:connection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) { 150 | NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer]; 151 | UIImage *image = [[UIImage alloc]initWithData:imageData]; 152 | // 切割图片 153 | CGFloat proportion = [self getPoportionByHcCameraMode:[self cameraMode]]; 154 | image = [self cropImageWithImage:image proportion:proportion]; 155 | 156 | [self presentEditViewController:image]; 157 | }]; 158 | } 159 | 160 | // 图片库按钮 161 | - (IBAction)clickCameraRollButton:(id)sender { 162 | 163 | if ([UIImagePickerController isSourceTypeAvailable: 164 | UIImagePickerControllerSourceTypeSavedPhotosAlbum]) 165 | { 166 | UIImagePickerController *imagePicker = 167 | [[UIImagePickerController alloc] init]; 168 | imagePicker.delegate = self; 169 | imagePicker.sourceType = 170 | UIImagePickerControllerSourceTypePhotoLibrary; 171 | imagePicker.mediaTypes = [NSArray arrayWithObjects: 172 | (NSString *) kUTTypeImage, 173 | nil]; 174 | imagePicker.allowsEditing = NO; 175 | [self presentViewController:imagePicker animated:YES completion:^(void){}]; 176 | } 177 | } 178 | 179 | // 图库选中了照片 180 | - (void)imagePickerController: (UIImagePickerController *)picker 181 | didFinishPickingMediaWithInfo: (NSDictionary *)info 182 | { 183 | NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType]; 184 | 185 | [picker dismissViewControllerAnimated:YES completion:^(void){}]; 186 | 187 | if ([mediaType isEqualToString:(NSString *)kUTTypeImage]) { 188 | UIImage *image = [info 189 | objectForKey:UIImagePickerControllerOriginalImage]; 190 | 191 | [self presentEditViewController:image]; 192 | } 193 | } 194 | 195 | - (void)presentEditViewController:(UIImage*) uiimage { 196 | UIImage *newImage = [EditViewController effectImage:uiimage byFilterName:@"None"]; 197 | 198 | EditViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"theEditView"]; 199 | 200 | [viewController setOriginalImage:uiimage]; 201 | [viewController setImage:newImage]; 202 | 203 | [self presentViewController:viewController animated:YES completion:^{ 204 | }]; 205 | } 206 | 207 | // 保存图片出现 error 208 | - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error 209 | contextInfo:(void *)contextInfo 210 | { 211 | if (error != NULL) 212 | { 213 | NSLog(@"error - didFinishSavingWithError"); 214 | 215 | } 216 | } 217 | 218 | // 获取相机 input 219 | - (AVCaptureDeviceInput *)getVideoInput { 220 | 221 | for (AVCaptureDeviceInput *input in self.session.inputs) { 222 | if ([input.device hasMediaType:AVMediaTypeVideo]) { 223 | return input; 224 | } 225 | } 226 | 227 | return nil; 228 | } 229 | 230 | // 前后摄像头按钮 231 | - (IBAction)clickSwitchCameraButton:(id)sender { 232 | 233 | AVCaptureDeviceInput *currentInput = [self getVideoInput]; 234 | 235 | if (currentInput) { 236 | AVCaptureDevicePosition newPosition = AVCaptureDevicePositionFront; 237 | if (currentInput.device.position == AVCaptureDevicePositionFront) { 238 | newPosition = AVCaptureDevicePositionBack; 239 | } 240 | 241 | AVCaptureDevice *newDevice = nil; 242 | NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; 243 | for (AVCaptureDevice *device in devices) 244 | { 245 | if ([device position] == newPosition) 246 | { 247 | newDevice = device; 248 | break; 249 | } 250 | } 251 | 252 | NSError *error; 253 | AVCaptureDeviceInput *newInput = [AVCaptureDeviceInput deviceInputWithDevice:newDevice error:&error]; 254 | 255 | [self.session beginConfiguration]; 256 | [self.session removeInput:currentInput]; 257 | [self.session addInput:newInput]; 258 | [self.session commitConfiguration]; 259 | 260 | // font camera 时隐藏闪光灯按钮 261 | if (newDevice.position == AVCaptureDevicePositionFront) { 262 | [self.flashlightButton setHidden:YES]; 263 | } else { 264 | [self.flashlightButton setHidden:NO]; 265 | } 266 | } 267 | } 268 | 269 | // 闪光灯按钮 270 | - (IBAction)clickFlashlightButton:(id)sender { 271 | AVCaptureDeviceInput *input = [self getVideoInput]; 272 | 273 | [input.device lockForConfiguration:nil]; 274 | 275 | if (input.device.flashMode == AVCaptureFlashModeAuto) { 276 | [input.device setFlashMode:AVCaptureFlashModeOff]; 277 | } else if (input.device.flashMode == AVCaptureFlashModeOff) { 278 | [input.device setFlashMode:AVCaptureFlashModeOn]; 279 | } else { 280 | [input.device setFlashMode:AVCaptureFlashModeAuto]; 281 | } 282 | 283 | [input.device unlockForConfiguration]; 284 | 285 | NSString *buttonTitle = [self getTitleByFlashlightMode:input.device.flashMode]; 286 | [[self flashlightButton] setTitle:buttonTitle forState:normal]; 287 | 288 | UIImage *buttonImage = [self getImageByFlashlightMode:input.device.flashMode]; 289 | buttonImage = [self imageWithImage:buttonImage scaledToSize:CGRectMake(0,0,40,40).size]; 290 | [[self flashlightButton] setImage:buttonImage forState:UIControlStateNormal]; 291 | 292 | } 293 | 294 | // 画幅比例按钮 295 | - (IBAction)clickProportionButton:(id)sender { 296 | 297 | hcCameraMode newCameraMode; 298 | if ([self cameraMode] == hcCameraMode3to4) { 299 | newCameraMode = hcCameraMode9to16; 300 | } else { 301 | newCameraMode = [self cameraMode] + 1; 302 | } 303 | [self setCameraMode:newCameraMode]; 304 | 305 | [[self proportionButton] setTitle:[self getTitleByCameraMode:[self cameraMode]] forState:UIControlStateNormal]; 306 | 307 | AVCaptureVideoPreviewLayer *subPreviewLayer = [[[[self preview] layer] sublayers] objectAtIndex:0]; 308 | [subPreviewLayer removeFromSuperlayer]; 309 | 310 | CGFloat proportion = [self getPoportionByHcCameraMode:[self cameraMode]]; 311 | CGRect rect = [self getFrameByProportion:proportion]; 312 | [subPreviewLayer setFrame:rect]; 313 | [[[self preview] layer] insertSublayer:subPreviewLayer atIndex:0]; 314 | } 315 | 316 | // 初始化按键 317 | - (void) initViewsOfButtons:(AVCaptureFlashMode) flashMode { 318 | 319 | // 闪光灯按钮 320 | NSString *buttonTitle = [self getTitleByFlashlightMode:flashMode]; 321 | [[self flashlightButton] setTitle:buttonTitle forState:normal]; 322 | 323 | UIImage *buttonImage = [self getImageByFlashlightMode:flashMode]; 324 | buttonImage = [self imageWithImage:buttonImage scaledToSize:CGRectMake(0,0,40,40).size]; 325 | [[self flashlightButton] setImage:buttonImage forState:UIControlStateNormal]; 326 | 327 | // 前后摄像头切换按钮 328 | [[self switchCameraButton] setTitle:@"" forState:UIControlStateNormal]; 329 | buttonImage = [UIImage imageNamed:@"switchCamera.png"]; 330 | buttonImage = [self imageWithImage:buttonImage scaledToSize:CGRectMake(0,0,40,40).size]; 331 | [[self switchCameraButton] setImage:buttonImage forState:UIControlStateNormal]; 332 | 333 | // 拍照按钮 334 | [[self snapButton] setTitle:@"" forState:UIControlStateNormal]; 335 | buttonImage = [UIImage imageNamed:@"snap.png"]; 336 | buttonImage = [self imageWithImage:buttonImage scaledToSize:CGRectMake(0,0,50,50).size]; 337 | [[self snapButton] setImage:buttonImage forState:UIControlStateNormal]; 338 | 339 | // 画布比例按钮 340 | [[self proportionButton] setTitle:[self getTitleByCameraMode:[self cameraMode]] forState:UIControlStateNormal]; 341 | } 342 | 343 | - (NSString *) getTitleByCameraMode:(hcCameraMode) theCameraMode{ 344 | NSString *buttonTitle; 345 | if (theCameraMode == hcCameraMode9to16) { 346 | buttonTitle = @"16:9"; 347 | } else if (theCameraMode == hcCameraMode1to1) { 348 | buttonTitle = @"1:1"; 349 | } else { // hcCameraMode3to4 350 | buttonTitle = @"4:3"; 351 | } 352 | 353 | return buttonTitle; 354 | } 355 | 356 | 357 | - (NSString *) getTitleByFlashlightMode:(AVCaptureFlashMode) flashMode { 358 | NSString *buttonTitle; 359 | if (flashMode == AVCaptureFlashModeAuto) { 360 | buttonTitle = @"Auto"; 361 | } else if (flashMode == AVCaptureFlashModeOff) { 362 | buttonTitle = @"Off"; 363 | } else { 364 | buttonTitle = @"On"; 365 | } 366 | 367 | return buttonTitle; 368 | } 369 | 370 | - (UIImage *) getImageByFlashlightMode:(AVCaptureFlashMode) flashMode { 371 | 372 | NSString *imageName; 373 | if (flashMode == AVCaptureFlashModeAuto) { 374 | imageName = @"flashlightAuto.png"; 375 | } else if (flashMode == AVCaptureFlashModeOff) { 376 | imageName = @"flashlightOff.png"; 377 | } else { // AVCaptureFlashModeOn 378 | imageName = @"flashlightOn.png"; 379 | } 380 | 381 | UIImage *buttonImage = [UIImage imageNamed:imageName]; 382 | 383 | return buttonImage; 384 | } 385 | 386 | // 根据比例获得缩小后的 size 387 | - (CGSize) sizeWithSize:(CGSize) size poportion:(CGFloat) proportion{ 388 | 389 | CGSize screenSize = [[UIScreen mainScreen] bounds].size; 390 | CGFloat screenProportion = screenSize.width / screenSize.height; 391 | 392 | CGSize newSize; 393 | if (proportion > screenProportion) { 394 | newSize.width = size.width; 395 | newSize.height = size.width / proportion; 396 | } else { 397 | newSize.height = size.height; 398 | newSize.width = size.height * proportion; 399 | } 400 | 401 | return newSize; 402 | } 403 | 404 | // 根据 cameraMode 获取比例 405 | - (CGFloat) getPoportionByHcCameraMode:(hcCameraMode) theCameraMode { 406 | 407 | if (theCameraMode == hcCameraMode1to1) { 408 | return 1.0 / 1.0; 409 | } else if (theCameraMode == hcCameraMode3to4) { 410 | return 3.0 / 4.0; 411 | } else {// hcCameraMode9to16 412 | return 9.0 / 16.0; 413 | } 414 | } 415 | 416 | // 根据比例获取 frame 417 | - (CGRect) getFrameByProportion:(CGFloat) proportion { 418 | CGSize screenSize = [[UIScreen mainScreen] bounds].size; 419 | 420 | CGSize newSize = [self sizeWithSize:screenSize poportion:proportion]; 421 | 422 | return CGRectMake(screenSize.width / 2 - newSize.width / 2, 423 | screenSize.height / 2 - newSize.height / 2, 424 | newSize.width, 425 | newSize.height); 426 | } 427 | 428 | 429 | @end 430 | -------------------------------------------------------------------------------- /HanCamera/flashlightAuto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera/flashlightAuto.png -------------------------------------------------------------------------------- /HanCamera/flashlightOff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera/flashlightOff.png -------------------------------------------------------------------------------- /HanCamera/flashlightOn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera/flashlightOn.png -------------------------------------------------------------------------------- /HanCamera/iTunesArtwork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera/iTunesArtwork.png -------------------------------------------------------------------------------- /HanCamera/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // HanCamera 4 | // 5 | // Created by 韩畅 on 14/11/6. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /HanCamera/snap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera/snap.png -------------------------------------------------------------------------------- /HanCamera/switchCamera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera/switchCamera.png -------------------------------------------------------------------------------- /HanCamera/swtichCamera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera/swtichCamera.png -------------------------------------------------------------------------------- /HanCamera/xxl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mirhan/HanCamera/b556abb733dbabe115427f7d95894012c357f159/HanCamera/xxl.jpg -------------------------------------------------------------------------------- /HanCameraTests/HanCameraTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // HanCameraTests.m 3 | // HanCameraTests 4 | // 5 | // Created by 韩畅 on 14/11/6. 6 | // Copyright (c) 2014年 韩畅. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface HanCameraTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation HanCameraTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /HanCameraTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.example.$(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 | --------------------------------------------------------------------------------