├── net.sixfivezero.BKCameraController.docset └── Contents │ ├── Resources │ ├── docSet.mom │ ├── docSet.toc │ ├── docSet.dsidx │ ├── docSet.skidx │ ├── docSet.dsidx-shm │ ├── docSet.dsidx-wal │ ├── docSet.tokencache │ ├── Tokens3.xml │ ├── Tokens4.xml │ ├── Documents │ │ ├── img │ │ │ ├── disclosure.png │ │ │ ├── disclosure_open.png │ │ │ ├── title_background.png │ │ │ ├── library_background.png │ │ │ └── button_bar_background.png │ │ ├── css │ │ │ ├── stylesPrint.css │ │ │ └── styles.css │ │ ├── index.html │ │ ├── hierarchy.html │ │ ├── Blocks │ │ │ ├── asset_capture_completion_t.html │ │ │ └── ciimage_capture_completion_t.html │ │ ├── Protocols │ │ │ └── BKCameraControllerDelegate.html │ │ └── Classes │ │ │ └── BKCameraController.html │ ├── Tokens2.xml │ ├── Nodes.xml │ └── Tokens1.xml │ └── Info.plist ├── BKCameraController.podspec ├── LICENSE ├── BKCameraController ├── BKCameraController+Simulator.h ├── BKCameraController+Simulator.m ├── BKCameraController.h └── BKCameraController.m ├── .gitignore ├── README.md └── BKCameraController.xcodeproj └── project.pbxproj /net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.mom: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.mom -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.toc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.toc -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.dsidx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.dsidx -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.skidx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.skidx -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.dsidx-shm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.dsidx-shm -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.dsidx-wal: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.dsidx-wal -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.tokencache: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/docSet.tokencache -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Tokens3.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Tokens4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/disclosure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/disclosure.png -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/disclosure_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/disclosure_open.png -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/title_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/title_background.png -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/library_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/library_background.png -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/button_bar_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/basket/BKCameraController/master/net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/img/button_bar_background.png -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/css/stylesPrint.css: -------------------------------------------------------------------------------- 1 | 2 | header { 3 | display: none; 4 | } 5 | 6 | div.main-navigation, div.navigation-top { 7 | display: none; 8 | } 9 | 10 | div#overview_contents, div#contents.isShowingTOC, div#contents { 11 | overflow: visible; 12 | position: relative; 13 | top: 0px; 14 | border: none; 15 | left: 0; 16 | } 17 | #tocContainer.isShowingTOC { 18 | display: none; 19 | } 20 | nav { 21 | display: none; 22 | } -------------------------------------------------------------------------------- /BKCameraController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "BKCameraController" 3 | s.version = "0.0.1" 4 | s.summary = "A class to simplify the process of capturing photos and make testing in the simulator less of a hassle for photo-based apps." 5 | s.homepage = "https://github.com/Basket/BKCameraController" 6 | s.license = 'MIT' 7 | s.author = { "Andrew Toulouse" => "andrew@atoulou.se" } 8 | s.source = { :git => "https://github.com/Basket/BKCameraController.git", :tag => s.version.to_s } 9 | 10 | s.platform = :ios, '7.0' 11 | s.requires_arc = true 12 | 13 | s.source_files = 'BKCameraController/*.{h,m}' 14 | s.frameworks = 'AssetsLibrary', 'AVFoundation', 'CoreMedia', 'ImageIO', 'UIKit' 15 | end 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 650 Industries, Inc. 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /BKCameraController/BKCameraController+Simulator.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014-present 650 Industries. All rights reserved. 2 | 3 | #import "BKCameraController.h" 4 | 5 | @class CIColor; 6 | @class UIColor; 7 | 8 | @interface BKCameraController (Simulator) 9 | 10 | /** 11 | Getter for the fake image data used by the simulator. 12 | 13 | @return The fake image data used by the simulator. 14 | */ 15 | + (NSData *)fakeImageData; 16 | 17 | /** 18 | Setter for the fake image data used by the simulator 19 | 20 | @param fakeImageData The fake image data to be used by the simulator. 21 | */ 22 | + (void)setFakeImageData:(NSData *)fakeImageData; 23 | 24 | /** 25 | Getter for the fake image color used by the simulator. 26 | 27 | @return The fake image color used by the simulator. 28 | */ 29 | + (CIColor *)fakeImageColor; 30 | 31 | /** 32 | Setter for the fake image color used by the simulator 33 | 34 | @param fakeImageColor The fake image color to be used by the simulator. 35 | */ 36 | + (void)setFakeImageColor:(NSData *)fakeImageColor; 37 | 38 | /** 39 | Setter for fake image color from UIColor 40 | 41 | @param fakeImageColor UIColor 42 | */ 43 | + (void)setFakeImageColorFromUIColor:(UIColor *)fakeImageColor; 44 | 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleIdentifier 8 | net.sixfivezero.BKCameraController 9 | CFBundleName 10 | BKCameraController Documentation 11 | CFBundleShortVersionString 12 | 1.0 13 | CFBundleVersion 14 | 1.0 15 | 16 | 17 | 18 | 19 | DocSetFeedName 20 | BKCameraController Documentation 21 | 22 | DocSetMinimumXcodeVersion 23 | 3.0 24 | DocSetPlatformFamily 25 | iphoneos 26 | DashDocSetFamily 27 | appledoc 28 | DocSetPublisherIdentifier 29 | net.sixfivezero.documentation 30 | DocSetPublisherName 31 | 650 Industries, Inc. 32 | NSHumanReadableCopyright 33 | Copyright © 2014 650 Industries, Inc.. All rights reserved. 34 | 35 | 36 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Tokens2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | //apple_ref/occ/intf/BKCameraControllerDelegate 7 | The delegate of a BKCameraController object must adopt the <BKCameraControllerDelegate> protocol. 8 | BKCameraController.h 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | //apple_ref/occ/intfm/BKCameraControllerDelegate/cameraControllerWillCyclePosition: 17 | Tells the delegate that the camera controller will cycle the camera position. 18 | BKCameraController.h 19 | 20 | - (void)cameraControllerWillCyclePosition:(id)cameraController 21 | 22 | 23 | cameraController 24 | The camera controller object informing the delegate of this event. 25 | 26 | 27 | 28 | //api/name/cameraControllerWillCyclePosition: 29 | 30 | 31 | 32 | 33 | //apple_ref/occ/intfm/BKCameraControllerDelegate/cameraControllerDidCyclePosition: 34 | Tells the delegate that the camera controller cycled the camera position. 35 | BKCameraController.h 36 | 37 | - (void)cameraControllerDidCyclePosition:(id)cameraController 38 | 39 | 40 | cameraController 41 | The camera controller that cycled position. 42 | 43 | 44 | 45 | //api/name/cameraControllerDidCyclePosition: 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BKCameraController Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

BKCameraController

14 | 650 Industries, Inc. 15 |
16 | 17 | 20 | 21 |
22 |
23 |
24 | 27 | 32 |
33 | 34 | 35 | 36 | 37 | 38 |
39 |

Class References

40 | 45 |
46 | 47 | 48 | 49 |
50 | 51 |

Protocol References

52 | 57 | 58 | 59 | 60 |

Block References

61 | 68 | 69 | 70 |
71 | 72 |
73 | 76 | 86 |
87 |
88 | 89 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/hierarchy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BKCameraController Hierarchy 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

BKCameraController

14 | 650 Industries, Inc. 15 |
16 | 17 | 20 | 21 |
22 |
23 |
24 | 27 | 32 |
33 | 34 |
35 |

Class Hierarchy

36 | 37 | 48 | 49 |
50 | 51 | 52 | 53 |
54 | 55 |

Protocol References

56 | 61 | 62 | 63 | 64 |

Block References

65 | 72 | 73 | 74 |
75 | 76 |
77 | 80 | 90 |
91 |
92 | 93 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # .gitignore file for Xcode4 / OS X Source projects 3 | # 4 | # Version 2.0 5 | # For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects 6 | # 7 | # 2013 updates: 8 | # - fixed the broken "save personal Schemes" 9 | # 10 | # NB: if you are storing "built" products, this WILL NOT WORK, 11 | # and you should use a different .gitignore (or none at all) 12 | # This file is for SOURCE projects, where there are many extra 13 | # files that we want to exclude 14 | # 15 | ######################### 16 | 17 | ##### 18 | # OS X temporary files that should never be committed 19 | 20 | .DS_Store 21 | *.swp 22 | *.lock 23 | profile 24 | 25 | 26 | #### 27 | # Xcode temporary files that should never be committed 28 | # 29 | # NB: NIB/XIB files still exist even on Storyboard projects, so we want this... 30 | 31 | *~.nib 32 | 33 | 34 | #### 35 | # Xcode build files - 36 | # 37 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData" 38 | 39 | DerivedData/ 40 | 41 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build" 42 | 43 | build/ 44 | 45 | 46 | ##### 47 | # Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups) 48 | # 49 | # This is complicated: 50 | # 51 | # SOMETIMES you need to put this file in version control. 52 | # Apple designed it poorly - if you use "custom executables", they are 53 | # saved in this file. 54 | # 99% of projects do NOT use those, so they do NOT want to version control this file. 55 | # ..but if you're in the 1%, comment out the line "*.pbxuser" 56 | 57 | *.pbxuser 58 | *.mode1v3 59 | *.mode2v3 60 | *.perspectivev3 61 | # NB: also, whitelist the default ones, some projects need to use these 62 | !default.pbxuser 63 | !default.mode1v3 64 | !default.mode2v3 65 | !default.perspectivev3 66 | 67 | 68 | #### 69 | # Xcode 4 - semi-personal settings 70 | # 71 | # 72 | # OPTION 1: --------------------------------- 73 | # throw away ALL personal settings (including custom schemes! 74 | # - unless they are "shared") 75 | # 76 | # NB: this is exclusive with OPTION 2 below 77 | xcuserdata 78 | 79 | # OPTION 2: --------------------------------- 80 | # get rid of ALL personal settings, but KEEP SOME OF THEM 81 | # - NB: you must manually uncomment the bits you want to keep 82 | # 83 | # NB: this is exclusive with OPTION 1 above 84 | # 85 | #xcuserdata/**/* 86 | 87 | # (requires option 2 above): Personal Schemes 88 | # 89 | #!xcuserdata/**/xcschemes/* 90 | 91 | #### 92 | # XCode 4 workspaces - more detailed 93 | # 94 | # Workspaces are important! They are a core feature of Xcode - don't exclude them :) 95 | # 96 | # Workspace layout is quite spammy. For reference: 97 | # 98 | # /(root)/ 99 | # /(project-name).xcodeproj/ 100 | # project.pbxproj 101 | # /project.xcworkspace/ 102 | # contents.xcworkspacedata 103 | # /xcuserdata/ 104 | # /(your name)/xcuserdatad/ 105 | # UserInterfaceState.xcuserstate 106 | # /xcsshareddata/ 107 | # /xcschemes/ 108 | # (shared scheme name).xcscheme 109 | # /xcuserdata/ 110 | # /(your name)/xcuserdatad/ 111 | # (private scheme).xcscheme 112 | # xcschememanagement.plist 113 | # 114 | # 115 | 116 | #### 117 | # Xcode 4 - Deprecated classes 118 | # 119 | # Allegedly, if you manually "deprecate" your classes, they get moved here. 120 | # 121 | # We're using source-control, so this is a "feature" that we do not want! 122 | 123 | *.moved-aside 124 | 125 | 126 | #### 127 | # UNKNOWN: recommended by others, but I can't discover what these files are 128 | # 129 | # ...none. Everything is now explained. -------------------------------------------------------------------------------- /BKCameraController/BKCameraController+Simulator.m: -------------------------------------------------------------------------------- 1 | // Copyright 2014-present 650 Industries. All rights reserved. 2 | 3 | #import "BKCameraController+Simulator.h" 4 | 5 | @import AssetsLibrary; 6 | @import CoreImage; 7 | @import ObjectiveC; 8 | @import UIKit; 9 | 10 | @interface BKCameraController () 11 | @property (nonatomic, strong) dispatch_queue_t avQueue; 12 | @end 13 | 14 | void __swizzled_captureAssetWithCompletion(BKCameraController *self, SEL _cmd, asset_capture_completion_t completion) { 15 | dispatch_async(self.avQueue, ^{ 16 | NSData *data = [BKCameraController fakeImageData]; 17 | ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; 18 | [assetsLibrary writeImageDataToSavedPhotosAlbum:data metadata:nil completionBlock:^(NSURL *assetURL, NSError *error) { 19 | if (error) { 20 | dispatch_async(dispatch_get_main_queue(), ^{ 21 | completion(nil, error); 22 | }); 23 | } else { 24 | dispatch_async(dispatch_get_main_queue(), ^{ 25 | completion(assetURL, nil); 26 | }); 27 | } 28 | }]; 29 | }); 30 | } 31 | 32 | void __swizzled_captureSampleWithCompletion(BKCameraController *self, SEL _cmd, ciimage_capture_completion_t completion) { 33 | dispatch_async(((BKCameraController *)self).avQueue, ^{ 34 | CIImage *image; 35 | if ([BKCameraController fakeImageData]) { 36 | image = [CIImage imageWithData:[BKCameraController fakeImageData]]; 37 | } else { 38 | CIColor *fakeImageColor = [BKCameraController fakeImageColor]; 39 | if (!fakeImageColor) { 40 | CGFloat hue = ( arc4random() % 256 / 256.0 ); // 0.0 to 1.0 41 | CGFloat saturation = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from white 42 | CGFloat brightness = ( arc4random() % 128 / 256.0 ) + 0.5; // 0.5 to 1.0, away from black 43 | UIColor *color = [UIColor colorWithHue:hue saturation:saturation brightness:brightness alpha:1]; 44 | fakeImageColor = [CIColor colorWithCGColor:color.CGColor]; 45 | } 46 | image = [CIImage imageWithColor:fakeImageColor]; 47 | } 48 | 49 | dispatch_async(dispatch_get_main_queue(), ^{ 50 | completion(image, nil); 51 | }); 52 | }); 53 | } 54 | 55 | @implementation BKCameraController (Simulator) 56 | 57 | static IMP __original_captureAssetWithCompletion; 58 | static IMP __original_captureSampleWithCompletion; 59 | + (void)load 60 | { 61 | if ([[[UIDevice currentDevice].model lowercaseString] rangeOfString:@"simulator"].location != NSNotFound){ 62 | Method assetMethod = class_getInstanceMethod([self class], @selector(captureAssetWithCompletion:)); 63 | IMP assetImp = (IMP)__swizzled_captureAssetWithCompletion; 64 | __original_captureAssetWithCompletion = method_setImplementation(assetMethod, assetImp); 65 | 66 | Method sampleMethod = class_getInstanceMethod([self class], @selector(captureSampleWithCompletion:)); 67 | IMP sampleImp = (IMP)__swizzled_captureSampleWithCompletion; 68 | __original_captureSampleWithCompletion = method_setImplementation(sampleMethod, sampleImp); 69 | } 70 | } 71 | 72 | static NSData *_fakeImageData; 73 | 74 | + (NSData *)fakeImageData 75 | { 76 | return _fakeImageData; 77 | } 78 | 79 | + (void)setFakeImageData:(NSData *)fakeImageData; 80 | { 81 | _fakeImageData = fakeImageData; 82 | } 83 | 84 | static CIColor *_fakeImageColor; 85 | 86 | + (CIColor *)fakeImageColor 87 | { 88 | return _fakeImageColor; 89 | } 90 | 91 | + (void)setFakeImageColor:(CIColor *)fakeImageColor 92 | { 93 | _fakeImageColor = fakeImageColor; 94 | } 95 | 96 | + (void)setFakeImageColorFromUIColor:(UIColor *)fakeImageColor 97 | { 98 | _fakeImageColor = [CIColor colorWithCGColor:fakeImageColor.CGColor]; 99 | } 100 | 101 | @end 102 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Nodes.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BKCameraController 6 | index.html 7 | 8 | 9 | 10 | 11 | Classes 12 | index.html 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | Protocols 23 | index.html 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | Blocks 34 | index.html 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | BKCameraController 49 | Classes/BKCameraController.html 50 | 51 | 52 | 53 | Classes/BKCameraController.html 54 | Overview 55 | overview 56 | 57 | 58 | Classes/BKCameraController.html 59 | Tasks 60 | tasks 61 | 62 | 63 | 64 | Classes/BKCameraController.html 65 | Properties 66 | properties 67 | 68 | 69 | 70 | 71 | Classes/BKCameraController.html 72 | Class Methods 73 | class_methods 74 | 75 | 76 | 77 | 78 | Classes/BKCameraController.html 79 | Instance Methods 80 | instance_methods 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | BKCameraControllerDelegate 90 | Protocols/BKCameraControllerDelegate.html 91 | 92 | 93 | 94 | Protocols/BKCameraControllerDelegate.html 95 | Overview 96 | overview 97 | 98 | 99 | Protocols/BKCameraControllerDelegate.html 100 | Tasks 101 | tasks 102 | 103 | 104 | 105 | 106 | 107 | Protocols/BKCameraControllerDelegate.html 108 | Instance Methods 109 | instance_methods 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | asset_capture_completion_t 119 | Blocks/asset_capture_completion_t.html 120 | 121 | 122 | 123 | ciimage_capture_completion_t 124 | Blocks/ciimage_capture_completion_t.html 125 | 126 | 127 | 128 | 129 | -------------------------------------------------------------------------------- /BKCameraController/BKCameraController.h: -------------------------------------------------------------------------------- 1 | // Copyright 2014-present 650 Industries. All rights reserved. 2 | 3 | @import AVFoundation.AVCaptureDevice; 4 | @import AVFoundation.AVCaptureSession; 5 | 6 | @class CIImage; 7 | @protocol BKCameraControllerDelegate; 8 | 9 | /** Completion callback invoked upon capture. */ 10 | typedef void (^ciimage_capture_completion_t)(CIImage *image, NSError *error); 11 | 12 | /** Completion callback invoked upon asset capture. */ 13 | typedef void (^asset_capture_completion_t)(NSURL *assetURL, NSError *error); 14 | 15 | /** 16 | A wrapper for AVCaptureSession to simplify the process of capturing photos. 17 | */ 18 | @interface BKCameraController : NSObject 19 | 20 | /** 21 | The receiver’s delegate or nil if it doesn’t have a delegate. 22 | 23 | @discussion For a list of methods your delegate object can implement, see [BKCameraControllerDelegate Protocol Reference](BKCameraControllerDelegate) 24 | */ 25 | @property (nonatomic, weak) id delegate; 26 | 27 | /** The controller-owned `AVCaptureSession` instance. */ 28 | @property (nonatomic, strong, readonly) AVCaptureSession *session; 29 | /** The current camera position. */ 30 | @property (nonatomic, assign, readonly) AVCaptureDevicePosition position; 31 | /** The current camera flash mode. */ 32 | @property (nonatomic, assign, readonly) AVCaptureFlashMode flashMode; 33 | /** Whether the current camera has the capability to flash. */ 34 | @property (nonatomic, assign, readonly) BOOL flashCapable; 35 | 36 | /** @name Initializing a BKCameraController object */ 37 | 38 | /** 39 | Initializes the camera controller using the specified starting parameters. 40 | 41 | @param position The position used to select the initial capture device used by the camera controller. Defaults to `AVCaptureDevicePositionBack`. 42 | @param enabled YES if the camera controller should include `AVCaptureFlashModeAuto` when cycling the flash mode. Defaults to `NO`. 43 | @return An initialized `BKCameraController` instance. 44 | */ 45 | - (instancetype)initWithInitialPosition:(AVCaptureDevicePosition)position 46 | autoFlashEnabled:(BOOL)enabled __attribute__((objc_designated_initializer)); 47 | 48 | /** @name Starting/Stopping Capture Session State */ 49 | 50 | /** 51 | Tells the receiver to start the capture session. 52 | 53 | @discussion This method is used to start the receiver's capture session. This method is asynchronous and runs on a serial background queue owned by the receiver. 54 | */ 55 | - (void)startCaptureSession; 56 | 57 | /** 58 | Tells the receiver to stop the capture session. 59 | 60 | @discussion This method is used to stop the receiver's capture session. This method is asynchronous and runs on a serial background queue owned by the receiver. 61 | */ 62 | - (void)stopCaptureSession; 63 | 64 | /** @name Adjusting Camera Settings */ 65 | 66 | /** 67 | Sets the focus and exposure point to the specified point, if supported. 68 | 69 | @param point The point to set the exposure and focus. 70 | */ 71 | - (void)autoAdjustCameraToPoint:(CGPoint)point; 72 | 73 | /** 74 | Cycles through supported flash modes. Skips `AVCaptureFlashModeAuto` if the receiver was initialized with `autoFlashEnabled` set to `NO`. 75 | */ 76 | - (void)cycleFlashMode; 77 | 78 | /** 79 | Cycles through supported flash modes. If no flash mode at all is supported (such as on the front-facing camera), is set to `NO`, otherwise `YES`. 80 | */ 81 | - (void)cyclePosition; 82 | 83 | /** @name Capturing Photos */ 84 | 85 | /** 86 | Capture a photo and save it, along with its EXIF metadata, to the camera roll. 87 | 88 | @param completion A completion block supplying either a valid Asset or a . Executed on the main thread. 89 | 90 | - *assetURL* The Asset URL to the captured media. nil if an error occurred. 91 | - *error* The error, if a problem occurred during capture. 92 | */ 93 | - (void)captureAssetWithCompletion:(asset_capture_completion_t)completion; 94 | 95 | /** 96 | Capture a photo. 97 | 98 | @param completion A completion block supplying either a or a . Executed on the main thread. 99 | 100 | - *image* A CIImage wrapping the sample buffer's pixel buffer, captured by the camera. nil if an error occurred. 101 | - *error* The error, if a problem occurred during capture. 102 | */ 103 | - (void)captureSampleWithCompletion:(ciimage_capture_completion_t)completion; 104 | @end 105 | 106 | /** 107 | The delegate of a object must adopt the protocol. 108 | */ 109 | @protocol BKCameraControllerDelegate 110 | 111 | @optional 112 | 113 | /** 114 | Tells the delegate that the camera controller will cycle the camera position. 115 | 116 | @param cameraController The camera controller object informing the delegate of this event. 117 | */ 118 | - (void)cameraControllerWillCyclePosition:(BKCameraController *)cameraController; 119 | 120 | /** 121 | Tells the delegate that the camera controller cycled the camera position. 122 | 123 | @param cameraController The camera controller that cycled position. 124 | */ 125 | - (void)cameraControllerDidCyclePosition:(BKCameraController *)cameraController; 126 | 127 | @end 128 | 129 | #if TARGET_IPHONE_SIMULATOR 130 | #import "BKCameraController+Simulator.h" 131 | #endif 132 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/Blocks/asset_capture_completion_t.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | asset_capture_completion_t Block Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 17 | 18 | 21 | 36 |
37 | 46 |
47 |
48 | 49 | 55 | 60 |
61 | 62 |
63 | 64 | 65 | 66 | 67 |
Declared inBKCameraController.h
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |

Block Definition

81 |

asset_capture_completion_t

82 | 83 | 84 |
85 |

Completion callback invoked upon asset capture.

86 |
87 | 88 | 89 | 90 | typedef void (^asset_capture_completion_t) (NSURL *assetURL, NSError *error) 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 |
103 |

Declared In

104 | BKCameraController.h
105 |
106 | 107 | 108 | 109 | 110 |
111 | 117 | 126 |
127 |
128 | 219 | 220 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/Blocks/ciimage_capture_completion_t.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ciimage_capture_completion_t Block Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 17 | 18 | 21 | 36 |
37 | 46 |
47 |
48 | 49 | 55 | 60 |
61 | 62 |
63 | 64 | 65 | 66 | 67 |
Declared inBKCameraController.h
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 |

Block Definition

81 |

ciimage_capture_completion_t

82 | 83 | 84 |
85 |

Completion callback invoked upon capture.

86 |
87 | 88 | 89 | 90 | typedef void (^ciimage_capture_completion_t) (CIImage *image, NSError *error) 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 |
103 |

Declared In

104 | BKCameraController.h
105 |
106 | 107 | 108 | 109 | 110 |
111 | 117 | 126 |
127 |
128 | 219 | 220 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BKCameraController 2 | 3 | A class to simplify the process of capturing photos and make testing in the simulator less of a hassle for photo-based apps. 4 | 5 | ## Installation 6 | 7 | 1. Add BKCameraController to your Podfile. 8 | 2. In your terminal, run `pod install`. 9 | 10 | ## Usage 11 | 12 | 13 | 1. Add `#import ` to your source file. 14 | 2. Initialize the camera controller: `_cameraController = [[BKCameraController alloc] initWithInitialPosition:AVCaptureDevicePositionBack autoFlashEnabled:YES];` (The default camera position is the front, and auto-flash is disabled by default) 15 | 3. Call `- (void)startCaptureSession` to start capturing and `- (void)stopCaptureSession` to stop capturing. One good place to do this is in `- (void)viewWillAppear:` and `- (void)viewDidDisppear:`, so the camera doesn't overheat from being left on. 16 | 4. Use the `session` property as necessary, i.e. for camera preview layers, and the other methods for camera position cycling, flash mode cycling, focus adjustment, and photo capture callbacks. 17 | 5. Add the following to set the camera controller's image response for testing in the simulator, revising the path as necessary: 18 | ```objc 19 | #if TARGET_IPHONE_SIMULATOR 20 | [BKCameraController setFakeImageData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"file:///path-to/image.jpeg"]]]; 21 | #endif 22 | ``` 23 | 24 | ## FAQ 25 | 26 | **Q:** Why is this necessary? 27 | **A:** **You can use it in the simulator!** Testing in the simulator is insanely annoying when some functions simply aren't available. However, it's not always reasonable to expect the simulator to virtualize the response of low-level frameworks. 28 | 29 | AVFoundation is a complex and very useful API, but every application that wants to customize its photo-taking experience needs to opt into this API, even when their needs are fairly straightforward. Because of this complexity, it's not hard to achieve an end result that works, but is subpar. For example, AVFoundation works best when it runs on a background queue, so that its blocking operations don't affect the main thread -- but not everyone does this. 30 | 31 | This is an ideal problem to solve with an abstraction layer to serve those typical needs. In creating a standard component to interface with AVFoundation for the camera, we can also take on a little extra complexity and use a background queue properly on behalf of the consumers of BKCameraController's API. 32 | 33 | *tl;dr:* __BKCameraController is usable in the simulator, and doesn't block the main (UI) thread.__ 34 | 35 | **Q:** My photos are rotated weirdly! What gives? 36 | **A:** Well, the camera doesn't necessarily return the photo rotated with the direction "up" necessarily what you'd expect. It's not currently clear what the best approach to this is -- i.e. internally correct, offer a method in the public API to perform the transformation, or leave it to the developer -- but this snippet of code may prove useful for common use: 37 | 38 | ```objc 39 | [_cameraController captureSampleWithCompletion:^(CIImage *image, NSError *error) { 40 | dispatch_async(dispatch_get_main_queue(), ^{ 41 | UIImage *photo; 42 | 43 | if (error) { 44 | NSLog(@"WARNING: Couldn't capture photo: %@", error); 45 | photo = nil; 46 | } else { 47 | CGFloat screenScale = [UIScreen mainScreen].scale; 48 | CGSize photoSizeInPixels = CGSizeMake(CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds)); 49 | 50 | // Compute the scale from the source image to the output image, both measured in pixels 51 | size_t outputWidth = ceil(photoSizeInPixels.width); 52 | size_t outputHeight = ceil(photoSizeInPixels.height); 53 | 54 | // Swap the width and height since the source image is rotated 55 | size_t inputWidth = CGRectGetHeight(image.extent); 56 | size_t inputHeight = CGRectGetWidth(image.extent); 57 | 58 | CGFloat scale = fmax((CGFloat)outputWidth / inputWidth, (CGFloat)outputHeight / inputHeight); 59 | 60 | // Normalize the orientation 61 | CGAffineTransform transform; 62 | if (_videoPreview.connection.isVideoMirrored) { 63 | transform = CGAffineTransformMakeRotation(M_PI_2); 64 | 65 | transform = CGAffineTransformTranslate(transform, inputWidth, 0); 66 | transform = CGAffineTransformScale(transform, -1, 1); 67 | } else { 68 | transform = CGAffineTransformMakeRotation(3 * M_PI_2); 69 | } 70 | 71 | // Scale the image 72 | transform = CGAffineTransformScale(transform, scale, scale); 73 | CIImage *transformedImage = [image imageByApplyingTransform:transform]; 74 | 75 | // Crop the scaled image 76 | CGRect cropRect = CGRectCenterInRect(CGRectFromSize(photoSizeInPixels), [transformedImage extent]); 77 | CIImage *correctedImage = [transformedImage imageByCroppingToRect:cropRect]; 78 | photo = [UIImage imageWithCIImage:correctedImage scale:screenScale orientation:UIImageOrientationUp]; 79 | } 80 | 81 | // Do something with UIImage *photo here 82 | }); 83 | }]; 84 | ``` 85 | 86 | Note that this code requires access to the `AVCaptureConnection` to determine whether or not to mirror the image. 87 | 88 | **Q:** Why does direct capturing use `CIImage`? Why not `CMSampleBuffer` or `CVPixelBuffer`? Why not `CGImage`? 89 | **A:** The original interface *did* use `CMSampleBuffer`, but that's before simulator support was added. One of the goals is to be able to very cheaply transform the photo once taken, with as little loss of information as possible. Rendering to a `CGImage` only to have to re-import *that* into a `CIImage` is a wasted transformation. 90 | 91 | While it seems theoretically possible to render a `CGImage` into a `CVPixelBuffer`, and in turn to a `CMSampleBuffer`, and to preserve the metadata dictionary -- and indeed this was the initial approach to adding simulator support -- `+[CIImage imageWithCVPixelBuffer:]` is either picky about its input format, or is simply non-functional in the iOS Simulator, and during development, only ever seemed to return `nil`. Additionally, there were many parameters to specify for the conversion to `CVPixelBuffer` and `CMSampleBuffer` which made assumptions about the image type (JPEG/PNG), color space, and color format -- assumptions that might not have held true for all example images. 92 | 93 | Relegating `CMSampleBuffer` and `CVPixelBuffer` to implementation details of the `CIImage` presented to the user on devices allowed the simulator to take a much simpler path and simply use the more forgiving `+[CIImage imageWithData:` initializer. 94 | 95 | *tl;dr:* __BKCameraController is fast and simple.__ 96 | 97 | **Q:** Support for video? Still Image brackets? 98 | **A:** Definitely possible, but also not something being actively worked on. Pull requests are very much welcome! 99 | 100 | **Q:** This sucks! 101 | **Q:** It doesn't do X! 102 | **Q:** The way you structured your API sucks! 103 | **A:** This was built to make taking photos smooth. If you have a specific need, I'd be happy to incorporate that input into future revisions. If you have any suggestions or bug reports, please feel free to file an issue on GitHub. And if there's any concrete way to improve the API, I'd love to hear your input! 104 | 105 | ## Documentation 106 | 107 | BKCameraController is fully documented. Check out the included docset! 108 | -------------------------------------------------------------------------------- /BKCameraController.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6B4F31B8198B10C7009B4667 /* BKCameraController+Simulator.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B4F31B7198B10C7009B4667 /* BKCameraController+Simulator.m */; }; 11 | 6BEE0A8F1987255200D73B41 /* BKCameraController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 6BEE0A8E1987255200D73B41 /* BKCameraController.h */; }; 12 | 6BEE0A911987255200D73B41 /* BKCameraController.m in Sources */ = {isa = PBXBuildFile; fileRef = 6BEE0A901987255200D73B41 /* BKCameraController.m */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXCopyFilesBuildPhase section */ 16 | 6BEE0A891987255200D73B41 /* CopyFiles */ = { 17 | isa = PBXCopyFilesBuildPhase; 18 | buildActionMask = 2147483647; 19 | dstPath = "include/$(PRODUCT_NAME)"; 20 | dstSubfolderSpec = 16; 21 | files = ( 22 | 6BEE0A8F1987255200D73B41 /* BKCameraController.h in CopyFiles */, 23 | ); 24 | runOnlyForDeploymentPostprocessing = 0; 25 | }; 26 | /* End PBXCopyFilesBuildPhase section */ 27 | 28 | /* Begin PBXFileReference section */ 29 | 6B4F31B6198B10C7009B4667 /* BKCameraController+Simulator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BKCameraController+Simulator.h"; sourceTree = ""; }; 30 | 6B4F31B7198B10C7009B4667 /* BKCameraController+Simulator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "BKCameraController+Simulator.m"; sourceTree = ""; }; 31 | 6BEE0A8B1987255200D73B41 /* libBKCameraController.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libBKCameraController.a; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 6BEE0A8E1987255200D73B41 /* BKCameraController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BKCameraController.h; sourceTree = ""; }; 33 | 6BEE0A901987255200D73B41 /* BKCameraController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BKCameraController.m; sourceTree = ""; }; 34 | /* End PBXFileReference section */ 35 | 36 | /* Begin PBXFrameworksBuildPhase section */ 37 | 6BEE0A881987255200D73B41 /* Frameworks */ = { 38 | isa = PBXFrameworksBuildPhase; 39 | buildActionMask = 2147483647; 40 | files = ( 41 | ); 42 | runOnlyForDeploymentPostprocessing = 0; 43 | }; 44 | /* End PBXFrameworksBuildPhase section */ 45 | 46 | /* Begin PBXGroup section */ 47 | 6BEE0A821987255200D73B41 = { 48 | isa = PBXGroup; 49 | children = ( 50 | 6BEE0A8D1987255200D73B41 /* BKCameraController */, 51 | 6BEE0A8C1987255200D73B41 /* Products */, 52 | ); 53 | sourceTree = ""; 54 | }; 55 | 6BEE0A8C1987255200D73B41 /* Products */ = { 56 | isa = PBXGroup; 57 | children = ( 58 | 6BEE0A8B1987255200D73B41 /* libBKCameraController.a */, 59 | ); 60 | name = Products; 61 | sourceTree = ""; 62 | }; 63 | 6BEE0A8D1987255200D73B41 /* BKCameraController */ = { 64 | isa = PBXGroup; 65 | children = ( 66 | 6B4F31B6198B10C7009B4667 /* BKCameraController+Simulator.h */, 67 | 6B4F31B7198B10C7009B4667 /* BKCameraController+Simulator.m */, 68 | 6BEE0A8E1987255200D73B41 /* BKCameraController.h */, 69 | 6BEE0A901987255200D73B41 /* BKCameraController.m */, 70 | ); 71 | path = BKCameraController; 72 | sourceTree = ""; 73 | }; 74 | /* End PBXGroup section */ 75 | 76 | /* Begin PBXNativeTarget section */ 77 | 6BEE0A8A1987255200D73B41 /* BKCameraController */ = { 78 | isa = PBXNativeTarget; 79 | buildConfigurationList = 6BEE0A9F1987255200D73B41 /* Build configuration list for PBXNativeTarget "BKCameraController" */; 80 | buildPhases = ( 81 | 6BEE0A871987255200D73B41 /* Sources */, 82 | 6BEE0A881987255200D73B41 /* Frameworks */, 83 | 6BEE0A891987255200D73B41 /* CopyFiles */, 84 | ); 85 | buildRules = ( 86 | ); 87 | dependencies = ( 88 | ); 89 | name = BKCameraController; 90 | productName = BKCameraController; 91 | productReference = 6BEE0A8B1987255200D73B41 /* libBKCameraController.a */; 92 | productType = "com.apple.product-type.library.static"; 93 | }; 94 | /* End PBXNativeTarget section */ 95 | 96 | /* Begin PBXProject section */ 97 | 6BEE0A831987255200D73B41 /* Project object */ = { 98 | isa = PBXProject; 99 | attributes = { 100 | LastUpgradeCheck = 0600; 101 | ORGANIZATIONNAME = "650 Industries, Inc."; 102 | TargetAttributes = { 103 | 6BEE0A8A1987255200D73B41 = { 104 | CreatedOnToolsVersion = 6.0; 105 | }; 106 | }; 107 | }; 108 | buildConfigurationList = 6BEE0A861987255200D73B41 /* Build configuration list for PBXProject "BKCameraController" */; 109 | compatibilityVersion = "Xcode 3.2"; 110 | developmentRegion = English; 111 | hasScannedForEncodings = 0; 112 | knownRegions = ( 113 | en, 114 | ); 115 | mainGroup = 6BEE0A821987255200D73B41; 116 | productRefGroup = 6BEE0A8C1987255200D73B41 /* Products */; 117 | projectDirPath = ""; 118 | projectRoot = ""; 119 | targets = ( 120 | 6BEE0A8A1987255200D73B41 /* BKCameraController */, 121 | ); 122 | }; 123 | /* End PBXProject section */ 124 | 125 | /* Begin PBXSourcesBuildPhase section */ 126 | 6BEE0A871987255200D73B41 /* Sources */ = { 127 | isa = PBXSourcesBuildPhase; 128 | buildActionMask = 2147483647; 129 | files = ( 130 | 6B4F31B8198B10C7009B4667 /* BKCameraController+Simulator.m in Sources */, 131 | 6BEE0A911987255200D73B41 /* BKCameraController.m in Sources */, 132 | ); 133 | runOnlyForDeploymentPostprocessing = 0; 134 | }; 135 | /* End PBXSourcesBuildPhase section */ 136 | 137 | /* Begin XCBuildConfiguration section */ 138 | 6BEE0A9D1987255200D73B41 /* Debug */ = { 139 | isa = XCBuildConfiguration; 140 | buildSettings = { 141 | ALWAYS_SEARCH_USER_PATHS = NO; 142 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 143 | CLANG_CXX_LIBRARY = "libc++"; 144 | CLANG_ENABLE_MODULES = YES; 145 | CLANG_ENABLE_OBJC_ARC = YES; 146 | CLANG_WARN_BOOL_CONVERSION = YES; 147 | CLANG_WARN_CONSTANT_CONVERSION = YES; 148 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 149 | CLANG_WARN_EMPTY_BODY = YES; 150 | CLANG_WARN_ENUM_CONVERSION = YES; 151 | CLANG_WARN_INT_CONVERSION = YES; 152 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 153 | CLANG_WARN_UNREACHABLE_CODE = YES; 154 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 155 | COPY_PHASE_STRIP = NO; 156 | ENABLE_STRICT_OBJC_MSGSEND = YES; 157 | GCC_C_LANGUAGE_STANDARD = gnu99; 158 | GCC_DYNAMIC_NO_PIC = NO; 159 | GCC_OPTIMIZATION_LEVEL = 0; 160 | GCC_PREPROCESSOR_DEFINITIONS = ( 161 | "DEBUG=1", 162 | "$(inherited)", 163 | ); 164 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 165 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 166 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 167 | GCC_WARN_UNDECLARED_SELECTOR = YES; 168 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 169 | GCC_WARN_UNUSED_FUNCTION = YES; 170 | GCC_WARN_UNUSED_VARIABLE = YES; 171 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 172 | MTL_ENABLE_DEBUG_INFO = YES; 173 | ONLY_ACTIVE_ARCH = YES; 174 | SDKROOT = iphoneos; 175 | }; 176 | name = Debug; 177 | }; 178 | 6BEE0A9E1987255200D73B41 /* Release */ = { 179 | isa = XCBuildConfiguration; 180 | buildSettings = { 181 | ALWAYS_SEARCH_USER_PATHS = NO; 182 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 183 | CLANG_CXX_LIBRARY = "libc++"; 184 | CLANG_ENABLE_MODULES = YES; 185 | CLANG_ENABLE_OBJC_ARC = YES; 186 | CLANG_WARN_BOOL_CONVERSION = YES; 187 | CLANG_WARN_CONSTANT_CONVERSION = YES; 188 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 189 | CLANG_WARN_EMPTY_BODY = YES; 190 | CLANG_WARN_ENUM_CONVERSION = YES; 191 | CLANG_WARN_INT_CONVERSION = YES; 192 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 193 | CLANG_WARN_UNREACHABLE_CODE = YES; 194 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 195 | COPY_PHASE_STRIP = YES; 196 | ENABLE_NS_ASSERTIONS = NO; 197 | ENABLE_STRICT_OBJC_MSGSEND = YES; 198 | GCC_C_LANGUAGE_STANDARD = gnu99; 199 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 200 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 201 | GCC_WARN_UNDECLARED_SELECTOR = YES; 202 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 203 | GCC_WARN_UNUSED_FUNCTION = YES; 204 | GCC_WARN_UNUSED_VARIABLE = YES; 205 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 206 | MTL_ENABLE_DEBUG_INFO = NO; 207 | SDKROOT = iphoneos; 208 | VALIDATE_PRODUCT = YES; 209 | }; 210 | name = Release; 211 | }; 212 | 6BEE0AA01987255200D73B41 /* Debug */ = { 213 | isa = XCBuildConfiguration; 214 | buildSettings = { 215 | OTHER_LDFLAGS = "-ObjC"; 216 | PRODUCT_NAME = "$(TARGET_NAME)"; 217 | SKIP_INSTALL = YES; 218 | }; 219 | name = Debug; 220 | }; 221 | 6BEE0AA11987255200D73B41 /* Release */ = { 222 | isa = XCBuildConfiguration; 223 | buildSettings = { 224 | OTHER_LDFLAGS = "-ObjC"; 225 | PRODUCT_NAME = "$(TARGET_NAME)"; 226 | SKIP_INSTALL = YES; 227 | }; 228 | name = Release; 229 | }; 230 | /* End XCBuildConfiguration section */ 231 | 232 | /* Begin XCConfigurationList section */ 233 | 6BEE0A861987255200D73B41 /* Build configuration list for PBXProject "BKCameraController" */ = { 234 | isa = XCConfigurationList; 235 | buildConfigurations = ( 236 | 6BEE0A9D1987255200D73B41 /* Debug */, 237 | 6BEE0A9E1987255200D73B41 /* Release */, 238 | ); 239 | defaultConfigurationIsVisible = 0; 240 | defaultConfigurationName = Release; 241 | }; 242 | 6BEE0A9F1987255200D73B41 /* Build configuration list for PBXNativeTarget "BKCameraController" */ = { 243 | isa = XCConfigurationList; 244 | buildConfigurations = ( 245 | 6BEE0AA01987255200D73B41 /* Debug */, 246 | 6BEE0AA11987255200D73B41 /* Release */, 247 | ); 248 | defaultConfigurationIsVisible = 0; 249 | defaultConfigurationName = Release; 250 | }; 251 | /* End XCConfigurationList section */ 252 | }; 253 | rootObject = 6BEE0A831987255200D73B41 /* Project object */; 254 | } 255 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/Protocols/BKCameraControllerDelegate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BKCameraControllerDelegate Protocol Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 17 | 18 | 21 | 55 |
56 | 87 |
88 |
89 | 90 | 96 | 101 |
102 | 103 |
104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 |
Conforms toNSObject
Declared inBKCameraController.h
112 | 113 | 114 | 115 | 116 |
117 | 118 |

Overview

119 |

The delegate of a BKCameraController object must adopt the protocol.

120 |
121 | 122 | 123 | 124 | 125 | 126 |
127 | 128 |

Tasks

129 | 130 | 131 | 132 | 133 | 134 | 149 | 150 |
151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 |
161 | 162 |

Instance Methods

163 | 164 |
165 | 166 |

cameraControllerDidCyclePosition:

167 | 168 | 169 | 170 |
171 |

Tells the delegate that the camera controller cycled the camera position.

172 |
173 | 174 | 175 | 176 |
- (void)cameraControllerDidCyclePosition:(id)cameraController
177 | 178 | 179 | 180 |
181 |

Parameters

182 | 183 |
184 |
cameraController
185 |

The camera controller that cycled position.

186 |
187 | 188 |
189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 |
203 |

Declared In

204 | BKCameraController.h
205 |
206 | 207 | 208 |
209 | 210 |
211 | 212 |

cameraControllerWillCyclePosition:

213 | 214 | 215 | 216 |
217 |

Tells the delegate that the camera controller will cycle the camera position.

218 |
219 | 220 | 221 | 222 |
- (void)cameraControllerWillCyclePosition:(id)cameraController
223 | 224 | 225 | 226 |
227 |

Parameters

228 | 229 |
230 |
cameraController
231 |

The camera controller object informing the delegate of this event.

232 |
233 | 234 |
235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 |
249 |

Declared In

250 | BKCameraController.h
251 |
252 | 253 | 254 |
255 | 256 |
257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 |
265 | 271 | 280 |
281 |
282 | 373 | 374 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 3 | font-size: 13px; 4 | } 5 | 6 | code { 7 | font-family: Courier, Consolas, monospace; 8 | font-size: 13px; 9 | color: #666; 10 | } 11 | 12 | pre { 13 | font-family: Courier, Consolas, monospace; 14 | font-size: 13px; 15 | line-height: 18px; 16 | tab-interval: 0.5em; 17 | border: 1px solid #C7CFD5; 18 | background-color: #F1F5F9; 19 | color: #666; 20 | padding: 0.3em 1em; 21 | } 22 | 23 | ul { 24 | list-style-type: square; 25 | } 26 | 27 | li { 28 | margin-bottom: 10px; 29 | } 30 | 31 | a, a code { 32 | text-decoration: none; 33 | color: #36C; 34 | } 35 | 36 | a:hover, a:hover code { 37 | text-decoration: underline; 38 | color: #36C; 39 | } 40 | 41 | h2 { 42 | border-bottom: 1px solid #8391A8; 43 | color: #3C4C6C; 44 | font-size: 187%; 45 | font-weight: normal; 46 | margin-top: 1.75em; 47 | padding-bottom: 2px; 48 | } 49 | 50 | table { 51 | margin-bottom: 4em; 52 | border-collapse:collapse; 53 | vertical-align: middle; 54 | } 55 | 56 | td { 57 | border: 1px solid #9BB3CD; 58 | padding: .667em; 59 | font-size: 100%; 60 | } 61 | 62 | th { 63 | border: 1px solid #9BB3CD; 64 | padding: .3em .667em .3em .667em; 65 | background: #93A5BB; 66 | font-size: 103%; 67 | font-weight: bold; 68 | color: white; 69 | text-align: left; 70 | } 71 | 72 | /* @group Common page elements */ 73 | 74 | #top_header { 75 | height: 91px; 76 | left: 0; 77 | min-width: 598px; 78 | position: absolute; 79 | right: 0; 80 | top: 0; 81 | z-index: 900; 82 | } 83 | 84 | #footer { 85 | clear: both; 86 | padding-top: 20px; 87 | text-align: center; 88 | } 89 | 90 | #contents, #overview_contents { 91 | -webkit-overflow-scrolling: touch; 92 | border-top: 1px solid #A9A9A9; 93 | position: absolute; 94 | top: 90px; 95 | left: 0; 96 | right: 0; 97 | bottom: 0; 98 | overflow-x: hidden; 99 | overflow-y: auto; 100 | padding-left: 2em; 101 | padding-right: 2em; 102 | padding-top: 1em; 103 | min-width: 550px; 104 | } 105 | 106 | #contents.isShowingTOC { 107 | left: 230px; 108 | min-width: 320px; 109 | } 110 | 111 | .copyright { 112 | font-size: 12px; 113 | } 114 | 115 | .generator { 116 | font-size: 11px; 117 | } 118 | 119 | .main-navigation ul li { 120 | display: inline; 121 | margin-left: 15px; 122 | list-style: none; 123 | } 124 | 125 | .navigation-top { 126 | clear: both; 127 | float: right; 128 | } 129 | 130 | .navigation-bottom { 131 | clear: both; 132 | float: right; 133 | margin-top: 20px; 134 | margin-bottom: -10px; 135 | } 136 | 137 | .open > .disclosure { 138 | background-image: url("../img/disclosure_open.png"); 139 | } 140 | 141 | .disclosure { 142 | background: url("../img/disclosure.png") no-repeat scroll 0 0; 143 | } 144 | 145 | .disclosure, .nodisclosure { 146 | display: inline-block; 147 | height: 8px; 148 | margin-right: 5px; 149 | position: relative; 150 | width: 9px; 151 | } 152 | 153 | /* @end */ 154 | 155 | /* @group Header */ 156 | 157 | #top_header #library { 158 | background: url("../img/library_background.png") repeat-x 0 0 #485E78; 159 | background-color: #ccc; 160 | height: 35px; 161 | font-size: 115%; 162 | } 163 | 164 | #top_header #library #libraryTitle { 165 | color: #FFFFFF; 166 | margin-left: 15px; 167 | text-shadow: 0 -1px 0 #485E78; 168 | top: 8px; 169 | position: absolute; 170 | } 171 | 172 | #libraryTitle { 173 | left: 0; 174 | } 175 | 176 | #top_header #library #developerHome { 177 | color: #92979E; 178 | right: 15px; 179 | top: 8px; 180 | position: absolute; 181 | } 182 | 183 | #top_header #library a:hover { 184 | text-decoration: none; 185 | } 186 | 187 | #top_header #title { 188 | background: url("../img/title_background.png") repeat-x 0 0 #8A98A9; 189 | border-bottom: 1px solid #757575; 190 | height: 25px; 191 | overflow: hidden; 192 | } 193 | 194 | #top_header h1 { 195 | font-size: 105%; 196 | font-weight: normal; 197 | margin: 0; 198 | padding: 3px 0 2px; 199 | text-align: center; 200 | /*text-shadow: 0 1px 0 #D5D5D5;*/ 201 | white-space: nowrap; 202 | } 203 | 204 | #headerButtons { 205 | background-color: #D8D8D8; 206 | background-image: url("../img/button_bar_background.png"); 207 | border-bottom: 0px solid #EDEDED; 208 | border-top: 0px solid #a8a8a8; 209 | font-size: 8pt; 210 | height: 28px; 211 | left: 0; 212 | list-style: none outside none; 213 | margin: 0; 214 | overflow: hidden; 215 | padding: 0; 216 | position: absolute; 217 | right: 0; 218 | top: 61px; 219 | } 220 | 221 | #headerButtons li { 222 | background-repeat: no-repeat; 223 | display: inline; 224 | margin-top: 0; 225 | margin-bottom: 0; 226 | padding: 0; 227 | } 228 | 229 | #toc_button button { 230 | background-color: #EBEEF1; 231 | border-color: #ACACAC; 232 | border-style: none solid none none; 233 | border-width: 0 1px 0 0; 234 | height: 28px; 235 | margin: 0; 236 | padding-left: 30px; 237 | text-align: left; 238 | width: 230px; 239 | } 240 | 241 | li#jumpto_button { 242 | left: 230px; 243 | margin-left: 0; 244 | position: absolute; 245 | } 246 | 247 | li#jumpto_button select { 248 | height: 22px; 249 | margin: 5px 2px 0 10px; 250 | max-width: 300px; 251 | } 252 | 253 | /* @end */ 254 | 255 | /* @group Table of contents */ 256 | 257 | #tocContainer.isShowingTOC { 258 | border-right: 1px solid #ACACAC; 259 | display: block; 260 | overflow-x: hidden; 261 | overflow-y: auto; 262 | padding: 0; 263 | } 264 | 265 | #tocContainer { 266 | background-color: #EBEEF1; 267 | border-top: 1px solid #ACACAC; 268 | bottom: 0; 269 | display: none; 270 | left: 0; 271 | overflow: hidden; 272 | position: absolute; 273 | top: 90px; 274 | width: 229px; 275 | } 276 | 277 | #tocContainer > ul#toc { 278 | font-size: 11px; 279 | margin: 0; 280 | padding: 12px 0 18px; 281 | width: 209px; 282 | -moz-user-select: none; 283 | -webkit-user-select: none; 284 | user-select: none; 285 | } 286 | 287 | #tocContainer > ul#toc > li { 288 | margin: 0; 289 | padding: 0 0 7px 30px; 290 | text-indent: -15px; 291 | } 292 | 293 | #tocContainer > ul#toc > li > .sectionName a { 294 | color: #000000; 295 | font-weight: bold; 296 | } 297 | 298 | #tocContainer > ul#toc > li > .sectionName a:hover { 299 | text-decoration: none; 300 | } 301 | 302 | #tocContainer > ul#toc li.children > ul { 303 | display: none; 304 | height: 0; 305 | } 306 | 307 | #tocContainer > ul#toc > li > ul { 308 | margin: 0; 309 | padding: 0; 310 | } 311 | 312 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li { 313 | margin-left: 0; 314 | margin-bottom: 0; 315 | padding-left: 15px; 316 | } 317 | 318 | #tocContainer > ul#toc > li ul { 319 | list-style: none; 320 | margin-right: 0; 321 | padding-right: 0; 322 | } 323 | 324 | #tocContainer > ul#toc li.children.open > ul { 325 | display: block; 326 | height: auto; 327 | margin-left: -15px; 328 | padding-left: 0; 329 | } 330 | 331 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li { 332 | margin-left: 0; 333 | padding-left: 15px; 334 | } 335 | 336 | #tocContainer li ul li { 337 | margin-top: 0.583em; 338 | overflow: hidden; 339 | text-overflow: ellipsis; 340 | white-space: nowrap; 341 | } 342 | 343 | #tocContainer li ul li span.sectionName { 344 | white-space: normal; 345 | } 346 | 347 | #tocContainer > ul#toc > li > ul > li > .sectionName a { 348 | font-weight: bold; 349 | } 350 | 351 | #tocContainer > ul#toc > li > ul a { 352 | color: #4F4F4F; 353 | } 354 | 355 | /* @end */ 356 | 357 | /* @group Index formatting */ 358 | 359 | .index-title { 360 | font-size: 13px; 361 | font-weight: normal; 362 | } 363 | 364 | .index-column { 365 | float: left; 366 | width: 30%; 367 | min-width: 200px; 368 | font-size: 11px; 369 | } 370 | 371 | .index-column ul { 372 | margin: 8px 0 0 0; 373 | padding: 0; 374 | list-style: none; 375 | } 376 | 377 | .index-column ul li { 378 | margin: 0 0 3px 0; 379 | padding: 0; 380 | } 381 | 382 | .hierarchy-column { 383 | min-width: 400px; 384 | } 385 | 386 | .hierarchy-column ul { 387 | margin: 3px 0 0 15px; 388 | } 389 | 390 | .hierarchy-column ul li { 391 | list-style-type: square; 392 | } 393 | 394 | /* @end */ 395 | 396 | /* @group Common formatting elements */ 397 | 398 | .title { 399 | font-weight: normal; 400 | font-size: 215%; 401 | margin-top:0; 402 | } 403 | 404 | .subtitle { 405 | font-weight: normal; 406 | font-size: 180%; 407 | color: #3C4C6C; 408 | border-bottom: 1px solid #5088C5; 409 | } 410 | 411 | .subsubtitle { 412 | font-weight: normal; 413 | font-size: 145%; 414 | height: 0.7em; 415 | } 416 | 417 | .note { 418 | border: 1px solid #5088C5; 419 | background-color: white; 420 | margin: 1.667em 0 1.75em 0; 421 | padding: 0 .667em .083em .750em; 422 | } 423 | 424 | .warning { 425 | border: 1px solid #5088C5; 426 | background-color: #F0F3F7; 427 | margin-bottom: 0.5em; 428 | padding: 0.3em 0.8em; 429 | } 430 | 431 | .bug { 432 | border: 1px solid #000; 433 | background-color: #ffffcc; 434 | margin-bottom: 0.5em; 435 | padding: 0.3em 0.8em; 436 | } 437 | 438 | .deprecated { 439 | color: #F60425; 440 | } 441 | 442 | /* @end */ 443 | 444 | /* @group Common layout */ 445 | 446 | .section { 447 | margin-top: 3em; 448 | } 449 | 450 | /* @end */ 451 | 452 | /* @group Object specification section */ 453 | 454 | .section-specification { 455 | margin-left: 2.5em; 456 | margin-right: 2.5em; 457 | font-size: 12px; 458 | } 459 | 460 | .section-specification table { 461 | margin-bottom: 0em; 462 | border-top: 1px solid #d6e0e5; 463 | } 464 | 465 | .section-specification td { 466 | vertical-align: top; 467 | border-bottom: 1px solid #d6e0e5; 468 | border-left-width: 0px; 469 | border-right-width: 0px; 470 | border-top-width: 0px; 471 | padding: .6em; 472 | } 473 | 474 | .section-specification .specification-title { 475 | font-weight: bold; 476 | } 477 | 478 | /* @end */ 479 | 480 | /* @group Tasks section */ 481 | 482 | .task-list { 483 | list-style-type: none; 484 | padding-left: 0px; 485 | } 486 | 487 | .task-list li { 488 | margin-bottom: 3px; 489 | } 490 | 491 | .task-item-suffix { 492 | color: #996; 493 | font-size: 12px; 494 | font-style: italic; 495 | margin-left: 0.5em; 496 | } 497 | 498 | span.tooltip span.tooltip { 499 | font-size: 1.0em; 500 | display: none; 501 | padding: 0.3em; 502 | border: 1px solid #aaa; 503 | background-color: #fdfec8; 504 | color: #000; 505 | text-align: left; 506 | } 507 | 508 | span.tooltip:hover span.tooltip { 509 | display: block; 510 | position: absolute; 511 | margin-left: 2em; 512 | } 513 | 514 | /* @end */ 515 | 516 | /* @group Method section */ 517 | 518 | .section-method { 519 | margin-top: 2.3em; 520 | } 521 | 522 | .method-title { 523 | margin-bottom: 1.5em; 524 | } 525 | 526 | .method-subtitle { 527 | margin-top: 0.7em; 528 | margin-bottom: 0.2em; 529 | } 530 | 531 | .method-subsection p { 532 | margin-top: 0.4em; 533 | margin-bottom: 0.8em; 534 | } 535 | 536 | .method-declaration { 537 | margin-top:1.182em; 538 | margin-bottom:.909em; 539 | } 540 | 541 | .method-declaration code { 542 | font:14px Courier, Consolas, monospace; 543 | color:#000; 544 | } 545 | 546 | .declaration { 547 | color: #000; 548 | } 549 | 550 | .termdef { 551 | margin-bottom: 10px; 552 | margin-left: 0px; 553 | margin-right: 0px; 554 | margin-top: 0px; 555 | } 556 | 557 | .termdef dt { 558 | margin: 0; 559 | padding: 0; 560 | } 561 | 562 | .termdef dd { 563 | margin-bottom: 6px; 564 | margin-left: 16px; 565 | margin-right: 0px; 566 | margin-top: 1px; 567 | } 568 | 569 | .termdef dd p { 570 | margin-bottom: 6px; 571 | margin-left: 0px; 572 | margin-right: 0px; 573 | margin-top: -1px; 574 | } 575 | 576 | .argument-def { 577 | margin-top: 0.3em; 578 | margin-bottom: 0.3em; 579 | } 580 | 581 | .argument-def dd { 582 | margin-left: 1.25em; 583 | } 584 | 585 | .see-also-section ul { 586 | list-style-type: none; 587 | padding-left: 0px; 588 | margin-top: 0; 589 | } 590 | 591 | .see-also-section li { 592 | margin-bottom: 3px; 593 | } 594 | 595 | .declared-in-ref { 596 | color: #666; 597 | } 598 | 599 | #tocContainer.hideInXcode { 600 | display: none; 601 | border: 0px solid black; 602 | } 603 | 604 | #top_header.hideInXcode { 605 | display: none; 606 | } 607 | 608 | #contents.hideInXcode { 609 | border: 0px solid black; 610 | top: 0px; 611 | left: 0px; 612 | } 613 | 614 | /* @end */ 615 | 616 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Tokens1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | //apple_ref/occ/cl/BKCameraController 7 | A wrapper for AVCaptureSession to simplify the process of capturing photos. 8 | BKCameraController.h 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | //apple_ref/occ/instm/BKCameraController/setDelegate: 17 | The receiver’s delegate or nil if it doesn’t have a delegate. 18 | BKCameraController.h 19 | 20 | @property (nonatomic, weak) id<BKCameraControllerDelegate> delegate 21 | 22 | 23 | //api/name/delegate 24 | 25 | 26 | 27 | 28 | //apple_ref/occ/instm/BKCameraController/delegate 29 | The receiver’s delegate or nil if it doesn’t have a delegate. 30 | BKCameraController.h 31 | 32 | @property (nonatomic, weak) id<BKCameraControllerDelegate> delegate 33 | 34 | 35 | //api/name/delegate 36 | 37 | 38 | 39 | 40 | //apple_ref/occ/instp/BKCameraController/delegate 41 | The receiver’s delegate or nil if it doesn’t have a delegate. 42 | BKCameraController.h 43 | 44 | @property (nonatomic, weak) id<BKCameraControllerDelegate> delegate 45 | 46 | 47 | //api/name/delegate 48 | 49 | 50 | 51 | 52 | //apple_ref/occ/instm/BKCameraController/setSession: 53 | The controller-owned AVCaptureSession instance. 54 | BKCameraController.h 55 | 56 | @property (nonatomic, strong, readonly) AVCaptureSession *session 57 | 58 | 59 | //api/name/session 60 | 61 | 62 | 63 | 64 | //apple_ref/occ/instm/BKCameraController/session 65 | The controller-owned AVCaptureSession instance. 66 | BKCameraController.h 67 | 68 | @property (nonatomic, strong, readonly) AVCaptureSession *session 69 | 70 | 71 | //api/name/session 72 | 73 | 74 | 75 | 76 | //apple_ref/occ/instp/BKCameraController/session 77 | The controller-owned AVCaptureSession instance. 78 | BKCameraController.h 79 | 80 | @property (nonatomic, strong, readonly) AVCaptureSession *session 81 | 82 | 83 | //api/name/session 84 | 85 | 86 | 87 | 88 | //apple_ref/occ/instm/BKCameraController/setPosition: 89 | The current camera position. 90 | BKCameraController.h 91 | 92 | @property (nonatomic, assign, readonly) AVCaptureDevicePosition position 93 | 94 | 95 | //api/name/position 96 | 97 | 98 | 99 | 100 | //apple_ref/occ/instm/BKCameraController/position 101 | The current camera position. 102 | BKCameraController.h 103 | 104 | @property (nonatomic, assign, readonly) AVCaptureDevicePosition position 105 | 106 | 107 | //api/name/position 108 | 109 | 110 | 111 | 112 | //apple_ref/occ/instp/BKCameraController/position 113 | The current camera position. 114 | BKCameraController.h 115 | 116 | @property (nonatomic, assign, readonly) AVCaptureDevicePosition position 117 | 118 | 119 | //api/name/position 120 | 121 | 122 | 123 | 124 | //apple_ref/occ/instm/BKCameraController/setFlashMode: 125 | The current camera flash mode. 126 | BKCameraController.h 127 | 128 | @property (nonatomic, assign, readonly) AVCaptureFlashMode flashMode 129 | 130 | 131 | //api/name/flashMode 132 | 133 | 134 | 135 | 136 | //apple_ref/occ/instm/BKCameraController/flashMode 137 | The current camera flash mode. 138 | BKCameraController.h 139 | 140 | @property (nonatomic, assign, readonly) AVCaptureFlashMode flashMode 141 | 142 | 143 | //api/name/flashMode 144 | 145 | 146 | 147 | 148 | //apple_ref/occ/instp/BKCameraController/flashMode 149 | The current camera flash mode. 150 | BKCameraController.h 151 | 152 | @property (nonatomic, assign, readonly) AVCaptureFlashMode flashMode 153 | 154 | 155 | //api/name/flashMode 156 | 157 | 158 | 159 | 160 | //apple_ref/occ/instm/BKCameraController/setFlashCapable: 161 | Whether the current camera has the capability to flash. 162 | BKCameraController.h 163 | 164 | @property (nonatomic, assign, readonly) BOOL flashCapable 165 | 166 | 167 | //api/name/flashCapable 168 | 169 | 170 | 171 | 172 | //apple_ref/occ/instm/BKCameraController/flashCapable 173 | Whether the current camera has the capability to flash. 174 | BKCameraController.h 175 | 176 | @property (nonatomic, assign, readonly) BOOL flashCapable 177 | 178 | 179 | //api/name/flashCapable 180 | 181 | 182 | 183 | 184 | //apple_ref/occ/instp/BKCameraController/flashCapable 185 | Whether the current camera has the capability to flash. 186 | BKCameraController.h 187 | 188 | @property (nonatomic, assign, readonly) BOOL flashCapable 189 | 190 | 191 | //api/name/flashCapable 192 | 193 | 194 | 195 | 196 | //apple_ref/occ/instm/BKCameraController/initWithInitialPosition:autoFlashEnabled: 197 | Initializes the camera controller using the specified starting parameters. 198 | BKCameraController.h 199 | 200 | - (instancetype)initWithInitialPosition:(id)position autoFlashEnabled:(id)enabled 201 | 202 | 203 | position 204 | The position used to select the initial capture device used by the camera controller. Defaults to AVCaptureDevicePositionBack. 205 | 206 | enabled 207 | YES if the camera controller should include AVCaptureFlashModeAuto when cycling the flash mode. Defaults to NO. 208 | 209 | 210 | An initialized BKCameraController instance. 211 | //api/name/initWithInitialPosition:autoFlashEnabled: 212 | 213 | 214 | 215 | 216 | //apple_ref/occ/instm/BKCameraController/startCaptureSession 217 | Tells the receiver to start the capture session. 218 | BKCameraController.h 219 | 220 | - (void)startCaptureSession 221 | 222 | 223 | //api/name/startCaptureSession 224 | 225 | 226 | 227 | 228 | //apple_ref/occ/instm/BKCameraController/stopCaptureSession 229 | Tells the receiver to stop the capture session. 230 | BKCameraController.h 231 | 232 | - (void)stopCaptureSession 233 | 234 | 235 | //api/name/stopCaptureSession 236 | 237 | 238 | 239 | 240 | //apple_ref/occ/instm/BKCameraController/autoAdjustCameraToPoint: 241 | Sets the focus and exposure point to the specified point, if supported. 242 | BKCameraController.h 243 | 244 | - (void)autoAdjustCameraToPoint:(id)point 245 | 246 | 247 | point 248 | The point to set the exposure and focus. 249 | 250 | 251 | 252 | //api/name/autoAdjustCameraToPoint: 253 | 254 | 255 | 256 | 257 | //apple_ref/occ/instm/BKCameraController/cycleFlashMode 258 | Cycles through supported flash modes. Skips AVCaptureFlashModeAuto if the receiver was initialized with autoFlashEnabled set to NO. 259 | BKCameraController.h 260 | 261 | - (void)cycleFlashMode 262 | 263 | 264 | //api/name/cycleFlashMode 265 | 266 | 267 | 268 | 269 | //apple_ref/occ/instm/BKCameraController/cyclePosition 270 | Cycles through supported flash modes. If no flash mode at all is supported (such as on the front-facing camera), flashCapable is set to NO, otherwise YES. 271 | BKCameraController.h 272 | 273 | - (void)cyclePosition 274 | 275 | 276 | //api/name/cyclePosition 277 | 278 | 279 | 280 | 281 | //apple_ref/occ/instm/BKCameraController/captureAssetWithCompletion: 282 | Capture a photo and save it, along with its EXIF metadata, to the camera roll. 283 | BKCameraController.h 284 | 285 | - (void)captureAssetWithCompletion:(id)completion 286 | 287 | 288 | completion 289 | A completion block supplying either a valid Asset <NSURL> or a <NSError>. Executed on the main thread. 290 | 291 | - assetURL The Asset URL to the captured media. nil if an error occurred. 292 | - error The error, if a problem occurred during capture. 293 | 294 | 295 | 296 | //api/name/captureAssetWithCompletion: 297 | 298 | 299 | 300 | 301 | //apple_ref/occ/instm/BKCameraController/captureSampleWithCompletion: 302 | Capture a photo. 303 | BKCameraController.h 304 | 305 | - (void)captureSampleWithCompletion:(id)completion 306 | 307 | 308 | completion 309 | A completion block supplying either a <CIImage> or a <NSError>. Executed on the main thread. 310 | 311 | - image A CIImage wrapping the sample buffer's pixel buffer, captured by the camera. nil if an error occurred. 312 | - error The error, if a problem occurred during capture. 313 | 314 | 315 | 316 | //api/name/captureSampleWithCompletion: 317 | 318 | 319 | 320 | 321 | //apple_ref/occ/clm/BKCameraController/fakeImageData 322 | Getter for the fake image data used by the simulator. 323 | BKCameraController+Simulator.h 324 | 325 | + (NSData *)fakeImageData 326 | 327 | The fake image data used by the simulator. 328 | //api/name/fakeImageData 329 | 330 | 331 | 332 | 333 | //apple_ref/occ/clm/BKCameraController/setFakeImageData: 334 | Setter for the fake image data used by the simulator 335 | BKCameraController+Simulator.h 336 | 337 | + (void)setFakeImageData:(id)fakeImageData 338 | 339 | 340 | fakeImageData 341 | The fake image data to be used by the simulator. 342 | 343 | 344 | 345 | //api/name/setFakeImageData: 346 | 347 | 348 | 349 | 350 | 351 | 352 | -------------------------------------------------------------------------------- /BKCameraController/BKCameraController.m: -------------------------------------------------------------------------------- 1 | // Copyright 2014-present 650 Industries. All rights reserved. 2 | 3 | #import "BKCameraController.h" 4 | 5 | @import AssetsLibrary.ALAssetsLibrary; 6 | @import AVFoundation.AVCaptureInput; 7 | @import AVFoundation.AVCaptureOutput; 8 | @import AVFoundation.AVMediaFormat; 9 | @import AVFoundation.AVVideoSettings; 10 | @import CoreImage.CIImage; 11 | @import ImageIO.CGImageProperties; 12 | 13 | @interface BKCameraController () 14 | @property (nonatomic, strong) dispatch_queue_t avQueue; 15 | @end 16 | 17 | @implementation BKCameraController { 18 | BOOL _autoFlashEnabled; 19 | 20 | BOOL _sessionInitialized; 21 | BOOL _inputIsCycling; 22 | 23 | AVCaptureDeviceInput *_activeDeviceInput; 24 | AVCaptureStillImageOutput *_stillImageOutput; 25 | 26 | AVCaptureFlashMode _avFlashMode; // avQueue-affined flash mode 27 | AVCaptureDevicePosition _avPosition; // avQueue-affined device position 28 | } 29 | 30 | - (instancetype)initWithInitialPosition:(AVCaptureDevicePosition)position 31 | autoFlashEnabled:(BOOL)enabled 32 | { 33 | if (self = [super init]) { 34 | _autoFlashEnabled = enabled; 35 | 36 | _avQueue = dispatch_queue_create("net.sixfivezero.av", DISPATCH_QUEUE_SERIAL); 37 | 38 | _position = position; 39 | _session = [[AVCaptureSession alloc] init]; 40 | } 41 | return self; 42 | } 43 | 44 | - (instancetype)init 45 | { 46 | if (self = [self initWithInitialPosition:AVCaptureDevicePositionBack autoFlashEnabled:NO]) { 47 | } 48 | return self; 49 | } 50 | 51 | - (void)_initialSessionSetup 52 | { 53 | NSAssert(![NSThread isMainThread], @"Method should not be run on the main thread"); 54 | NSAssert(!_sessionInitialized, @"Session already initialized!"); 55 | 56 | if ([_session canSetSessionPreset:AVCaptureSessionPresetPhoto]) { 57 | _session.sessionPreset = AVCaptureSessionPresetPhoto; 58 | } 59 | 60 | _stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; 61 | [_session addOutput:_stillImageOutput]; 62 | 63 | NSError *error = nil; 64 | AVCaptureDevice *initialDevice = [self _captureDeviceForPosition:_position]; 65 | AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:initialDevice error:&error]; 66 | NSAssert(TARGET_IPHONE_SIMULATOR || error == nil, @"Error getting device input"); 67 | 68 | [self _updateSessionWithInput:input error:&error]; 69 | NSAssert(TARGET_IPHONE_SIMULATOR || error == nil, @"Error updating session with input"); 70 | 71 | _sessionInitialized = YES; 72 | } 73 | 74 | - (void)startCaptureSession 75 | { 76 | dispatch_async(_avQueue, ^{ 77 | if (!_sessionInitialized) { 78 | [self _initialSessionSetup]; 79 | } 80 | [_session startRunning]; 81 | }); 82 | } 83 | 84 | - (void)stopCaptureSession 85 | { 86 | dispatch_async(_avQueue, ^{ 87 | [_session stopRunning]; 88 | }); 89 | } 90 | 91 | #pragma mark - Camera control 92 | 93 | - (AVCaptureDevice *)_captureDeviceForPosition:(AVCaptureDevicePosition)position 94 | { 95 | NSAssert(![NSThread isMainThread], @"Method should not be run on the main thread"); 96 | for (AVCaptureDevice *device in [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]) { 97 | if (device.position == position) { 98 | return device; 99 | } 100 | } 101 | return nil; 102 | } 103 | 104 | - (BOOL)_updateSessionWithInput:(AVCaptureDeviceInput *)newInput error:(NSError * __autoreleasing *)error 105 | { 106 | NSAssert(![NSThread isMainThread], @"Method should not be run on the main thread"); 107 | [_session beginConfiguration]; 108 | if (_activeDeviceInput) { 109 | [_session removeInput:_activeDeviceInput]; 110 | } 111 | 112 | if (![_session canAddInput:newInput]) { 113 | // Roll back the changes 114 | if (_activeDeviceInput) { 115 | [_session addInput:_activeDeviceInput]; 116 | } 117 | [_session commitConfiguration]; 118 | NSString *message = [NSString stringWithFormat:@"Something went wrong when switching to the %@", newInput.device.localizedName]; 119 | if (error) { 120 | *error = [NSError errorWithDomain:@"net.sixfivezero" code:0 userInfo:@{NSLocalizedDescriptionKey: message}]; 121 | } 122 | return YES; 123 | } 124 | 125 | [_session addInput:newInput]; 126 | _activeDeviceInput = newInput; 127 | [_session commitConfiguration]; 128 | return NO; 129 | } 130 | 131 | - (void)autoAdjustCameraToPoint:(CGPoint)point 132 | { 133 | dispatch_async(_avQueue, ^{ 134 | NSError *error = nil; 135 | AVCaptureDevice *camera = [_activeDeviceInput device]; 136 | [camera lockForConfiguration:&error]; 137 | if (error) { 138 | NSLog(@"ERROR: problem adjusting camera: %@", error); 139 | // TODO: handle error 140 | return; 141 | } 142 | if (camera.isFocusPointOfInterestSupported) { 143 | camera.focusPointOfInterest = point; 144 | } 145 | if (camera.isExposurePointOfInterestSupported) { 146 | camera.exposurePointOfInterest = point; 147 | } 148 | if ([camera isFocusModeSupported:AVCaptureFocusModeContinuousAutoFocus]) { 149 | camera.focusMode = AVCaptureFocusModeContinuousAutoFocus; 150 | } 151 | if ([camera isExposureModeSupported:AVCaptureExposureModeContinuousAutoExposure]) { 152 | camera.exposureMode = AVCaptureExposureModeContinuousAutoExposure; 153 | } 154 | if ([camera isWhiteBalanceModeSupported:AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance]) { 155 | camera.whiteBalanceMode = AVCaptureWhiteBalanceModeContinuousAutoWhiteBalance; 156 | } 157 | [camera unlockForConfiguration]; 158 | }); 159 | } 160 | 161 | - (void)cycleFlashMode 162 | { 163 | dispatch_async(_avQueue, ^{ 164 | AVCaptureDevice *camera = _activeDeviceInput.device; 165 | AVCaptureFlashMode currentFlashMode = camera.flashMode; 166 | AVCaptureFlashMode nextFlashMode = AVCaptureFlashModeOff; 167 | 168 | switch (currentFlashMode) { 169 | case AVCaptureFlashModeOff: 170 | if ([camera isFlashModeSupported:AVCaptureFlashModeOn]) { 171 | nextFlashMode = AVCaptureFlashModeOn; 172 | } 173 | break; 174 | case AVCaptureFlashModeOn: 175 | if ([camera isFlashModeSupported:AVCaptureFlashModeAuto] && _autoFlashEnabled) { 176 | nextFlashMode = AVCaptureFlashModeAuto; 177 | } else { 178 | nextFlashMode = AVCaptureFlashModeOff; 179 | } 180 | break; 181 | case AVCaptureFlashModeAuto: 182 | nextFlashMode = AVCaptureFlashModeOff; 183 | break; 184 | default: 185 | nextFlashMode = AVCaptureFlashModeOff; 186 | NSAssert(NO, @"Unknown flash mode: %d", (int)currentFlashMode); 187 | } 188 | 189 | // The front camera doesn't even support _setting_ flashMode, even to off. 190 | BOOL flashCapable = YES; 191 | if (![camera isFlashModeSupported:nextFlashMode]) { 192 | flashCapable = NO; 193 | } 194 | 195 | // Optimistically update button 196 | dispatch_async(dispatch_get_main_queue(), ^{ 197 | [self willChangeValueForKey:@"flashCapable"]; 198 | _flashCapable = flashCapable; 199 | [self didChangeValueForKey:@"flashCapable"]; 200 | [self willChangeValueForKey:@"flashMode"]; 201 | _flashMode = nextFlashMode; 202 | [self didChangeValueForKey:@"flashMode"]; 203 | }); 204 | 205 | // Don't bother trying to change flash mode if not capable 206 | if (!flashCapable) { 207 | return; 208 | } 209 | 210 | NSError *error = nil; 211 | [camera lockForConfiguration:&error]; 212 | if (error) { 213 | NSLog(@"error cycling flash: %@", error); 214 | // Roll back icon change 215 | dispatch_async(dispatch_get_main_queue(), ^{ 216 | [self willChangeValueForKey:@"flashCapable"]; 217 | _flashCapable = flashCapable; 218 | [self didChangeValueForKey:@"flashCapable"]; 219 | [self willChangeValueForKey:@"flashMode"]; 220 | _flashMode = nextFlashMode; 221 | [self didChangeValueForKey:@"flashMode"]; 222 | }); 223 | return; 224 | } 225 | 226 | camera.flashMode = nextFlashMode; 227 | [camera unlockForConfiguration]; 228 | }); 229 | } 230 | 231 | - (void)cyclePosition 232 | { 233 | if (_inputIsCycling) { 234 | return; 235 | } 236 | 237 | _inputIsCycling = YES; 238 | 239 | if ([_delegate respondsToSelector:@selector(cameraControllerWillCyclePosition:)]) { 240 | [_delegate cameraControllerWillCyclePosition:self]; 241 | } 242 | 243 | dispatch_async(_avQueue, ^{ 244 | AVCaptureDevice *camera = _activeDeviceInput.device; 245 | AVCaptureDevicePosition currentPosition = camera.position; 246 | AVCaptureDevicePosition nextPosition = AVCaptureDevicePositionUnspecified; 247 | 248 | switch (currentPosition) { 249 | case AVCaptureDevicePositionBack: 250 | nextPosition = AVCaptureDevicePositionFront; 251 | break; 252 | case AVCaptureDevicePositionFront: 253 | nextPosition = AVCaptureDevicePositionBack; 254 | break; 255 | default: 256 | nextPosition = AVCaptureDevicePositionUnspecified; 257 | NSAssert(NO, @"Unknown position: %d", (int)currentPosition); 258 | } 259 | 260 | NSError *error = nil; 261 | AVCaptureDevice *newCamera = [self _captureDeviceForPosition:nextPosition]; 262 | AVCaptureDeviceInput *newInput = [AVCaptureDeviceInput deviceInputWithDevice:newCamera error:&error]; 263 | if (error) { 264 | NSLog(@"ERROR: problem cycling position: %@", error); 265 | return; 266 | } 267 | [self _updateSessionWithInput:newInput error:&error]; 268 | if (error) { 269 | NSLog(@"ERROR: problem cycling position: %@", error); 270 | return; 271 | } 272 | 273 | AVCaptureFlashMode newFlashMode = newCamera.flashMode; 274 | BOOL flashCapable = YES; 275 | if (![newCamera isFlashModeSupported:newFlashMode]) { 276 | flashCapable = NO; 277 | } 278 | 279 | _avFlashMode = newFlashMode; 280 | _avPosition = nextPosition; 281 | 282 | dispatch_async(dispatch_get_main_queue(), ^{ 283 | _inputIsCycling = NO; 284 | [self willChangeValueForKey:@"flashCapable"]; 285 | _flashCapable = flashCapable; 286 | [self didChangeValueForKey:@"flashCapable"]; 287 | [self willChangeValueForKey:@"flashMode"]; 288 | _flashMode = newFlashMode; 289 | [self didChangeValueForKey:@"flashMode"]; 290 | [self willChangeValueForKey:@"position"]; 291 | _position = nextPosition; 292 | [self didChangeValueForKey:@"position"]; 293 | 294 | if ([_delegate respondsToSelector:@selector(cameraControllerDidCyclePosition:)]) { 295 | [_delegate cameraControllerDidCyclePosition:self]; 296 | } 297 | }); 298 | }); 299 | } 300 | 301 | #pragma mark - Photo capture 302 | 303 | - (void)captureAssetWithCompletion:(asset_capture_completion_t)completion 304 | { 305 | dispatch_async(_avQueue, ^{ 306 | AVCaptureConnection *connection = [_stillImageOutput connectionWithMediaType:AVMediaTypeVideo]; 307 | _stillImageOutput.outputSettings = @{AVVideoCodecKey: AVVideoCodecJPEG}; 308 | [_stillImageOutput captureStillImageAsynchronouslyFromConnection:connection 309 | completionHandler: 310 | ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 311 | if (error) { 312 | NSLog(@"ERROR: problem capturing photo: %@", [error localizedDescription]); 313 | dispatch_async(dispatch_get_main_queue(), ^{ 314 | completion(nil, error); 315 | }); 316 | return; 317 | } 318 | 319 | CFDictionaryRef exifAttachments = CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL); 320 | NSDictionary *exif; 321 | if (exifAttachments) { 322 | exif = [NSDictionary dictionaryWithDictionary:(__bridge NSDictionary *)(exifAttachments)]; 323 | } else { 324 | exif = nil; 325 | } 326 | 327 | NSData *data = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 328 | ALAssetsLibrary *assetsLibrary = [[ALAssetsLibrary alloc] init]; 329 | [assetsLibrary writeImageDataToSavedPhotosAlbum:data metadata:exif completionBlock:^(NSURL *assetURL, NSError *error) { 330 | if (error) { 331 | dispatch_async(dispatch_get_main_queue(), ^{ 332 | completion(nil, error); 333 | }); 334 | } else { 335 | dispatch_async(dispatch_get_main_queue(), ^{ 336 | completion(assetURL, nil); 337 | }); 338 | } 339 | }]; 340 | }]; 341 | }); 342 | } 343 | 344 | - (void)captureSampleWithCompletion:(ciimage_capture_completion_t)completion 345 | { 346 | dispatch_async(_avQueue, ^{ 347 | AVCaptureConnection *connection = [_stillImageOutput connectionWithMediaType:AVMediaTypeVideo]; 348 | _stillImageOutput.outputSettings = @{(NSString *)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)}; 349 | [_stillImageOutput captureStillImageAsynchronouslyFromConnection:connection 350 | completionHandler: 351 | ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 352 | if (error) { 353 | NSLog(@"ERROR: problem capturing photo: %@", [error localizedDescription]); 354 | dispatch_async(dispatch_get_main_queue(), ^{ 355 | completion(nil, error); 356 | }); 357 | return; 358 | } 359 | 360 | CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(imageSampleBuffer); 361 | NSDictionary *attachments = (__bridge_transfer NSDictionary *)CMCopyDictionaryOfAttachments(NULL, imageSampleBuffer, kCMAttachmentMode_ShouldPropagate); 362 | CIImage *image = [CIImage imageWithCVPixelBuffer:pixelBuffer options:@{kCIImageProperties: attachments}]; 363 | 364 | dispatch_async(dispatch_get_main_queue(), ^{ 365 | completion(image, nil); 366 | }); 367 | }]; 368 | }); 369 | } 370 | 371 | @end 372 | -------------------------------------------------------------------------------- /net.sixfivezero.BKCameraController.docset/Contents/Resources/Documents/Classes/BKCameraController.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BKCameraController Class Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 17 | 18 | 21 | 87 |
88 | 163 |
164 |
165 | 166 | 172 | 177 |
178 | 179 |
180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 |
Inherits fromNSObject
Declared inBKCameraController.h
188 | 189 | 190 | 191 | 192 |
193 | 194 |

Overview

195 |

A wrapper for AVCaptureSession to simplify the process of capturing photos.

196 |
197 | 198 | 199 | 200 | 201 | 202 |
203 | 204 |

Tasks

205 | 206 | 207 | 208 |

Other Methods

209 | 210 | 243 | 244 | 245 | 246 |

Initializing a BKCameraController object

247 | 248 | 257 | 258 | 259 | 260 |

Starting/Stopping Capture Session State

261 | 262 | 277 | 278 | 279 | 280 |

Adjusting Camera Settings

281 | 282 | 303 | 304 | 305 | 306 |

Capturing Photos

307 | 308 | 323 | 324 | 325 | 326 |

Simulator Methods

327 | 328 | 343 | 344 |
345 | 346 | 347 | 348 | 349 | 350 |
351 | 352 |

Properties

353 | 354 |
355 | 356 |

delegate

357 | 358 | 359 | 360 |
361 |

The receiver’s delegate or nil if it doesn’t have a delegate.

362 |
363 | 364 | 365 | 366 |
@property (nonatomic, weak) id<BKCameraControllerDelegate> delegate
367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 |
377 |

Discussion

378 |

For a list of methods your delegate object can implement, see BKCameraControllerDelegate Protocol Reference

379 |
380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 |
388 |

Declared In

389 | BKCameraController.h
390 |
391 | 392 | 393 |
394 | 395 |
396 | 397 |

flashCapable

398 | 399 | 400 | 401 |
402 |

Whether the current camera has the capability to flash.

403 |
404 | 405 | 406 | 407 |
@property (nonatomic, assign, readonly) BOOL flashCapable
408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 |
424 |

Declared In

425 | BKCameraController.h
426 |
427 | 428 | 429 |
430 | 431 |
432 | 433 |

flashMode

434 | 435 | 436 | 437 |
438 |

The current camera flash mode.

439 |
440 | 441 | 442 | 443 |
@property (nonatomic, assign, readonly) AVCaptureFlashMode flashMode
444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 |
460 |

Declared In

461 | BKCameraController.h
462 |
463 | 464 | 465 |
466 | 467 |
468 | 469 |

position

470 | 471 | 472 | 473 |
474 |

The current camera position.

475 |
476 | 477 | 478 | 479 |
@property (nonatomic, assign, readonly) AVCaptureDevicePosition position
480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 |
496 |

Declared In

497 | BKCameraController.h
498 |
499 | 500 | 501 |
502 | 503 |
504 | 505 |

session

506 | 507 | 508 | 509 |
510 |

The controller-owned AVCaptureSession instance.

511 |
512 | 513 | 514 | 515 |
@property (nonatomic, strong, readonly) AVCaptureSession *session
516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 |
532 |

Declared In

533 | BKCameraController.h
534 |
535 | 536 | 537 |
538 | 539 |
540 | 541 | 542 | 543 |
544 | 545 |

Class Methods

546 | 547 |
548 | 549 |

fakeImageData

550 | 551 | 552 | 553 |
554 |

Getter for the fake image data used by the simulator.

555 |
556 | 557 | 558 | 559 |
+ (NSData *)fakeImageData
560 | 561 | 562 | 563 | 564 | 565 |
566 |

Return Value

567 |

The fake image data used by the simulator.

568 |
569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 |
581 |

Declared In

582 | BKCameraController+Simulator.h
583 |
584 | 585 | 586 |
587 | 588 |
589 | 590 |

setFakeImageData:

591 | 592 | 593 | 594 |
595 |

Setter for the fake image data used by the simulator

596 |
597 | 598 | 599 | 600 |
+ (void)setFakeImageData:(id)fakeImageData
601 | 602 | 603 | 604 |
605 |

Parameters

606 | 607 |
608 |
fakeImageData
609 |

The fake image data to be used by the simulator.

610 |
611 | 612 |
613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 |
627 |

Declared In

628 | BKCameraController+Simulator.h
629 |
630 | 631 | 632 |
633 | 634 |
635 | 636 | 637 | 638 |
639 | 640 |

Instance Methods

641 | 642 |
643 | 644 |

autoAdjustCameraToPoint:

645 | 646 | 647 | 648 |
649 |

Sets the focus and exposure point to the specified point, if supported.

650 |
651 | 652 | 653 | 654 |
- (void)autoAdjustCameraToPoint:(id)point
655 | 656 | 657 | 658 |
659 |

Parameters

660 | 661 |
662 |
point
663 |

The point to set the exposure and focus.

664 |
665 | 666 |
667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 |
681 |

Declared In

682 | BKCameraController.h
683 |
684 | 685 | 686 |
687 | 688 |
689 | 690 |

captureAssetWithCompletion:

691 | 692 | 693 | 694 |
695 |

Capture a photo and save it, along with its EXIF metadata, to the camera roll.

696 |
697 | 698 | 699 | 700 |
- (void)captureAssetWithCompletion:(id)completion
701 | 702 | 703 | 704 |
705 |

Parameters

706 | 707 |
708 |
completion
709 |

A completion block supplying either a valid Asset or a . Executed on the main thread.

710 | 711 |
    712 |
  • assetURL The Asset URL to the captured media. nil if an error occurred.
  • 713 |
  • error The error, if a problem occurred during capture.
  • 714 |
715 |
716 |
717 | 718 |
719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 |
733 |

Declared In

734 | BKCameraController.h
735 |
736 | 737 | 738 |
739 | 740 |
741 | 742 |

captureSampleWithCompletion:

743 | 744 | 745 | 746 |
747 |

Capture a photo.

748 |
749 | 750 | 751 | 752 |
- (void)captureSampleWithCompletion:(id)completion
753 | 754 | 755 | 756 |
757 |

Parameters

758 | 759 |
760 |
completion
761 |

A completion block supplying either a or a . Executed on the main thread.

762 | 763 |
    764 |
  • image A CIImage wrapping the sample buffer’s pixel buffer, captured by the camera. nil if an error occurred.
  • 765 |
  • error The error, if a problem occurred during capture.
  • 766 |
767 |
768 |
769 | 770 |
771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 |
785 |

Declared In

786 | BKCameraController.h
787 |
788 | 789 | 790 |
791 | 792 |
793 | 794 |

cycleFlashMode

795 | 796 | 797 | 798 |
799 |

Cycles through supported flash modes. Skips AVCaptureFlashModeAuto if the receiver was initialized with autoFlashEnabled set to NO.

800 |
801 | 802 | 803 | 804 |
- (void)cycleFlashMode
805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 |
821 |

Declared In

822 | BKCameraController.h
823 |
824 | 825 | 826 |
827 | 828 |
829 | 830 |

cyclePosition

831 | 832 | 833 | 834 |
835 |

Cycles through supported flash modes. If no flash mode at all is supported (such as on the front-facing camera), flashCapable is set to NO, otherwise YES.

836 |
837 | 838 | 839 | 840 |
- (void)cyclePosition
841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 |
857 |

Declared In

858 | BKCameraController.h
859 |
860 | 861 | 862 |
863 | 864 |
865 | 866 |

initWithInitialPosition:autoFlashEnabled:

867 | 868 | 869 | 870 |
871 |

Initializes the camera controller using the specified starting parameters.

872 |
873 | 874 | 875 | 876 |
- (instancetype)initWithInitialPosition:(id)position autoFlashEnabled:(id)enabled
877 | 878 | 879 | 880 |
881 |

Parameters

882 | 883 |
884 |
position
885 |

The position used to select the initial capture device used by the camera controller. Defaults to AVCaptureDevicePositionBack.

886 |
887 | 888 |
889 |
enabled
890 |

YES if the camera controller should include AVCaptureFlashModeAuto when cycling the flash mode. Defaults to NO.

891 |
892 | 893 |
894 | 895 | 896 | 897 |
898 |

Return Value

899 |

An initialized BKCameraController instance.

900 |
901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 |
913 |

Declared In

914 | BKCameraController.h
915 |
916 | 917 | 918 |
919 | 920 |
921 | 922 |

startCaptureSession

923 | 924 | 925 | 926 |
927 |

Tells the receiver to start the capture session.

928 |
929 | 930 | 931 | 932 |
- (void)startCaptureSession
933 | 934 | 935 | 936 | 937 | 938 | 939 | 940 | 941 | 942 |
943 |

Discussion

944 |

This method is used to start the receiver’s capture session. This method is asynchronous and runs on a serial background queue owned by the receiver.

945 |
946 | 947 | 948 | 949 | 950 | 951 | 952 | 953 |
954 |

Declared In

955 | BKCameraController.h
956 |
957 | 958 | 959 |
960 | 961 |
962 | 963 |

stopCaptureSession

964 | 965 | 966 | 967 |
968 |

Tells the receiver to stop the capture session.

969 |
970 | 971 | 972 | 973 |
- (void)stopCaptureSession
974 | 975 | 976 | 977 | 978 | 979 | 980 | 981 | 982 | 983 |
984 |

Discussion

985 |

This method is used to stop the receiver’s capture session. This method is asynchronous and runs on a serial background queue owned by the receiver.

986 |
987 | 988 | 989 | 990 | 991 | 992 | 993 | 994 |
995 |

Declared In

996 | BKCameraController.h
997 |
998 | 999 | 1000 |
1001 | 1002 |
1003 | 1004 | 1005 | 1006 | 1007 | 1008 | 1009 | 1010 |
1011 | 1017 | 1026 |
1027 |
1028 | 1119 | 1120 | --------------------------------------------------------------------------------