├── .gitignore ├── CustomCamera.xcodeproj ├── project.pbxproj └── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── CustomCamera ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Camera icons │ │ ├── Contents.json │ │ ├── Flash Off Icon.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_flash_off.png │ │ │ ├── ic_flash_off_2x.png │ │ │ └── ic_flash_off_3x.png │ │ ├── Flash On Icon.imageset │ │ │ ├── Contents.json │ │ │ ├── ic_flash_on.png │ │ │ ├── ic_flash_on_2x.png │ │ │ └── ic_flash_on_3x.png │ │ ├── camera_close.imageset │ │ │ ├── Contents.json │ │ │ ├── icClear24Px.png │ │ │ ├── icClear24Px@2x.png │ │ │ └── icClear24Px@3x.png │ │ ├── camera_icon_green.imageset │ │ │ ├── Contents.json │ │ │ ├── icCameraAlt24Px.png │ │ │ ├── icCameraAlt24Px@2x.png │ │ │ └── icCameraAlt24Px@3x.png │ │ ├── delete_icon.imageset │ │ │ ├── Contents.json │ │ │ ├── icDelete48Px.png │ │ │ ├── icDelete48Px@2x.png │ │ │ └── icDelete48Px@3x.png │ │ ├── photo_camera.imageset │ │ │ ├── Contents.json │ │ │ ├── baseline_photo_camera_white_24pt_1x.png │ │ │ ├── baseline_photo_camera_white_24pt_2x.png │ │ │ └── baseline_photo_camera_white_24pt_3x.png │ │ └── rotate.imageset │ │ │ ├── Contents.json │ │ │ ├── Rotate icon-1.png │ │ │ ├── Rotate icon.png │ │ │ ├── Rotate icon@ @2X-1.png │ │ │ ├── Rotate icon@ @2X.png │ │ │ └── Rotate icon@3X.png │ └── Contents.json ├── Base.lproj │ └── LaunchScreen.storyboard ├── Camera Controller │ ├── Base.lproj │ │ └── Camera.storyboard │ ├── CameraController.swift │ ├── CameraViewController.swift │ ├── PhotoPreviewController.swift │ └── PreviewsCollectionViewCell.swift └── Info.plist ├── README.md └── an2.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | # 37 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 38 | # Packages/ 39 | # Package.pins 40 | # Package.resolved 41 | .build/ 42 | 43 | # CocoaPods 44 | # 45 | # We recommend against adding the Pods directory to your .gitignore. However 46 | # you should judge for yourself, the pros and cons are mentioned at: 47 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 48 | # 49 | # Pods/ 50 | 51 | # Carthage 52 | # 53 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 54 | # Carthage/Checkouts 55 | 56 | Carthage/Build 57 | 58 | # fastlane 59 | # 60 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 61 | # screenshots whenever they are needed. 62 | # For more information about the recommended setup visit: 63 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 64 | 65 | fastlane/report.xml 66 | fastlane/Preview.html 67 | fastlane/screenshots/**/*.png 68 | fastlane/test_output 69 | -------------------------------------------------------------------------------- /CustomCamera.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 260FAEF120DF78050036E494 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260FAEF020DF78050036E494 /* AppDelegate.swift */; }; 11 | 260FAEF320DF78050036E494 /* CameraViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260FAEF220DF78050036E494 /* CameraViewController.swift */; }; 12 | 260FAEF620DF78050036E494 /* Camera.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 260FAEF420DF78050036E494 /* Camera.storyboard */; }; 13 | 260FAEF820DF780C0036E494 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 260FAEF720DF780C0036E494 /* Assets.xcassets */; }; 14 | 260FAEFB20DF780C0036E494 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 260FAEF920DF780C0036E494 /* LaunchScreen.storyboard */; }; 15 | 260FAF0720DFA36E0036E494 /* CameraController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 260FAF0620DFA36E0036E494 /* CameraController.swift */; }; 16 | 26BF2F7F20E4A65300AFBD1E /* PhotoPreviewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BF2F7E20E4A65300AFBD1E /* PhotoPreviewController.swift */; }; 17 | 26BF2F8120E4C69D00AFBD1E /* PreviewsCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26BF2F8020E4C69D00AFBD1E /* PreviewsCollectionViewCell.swift */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | 260FAEED20DF78050036E494 /* CustomCamera.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CustomCamera.app; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | 260FAEF020DF78050036E494 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 23 | 260FAEF220DF78050036E494 /* CameraViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CameraViewController.swift; sourceTree = ""; }; 24 | 260FAEF520DF78050036E494 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Camera.storyboard; sourceTree = ""; }; 25 | 260FAEF720DF780C0036E494 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | 260FAEFA20DF780C0036E494 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 27 | 260FAEFC20DF780C0036E494 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | 260FAF0620DFA36E0036E494 /* CameraController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CameraController.swift; sourceTree = ""; }; 29 | 26BF2F7E20E4A65300AFBD1E /* PhotoPreviewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PhotoPreviewController.swift; sourceTree = ""; }; 30 | 26BF2F8020E4C69D00AFBD1E /* PreviewsCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewsCollectionViewCell.swift; sourceTree = ""; }; 31 | /* End PBXFileReference section */ 32 | 33 | /* Begin PBXFrameworksBuildPhase section */ 34 | 260FAEEA20DF78050036E494 /* Frameworks */ = { 35 | isa = PBXFrameworksBuildPhase; 36 | buildActionMask = 2147483647; 37 | files = ( 38 | ); 39 | runOnlyForDeploymentPostprocessing = 0; 40 | }; 41 | /* End PBXFrameworksBuildPhase section */ 42 | 43 | /* Begin PBXGroup section */ 44 | 260FAEE420DF78050036E494 = { 45 | isa = PBXGroup; 46 | children = ( 47 | 260FAEEF20DF78050036E494 /* CustomCamera */, 48 | 260FAEEE20DF78050036E494 /* Products */, 49 | ); 50 | sourceTree = ""; 51 | }; 52 | 260FAEEE20DF78050036E494 /* Products */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 260FAEED20DF78050036E494 /* CustomCamera.app */, 56 | ); 57 | name = Products; 58 | sourceTree = ""; 59 | }; 60 | 260FAEEF20DF78050036E494 /* CustomCamera */ = { 61 | isa = PBXGroup; 62 | children = ( 63 | 260FAEF020DF78050036E494 /* AppDelegate.swift */, 64 | 26BF2F8220E4E00C00AFBD1E /* Camera Controller */, 65 | 260FAEF720DF780C0036E494 /* Assets.xcassets */, 66 | 260FAEF920DF780C0036E494 /* LaunchScreen.storyboard */, 67 | 260FAEFC20DF780C0036E494 /* Info.plist */, 68 | ); 69 | path = CustomCamera; 70 | sourceTree = ""; 71 | }; 72 | 26BF2F8220E4E00C00AFBD1E /* Camera Controller */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 260FAEF220DF78050036E494 /* CameraViewController.swift */, 76 | 260FAF0620DFA36E0036E494 /* CameraController.swift */, 77 | 260FAEF420DF78050036E494 /* Camera.storyboard */, 78 | 26BF2F7E20E4A65300AFBD1E /* PhotoPreviewController.swift */, 79 | 26BF2F8020E4C69D00AFBD1E /* PreviewsCollectionViewCell.swift */, 80 | ); 81 | path = "Camera Controller"; 82 | sourceTree = ""; 83 | }; 84 | /* End PBXGroup section */ 85 | 86 | /* Begin PBXNativeTarget section */ 87 | 260FAEEC20DF78050036E494 /* CustomCamera */ = { 88 | isa = PBXNativeTarget; 89 | buildConfigurationList = 260FAEFF20DF780C0036E494 /* Build configuration list for PBXNativeTarget "CustomCamera" */; 90 | buildPhases = ( 91 | 260FAEE920DF78050036E494 /* Sources */, 92 | 260FAEEA20DF78050036E494 /* Frameworks */, 93 | 260FAEEB20DF78050036E494 /* Resources */, 94 | ); 95 | buildRules = ( 96 | ); 97 | dependencies = ( 98 | ); 99 | name = CustomCamera; 100 | productName = CustomCamera; 101 | productReference = 260FAEED20DF78050036E494 /* CustomCamera.app */; 102 | productType = "com.apple.product-type.application"; 103 | }; 104 | /* End PBXNativeTarget section */ 105 | 106 | /* Begin PBXProject section */ 107 | 260FAEE520DF78050036E494 /* Project object */ = { 108 | isa = PBXProject; 109 | attributes = { 110 | LastSwiftUpdateCheck = 0940; 111 | LastUpgradeCheck = 0940; 112 | ORGANIZATIONNAME = nfnlabs; 113 | TargetAttributes = { 114 | 260FAEEC20DF78050036E494 = { 115 | CreatedOnToolsVersion = 9.4.1; 116 | LastSwiftMigration = 1130; 117 | }; 118 | }; 119 | }; 120 | buildConfigurationList = 260FAEE820DF78050036E494 /* Build configuration list for PBXProject "CustomCamera" */; 121 | compatibilityVersion = "Xcode 9.3"; 122 | developmentRegion = en; 123 | hasScannedForEncodings = 0; 124 | knownRegions = ( 125 | en, 126 | Base, 127 | ); 128 | mainGroup = 260FAEE420DF78050036E494; 129 | productRefGroup = 260FAEEE20DF78050036E494 /* Products */; 130 | projectDirPath = ""; 131 | projectRoot = ""; 132 | targets = ( 133 | 260FAEEC20DF78050036E494 /* CustomCamera */, 134 | ); 135 | }; 136 | /* End PBXProject section */ 137 | 138 | /* Begin PBXResourcesBuildPhase section */ 139 | 260FAEEB20DF78050036E494 /* Resources */ = { 140 | isa = PBXResourcesBuildPhase; 141 | buildActionMask = 2147483647; 142 | files = ( 143 | 260FAEFB20DF780C0036E494 /* LaunchScreen.storyboard in Resources */, 144 | 260FAEF820DF780C0036E494 /* Assets.xcassets in Resources */, 145 | 260FAEF620DF78050036E494 /* Camera.storyboard in Resources */, 146 | ); 147 | runOnlyForDeploymentPostprocessing = 0; 148 | }; 149 | /* End PBXResourcesBuildPhase section */ 150 | 151 | /* Begin PBXSourcesBuildPhase section */ 152 | 260FAEE920DF78050036E494 /* Sources */ = { 153 | isa = PBXSourcesBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | 26BF2F7F20E4A65300AFBD1E /* PhotoPreviewController.swift in Sources */, 157 | 26BF2F8120E4C69D00AFBD1E /* PreviewsCollectionViewCell.swift in Sources */, 158 | 260FAF0720DFA36E0036E494 /* CameraController.swift in Sources */, 159 | 260FAEF320DF78050036E494 /* CameraViewController.swift in Sources */, 160 | 260FAEF120DF78050036E494 /* AppDelegate.swift in Sources */, 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | /* End PBXSourcesBuildPhase section */ 165 | 166 | /* Begin PBXVariantGroup section */ 167 | 260FAEF420DF78050036E494 /* Camera.storyboard */ = { 168 | isa = PBXVariantGroup; 169 | children = ( 170 | 260FAEF520DF78050036E494 /* Base */, 171 | ); 172 | name = Camera.storyboard; 173 | sourceTree = ""; 174 | }; 175 | 260FAEF920DF780C0036E494 /* LaunchScreen.storyboard */ = { 176 | isa = PBXVariantGroup; 177 | children = ( 178 | 260FAEFA20DF780C0036E494 /* Base */, 179 | ); 180 | name = LaunchScreen.storyboard; 181 | sourceTree = ""; 182 | }; 183 | /* End PBXVariantGroup section */ 184 | 185 | /* Begin XCBuildConfiguration section */ 186 | 260FAEFD20DF780C0036E494 /* Debug */ = { 187 | isa = XCBuildConfiguration; 188 | buildSettings = { 189 | ALWAYS_SEARCH_USER_PATHS = NO; 190 | CLANG_ANALYZER_NONNULL = YES; 191 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 192 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 193 | CLANG_CXX_LIBRARY = "libc++"; 194 | CLANG_ENABLE_MODULES = YES; 195 | CLANG_ENABLE_OBJC_ARC = YES; 196 | CLANG_ENABLE_OBJC_WEAK = YES; 197 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 198 | CLANG_WARN_BOOL_CONVERSION = YES; 199 | CLANG_WARN_COMMA = YES; 200 | CLANG_WARN_CONSTANT_CONVERSION = YES; 201 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 202 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 203 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 204 | CLANG_WARN_EMPTY_BODY = YES; 205 | CLANG_WARN_ENUM_CONVERSION = YES; 206 | CLANG_WARN_INFINITE_RECURSION = YES; 207 | CLANG_WARN_INT_CONVERSION = YES; 208 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 209 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 210 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 211 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 212 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 213 | CLANG_WARN_STRICT_PROTOTYPES = YES; 214 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 215 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 216 | CLANG_WARN_UNREACHABLE_CODE = YES; 217 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 218 | CODE_SIGN_IDENTITY = "iPhone Developer"; 219 | COPY_PHASE_STRIP = NO; 220 | DEBUG_INFORMATION_FORMAT = dwarf; 221 | ENABLE_STRICT_OBJC_MSGSEND = YES; 222 | ENABLE_TESTABILITY = YES; 223 | GCC_C_LANGUAGE_STANDARD = gnu11; 224 | GCC_DYNAMIC_NO_PIC = NO; 225 | GCC_NO_COMMON_BLOCKS = YES; 226 | GCC_OPTIMIZATION_LEVEL = 0; 227 | GCC_PREPROCESSOR_DEFINITIONS = ( 228 | "DEBUG=1", 229 | "$(inherited)", 230 | ); 231 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 232 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 233 | GCC_WARN_UNDECLARED_SELECTOR = YES; 234 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 235 | GCC_WARN_UNUSED_FUNCTION = YES; 236 | GCC_WARN_UNUSED_VARIABLE = YES; 237 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 238 | MTL_ENABLE_DEBUG_INFO = YES; 239 | ONLY_ACTIVE_ARCH = YES; 240 | SDKROOT = iphoneos; 241 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 242 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 243 | }; 244 | name = Debug; 245 | }; 246 | 260FAEFE20DF780C0036E494 /* Release */ = { 247 | isa = XCBuildConfiguration; 248 | buildSettings = { 249 | ALWAYS_SEARCH_USER_PATHS = NO; 250 | CLANG_ANALYZER_NONNULL = YES; 251 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 252 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 253 | CLANG_CXX_LIBRARY = "libc++"; 254 | CLANG_ENABLE_MODULES = YES; 255 | CLANG_ENABLE_OBJC_ARC = YES; 256 | CLANG_ENABLE_OBJC_WEAK = YES; 257 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 258 | CLANG_WARN_BOOL_CONVERSION = YES; 259 | CLANG_WARN_COMMA = YES; 260 | CLANG_WARN_CONSTANT_CONVERSION = YES; 261 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 262 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 263 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 264 | CLANG_WARN_EMPTY_BODY = YES; 265 | CLANG_WARN_ENUM_CONVERSION = YES; 266 | CLANG_WARN_INFINITE_RECURSION = YES; 267 | CLANG_WARN_INT_CONVERSION = YES; 268 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 269 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 270 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 271 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 272 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 273 | CLANG_WARN_STRICT_PROTOTYPES = YES; 274 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 275 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 276 | CLANG_WARN_UNREACHABLE_CODE = YES; 277 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 278 | CODE_SIGN_IDENTITY = "iPhone Developer"; 279 | COPY_PHASE_STRIP = NO; 280 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 281 | ENABLE_NS_ASSERTIONS = NO; 282 | ENABLE_STRICT_OBJC_MSGSEND = YES; 283 | GCC_C_LANGUAGE_STANDARD = gnu11; 284 | GCC_NO_COMMON_BLOCKS = YES; 285 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 286 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 287 | GCC_WARN_UNDECLARED_SELECTOR = YES; 288 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 289 | GCC_WARN_UNUSED_FUNCTION = YES; 290 | GCC_WARN_UNUSED_VARIABLE = YES; 291 | IPHONEOS_DEPLOYMENT_TARGET = 11.4; 292 | MTL_ENABLE_DEBUG_INFO = NO; 293 | SDKROOT = iphoneos; 294 | SWIFT_COMPILATION_MODE = wholemodule; 295 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 296 | VALIDATE_PRODUCT = YES; 297 | }; 298 | name = Release; 299 | }; 300 | 260FAF0020DF780C0036E494 /* Debug */ = { 301 | isa = XCBuildConfiguration; 302 | buildSettings = { 303 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 304 | CODE_SIGN_STYLE = Automatic; 305 | DEVELOPMENT_TEAM = EPRAJ965WT; 306 | INFOPLIST_FILE = CustomCamera/Info.plist; 307 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 308 | LD_RUNPATH_SEARCH_PATHS = ( 309 | "$(inherited)", 310 | "@executable_path/Frameworks", 311 | ); 312 | PRODUCT_BUNDLE_IDENTIFIER = com.nfnlabs.AZCamera; 313 | PRODUCT_NAME = "$(TARGET_NAME)"; 314 | SWIFT_VERSION = 5.0; 315 | TARGETED_DEVICE_FAMILY = "1,2"; 316 | }; 317 | name = Debug; 318 | }; 319 | 260FAF0120DF780C0036E494 /* Release */ = { 320 | isa = XCBuildConfiguration; 321 | buildSettings = { 322 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 323 | CODE_SIGN_STYLE = Automatic; 324 | DEVELOPMENT_TEAM = EPRAJ965WT; 325 | INFOPLIST_FILE = CustomCamera/Info.plist; 326 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 327 | LD_RUNPATH_SEARCH_PATHS = ( 328 | "$(inherited)", 329 | "@executable_path/Frameworks", 330 | ); 331 | PRODUCT_BUNDLE_IDENTIFIER = com.nfnlabs.AZCamera; 332 | PRODUCT_NAME = "$(TARGET_NAME)"; 333 | SWIFT_VERSION = 5.0; 334 | TARGETED_DEVICE_FAMILY = "1,2"; 335 | }; 336 | name = Release; 337 | }; 338 | /* End XCBuildConfiguration section */ 339 | 340 | /* Begin XCConfigurationList section */ 341 | 260FAEE820DF78050036E494 /* Build configuration list for PBXProject "CustomCamera" */ = { 342 | isa = XCConfigurationList; 343 | buildConfigurations = ( 344 | 260FAEFD20DF780C0036E494 /* Debug */, 345 | 260FAEFE20DF780C0036E494 /* Release */, 346 | ); 347 | defaultConfigurationIsVisible = 0; 348 | defaultConfigurationName = Release; 349 | }; 350 | 260FAEFF20DF780C0036E494 /* Build configuration list for PBXNativeTarget "CustomCamera" */ = { 351 | isa = XCConfigurationList; 352 | buildConfigurations = ( 353 | 260FAF0020DF780C0036E494 /* Debug */, 354 | 260FAF0120DF780C0036E494 /* Release */, 355 | ); 356 | defaultConfigurationIsVisible = 0; 357 | defaultConfigurationName = Release; 358 | }; 359 | /* End XCConfigurationList section */ 360 | }; 361 | rootObject = 260FAEE520DF78050036E494 /* Project object */; 362 | } 363 | -------------------------------------------------------------------------------- /CustomCamera.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CustomCamera.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /CustomCamera/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // CustomCamera 4 | // 5 | // Created by 🅐🅝🅐🅢 on 24/06/18. 6 | // Copyright © 2018 nfnlabs. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | func applicationWillResignActive(_ application: UIApplication) { 22 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 23 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 24 | } 25 | 26 | func applicationDidEnterBackground(_ application: UIApplication) { 27 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 28 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 29 | } 30 | 31 | func applicationWillEnterForeground(_ application: UIApplication) { 32 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 33 | } 34 | 35 | func applicationDidBecomeActive(_ application: UIApplication) { 36 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 37 | } 38 | 39 | func applicationWillTerminate(_ application: UIApplication) { 40 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 41 | } 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Flash Off Icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_flash_off.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_flash_off_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_flash_off_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Flash Off Icon.imageset/ic_flash_off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/Flash Off Icon.imageset/ic_flash_off.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Flash Off Icon.imageset/ic_flash_off_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/Flash Off Icon.imageset/ic_flash_off_2x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Flash Off Icon.imageset/ic_flash_off_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/Flash Off Icon.imageset/ic_flash_off_3x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Flash On Icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "ic_flash_on.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "ic_flash_on_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "ic_flash_on_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | }, 23 | "properties" : { 24 | "template-rendering-intent" : "template" 25 | } 26 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Flash On Icon.imageset/ic_flash_on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/Flash On Icon.imageset/ic_flash_on.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Flash On Icon.imageset/ic_flash_on_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/Flash On Icon.imageset/ic_flash_on_2x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/Flash On Icon.imageset/ic_flash_on_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/Flash On Icon.imageset/ic_flash_on_3x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/camera_close.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icClear24Px.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "icClear24Px@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "icClear24Px@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/camera_close.imageset/icClear24Px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/camera_close.imageset/icClear24Px.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/camera_close.imageset/icClear24Px@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/camera_close.imageset/icClear24Px@2x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/camera_close.imageset/icClear24Px@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/camera_close.imageset/icClear24Px@3x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/camera_icon_green.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icCameraAlt24Px.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "icCameraAlt24Px@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "icCameraAlt24Px@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/camera_icon_green.imageset/icCameraAlt24Px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/camera_icon_green.imageset/icCameraAlt24Px.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/camera_icon_green.imageset/icCameraAlt24Px@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/camera_icon_green.imageset/icCameraAlt24Px@2x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/camera_icon_green.imageset/icCameraAlt24Px@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/camera_icon_green.imageset/icCameraAlt24Px@3x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/delete_icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "icDelete48Px.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "icDelete48Px@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "icDelete48Px@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/delete_icon.imageset/icDelete48Px.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/delete_icon.imageset/icDelete48Px.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/delete_icon.imageset/icDelete48Px@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/delete_icon.imageset/icDelete48Px@2x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/delete_icon.imageset/icDelete48Px@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/delete_icon.imageset/icDelete48Px@3x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/photo_camera.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "baseline_photo_camera_white_24pt_1x.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "baseline_photo_camera_white_24pt_2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "baseline_photo_camera_white_24pt_3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/photo_camera.imageset/baseline_photo_camera_white_24pt_1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/photo_camera.imageset/baseline_photo_camera_white_24pt_1x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/photo_camera.imageset/baseline_photo_camera_white_24pt_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/photo_camera.imageset/baseline_photo_camera_white_24pt_2x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/photo_camera.imageset/baseline_photo_camera_white_24pt_3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/photo_camera.imageset/baseline_photo_camera_white_24pt_3x.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "filename" : "Rotate icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "filename" : "Rotate icon@ @2X.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "filename" : "Rotate icon@3X.png", 16 | "scale" : "3x" 17 | }, 18 | { 19 | "idiom" : "ipad", 20 | "filename" : "Rotate icon-1.png", 21 | "scale" : "1x" 22 | }, 23 | { 24 | "idiom" : "ipad", 25 | "filename" : "Rotate icon@ @2X-1.png", 26 | "scale" : "2x" 27 | } 28 | ], 29 | "info" : { 30 | "version" : 1, 31 | "author" : "xcode" 32 | }, 33 | "properties" : { 34 | "template-rendering-intent" : "original" 35 | } 36 | } -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon-1.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon@ @2X-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon@ @2X-1.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon@ @2X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon@ @2X.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon@3X.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/CustomCamera/Assets.xcassets/Camera icons/rotate.imageset/Rotate icon@3X.png -------------------------------------------------------------------------------- /CustomCamera/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /CustomCamera/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /CustomCamera/Camera Controller/Base.lproj/Camera.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 83 | 94 | 105 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 177 | 188 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 260 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | -------------------------------------------------------------------------------- /CustomCamera/Camera Controller/CameraController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CameraController.swift 3 | // AV Foundation 4 | // 5 | // Created by 🅐🅝🅐🅢 on 24/06/18. 6 | // Copyright © 2018 nfnlabs. All rights reserved. 7 | // GitHub: https://github.com/anasamanp/AZCameraView 8 | 9 | import AVFoundation 10 | import UIKit 11 | 12 | class CameraController: NSObject { 13 | var captureSession: AVCaptureSession? 14 | 15 | var currentCameraPosition: CameraPosition? 16 | 17 | var frontCamera: AVCaptureDevice? 18 | var frontCameraInput: AVCaptureDeviceInput? 19 | 20 | var photoOutput: AVCapturePhotoOutput? 21 | 22 | var rearCamera: AVCaptureDevice? 23 | var rearCameraInput: AVCaptureDeviceInput? 24 | 25 | var previewLayer: AVCaptureVideoPreviewLayer? 26 | 27 | var flashMode = AVCaptureDevice.FlashMode.off 28 | var photoCaptureCompletionBlock: ((UIImage?, Error?) -> Void)? 29 | } 30 | 31 | extension CameraController { 32 | func prepare(completionHandler: @escaping (Error?) -> Void) { 33 | func createCaptureSession() { 34 | self.previewLayer?.removeFromSuperlayer() 35 | self.captureSession = AVCaptureSession() 36 | } 37 | 38 | func configureCaptureDevices() throws { 39 | guard let session = AVCaptureDevice.default(.builtInWideAngleCamera, for: AVMediaType.video, position: .back) else { return } 40 | self.rearCamera = session 41 | try self.rearCamera?.lockForConfiguration() 42 | self.rearCamera?.focusMode = .continuousAutoFocus 43 | self.rearCamera?.unlockForConfiguration() 44 | } 45 | 46 | func configureDeviceInputs() throws { 47 | guard let captureSession = self.captureSession else { throw CameraControllerError.captureSessionIsMissing } 48 | 49 | if let rearCamera = self.rearCamera { 50 | self.rearCameraInput = try AVCaptureDeviceInput(device: rearCamera) 51 | 52 | if captureSession.canAddInput(self.rearCameraInput!) { captureSession.addInput(self.rearCameraInput!) } 53 | 54 | self.currentCameraPosition = .rear 55 | } 56 | else if let frontCamera = self.frontCamera { 57 | self.frontCameraInput = try AVCaptureDeviceInput(device: frontCamera) 58 | 59 | if captureSession.canAddInput(self.frontCameraInput!) { captureSession.addInput(self.frontCameraInput!) } 60 | else { throw CameraControllerError.inputsAreInvalid } 61 | 62 | self.currentCameraPosition = .front 63 | } 64 | 65 | else { throw CameraControllerError.noCamerasAvailable } 66 | } 67 | 68 | func configurePhotoOutput() throws { 69 | guard let captureSession = self.captureSession else { throw CameraControllerError.captureSessionIsMissing } 70 | 71 | self.photoOutput = AVCapturePhotoOutput() 72 | if #available(iOS 11.0, *) { 73 | self.photoOutput!.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey : AVVideoCodecType.jpeg])], completionHandler: nil) 74 | } else { 75 | self.photoOutput!.setPreparedPhotoSettingsArray([AVCapturePhotoSettings(format: [AVVideoCodecKey : AVVideoCodecJPEG])], completionHandler: nil) 76 | } 77 | 78 | if captureSession.canAddOutput(self.photoOutput!) { captureSession.addOutput(self.photoOutput!) } 79 | captureSession.startRunning() 80 | } 81 | 82 | DispatchQueue(label: "prepare").async { 83 | do { 84 | createCaptureSession() 85 | try configureCaptureDevices() 86 | try configureDeviceInputs() 87 | try configurePhotoOutput() 88 | } 89 | catch { 90 | DispatchQueue.main.async { 91 | completionHandler(error) 92 | } 93 | return 94 | } 95 | DispatchQueue.main.async { 96 | completionHandler(nil) 97 | } 98 | } 99 | } 100 | 101 | func displayPreview(on view: UIView) throws { 102 | guard let captureSession = self.captureSession, captureSession.isRunning else { throw CameraControllerError.captureSessionIsMissing } 103 | self.previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) 104 | self.previewLayer?.videoGravity = AVLayerVideoGravity.resizeAspectFill 105 | 106 | if UIDevice.current.orientation.isLandscape { 107 | self.previewLayer?.connection?.videoOrientation = .landscapeRight 108 | } 109 | else{ 110 | self.previewLayer?.connection?.videoOrientation = .portrait 111 | } 112 | view.layer.insertSublayer(self.previewLayer!, at: 0) 113 | self.previewLayer?.frame = view.frame 114 | } 115 | 116 | func switchCameras() throws { 117 | guard let currentCameraPosition = currentCameraPosition, let captureSession = self.captureSession, captureSession.isRunning else { throw CameraControllerError.captureSessionIsMissing } 118 | 119 | captureSession.beginConfiguration() 120 | 121 | func switchToFrontCamera() throws { 122 | 123 | guard let rearCameraInput = self.rearCameraInput, captureSession.inputs.contains(rearCameraInput), 124 | let frontCamera = self.frontCamera else { throw CameraControllerError.invalidOperation } 125 | 126 | self.frontCameraInput = try AVCaptureDeviceInput(device: frontCamera) 127 | 128 | captureSession.removeInput(rearCameraInput) 129 | 130 | if captureSession.canAddInput(self.frontCameraInput!) { 131 | captureSession.addInput(self.frontCameraInput!) 132 | 133 | self.currentCameraPosition = .front 134 | } 135 | 136 | else { 137 | throw CameraControllerError.invalidOperation 138 | } 139 | } 140 | 141 | func switchToRearCamera() throws { 142 | 143 | guard let frontCameraInput = self.frontCameraInput, captureSession.inputs.contains(frontCameraInput), 144 | let rearCamera = self.rearCamera else { throw CameraControllerError.invalidOperation } 145 | 146 | self.rearCameraInput = try AVCaptureDeviceInput(device: rearCamera) 147 | 148 | captureSession.removeInput(frontCameraInput) 149 | 150 | if captureSession.canAddInput(self.rearCameraInput!) { 151 | captureSession.addInput(self.rearCameraInput!) 152 | 153 | self.currentCameraPosition = .rear 154 | } 155 | 156 | else { throw CameraControllerError.invalidOperation } 157 | } 158 | 159 | switch currentCameraPosition { 160 | case .front: 161 | try switchToRearCamera() 162 | 163 | case .rear: 164 | try switchToFrontCamera() 165 | } 166 | 167 | captureSession.commitConfiguration() 168 | } 169 | 170 | func captureImage(completion: @escaping (UIImage?, Error?) -> Void) { 171 | guard let captureSession = captureSession, captureSession.isRunning else { completion(nil, CameraControllerError.captureSessionIsMissing); return } 172 | 173 | let settings = AVCapturePhotoSettings() 174 | settings.flashMode = self.flashMode 175 | 176 | if let photoOutputConnection = self.photoOutput?.connection(with: AVMediaType.video) { 177 | switch UIDevice.current.orientation{ 178 | case .landscapeLeft: 179 | photoOutputConnection.videoOrientation = .landscapeRight 180 | case .landscapeRight: 181 | photoOutputConnection.videoOrientation = .landscapeLeft 182 | case .portrait: 183 | photoOutputConnection.videoOrientation = .portrait 184 | case .portraitUpsideDown: 185 | photoOutputConnection.videoOrientation = .portraitUpsideDown 186 | case .faceUp: 187 | if UIApplication.shared.statusBarOrientation == .landscapeLeft { 188 | photoOutputConnection.videoOrientation = .portrait 189 | } 190 | else { 191 | photoOutputConnection.videoOrientation = .landscapeRight 192 | } 193 | case .faceDown: 194 | if UIApplication.shared.statusBarOrientation == .portrait { 195 | photoOutputConnection.videoOrientation = .landscapeRight 196 | } 197 | else { 198 | photoOutputConnection.videoOrientation = .portrait 199 | } 200 | default: 201 | break 202 | } 203 | } 204 | self.photoOutput?.capturePhoto(with: settings, delegate: self) 205 | self.photoCaptureCompletionBlock = completion 206 | } 207 | 208 | } 209 | 210 | extension CameraController: AVCapturePhotoCaptureDelegate { 211 | public func photoOutput(_ captureOutput: AVCapturePhotoOutput, didFinishProcessingPhoto photoSampleBuffer: CMSampleBuffer?, previewPhoto previewPhotoSampleBuffer: CMSampleBuffer?, 212 | resolvedSettings: AVCaptureResolvedPhotoSettings, bracketSettings: AVCaptureBracketedStillImageSettings?, error: Swift.Error?) { 213 | if let error = error { self.photoCaptureCompletionBlock?(nil, error) } 214 | 215 | else if let buffer = photoSampleBuffer, let data = AVCapturePhotoOutput.jpegPhotoDataRepresentation(forJPEGSampleBuffer: buffer, previewPhotoSampleBuffer: nil), 216 | let image = UIImage(data: data) { 217 | 218 | self.photoCaptureCompletionBlock?(image, nil) 219 | } 220 | 221 | else { 222 | self.photoCaptureCompletionBlock?(nil, CameraControllerError.unknown) 223 | } 224 | } 225 | } 226 | 227 | extension CameraController { 228 | enum CameraControllerError: Swift.Error { 229 | case captureSessionAlreadyRunning 230 | case captureSessionIsMissing 231 | case inputsAreInvalid 232 | case invalidOperation 233 | case noCamerasAvailable 234 | case unknown 235 | } 236 | 237 | public enum CameraPosition { 238 | case front 239 | case rear 240 | } 241 | } 242 | -------------------------------------------------------------------------------- /CustomCamera/Camera Controller/CameraViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CameraViewController.swift 3 | // CustomCamera 4 | // 5 | // Created by 🅐🅝🅐🅢 on 24/06/18. 6 | // Copyright © 2018 nfnlabs. All rights reserved. 7 | // GitHub: https://github.com/anasamanp/AZCameraView 8 | 9 | import UIKit 10 | import Photos 11 | 12 | protocol CameraViewControllerDelagate { 13 | /** 14 | Get the captured photos 15 | - parameter photos: Photos array 16 | */ 17 | func getCapturedPhotos(photos: [UIImage]) 18 | } 19 | 20 | class CameraViewController: UIViewController { 21 | 22 | // MARK: - Outlets 23 | @IBOutlet weak var capturePreviewView: UIView! 24 | @IBOutlet weak var btnCapture: UIButton! 25 | @IBOutlet weak var photoPreview: UIImageView! 26 | @IBOutlet weak var btnAdd: UIButton! 27 | @IBOutlet weak var btnClose: UIButton! 28 | @IBOutlet weak var btnFlashToggle: UIButton! 29 | @IBOutlet weak var btnCount: UIButton! 30 | @IBOutlet weak var lblMaxAlert: UILabel! 31 | @IBOutlet weak var photoPreviewView: UIView! 32 | 33 | // MARK: - Variables 34 | var photosCountLimit = 5 35 | var delegate: CameraViewControllerDelagate? 36 | let cameraController = CameraController() 37 | var photos = [UIImage]() 38 | 39 | var widthConstraint = NSLayoutConstraint() 40 | var rightConstraint = NSLayoutConstraint() 41 | 42 | 43 | // MARK: - View Lifecycle 44 | override func viewDidLoad() { 45 | super.viewDidLoad() 46 | 47 | let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.previewTapped(rocignizer:))) 48 | self.photoPreviewView.addGestureRecognizer(tapGesture) 49 | 50 | self.hideOrShowPreview() 51 | configureCameraController() 52 | } 53 | 54 | override func viewWillAppear(_ animated: Bool) { 55 | super.viewWillAppear(animated) 56 | 57 | NotificationCenter.default.addObserver(self, selector: #selector(self.orientationChanged(notification:)), name: UIDevice.orientationDidChangeNotification, object: nil) 58 | } 59 | 60 | //Uncomment this to remove status bar 61 | // override var prefersStatusBarHidden: Bool { return true } 62 | 63 | @objc func orientationChanged(notification:Notification){ 64 | switch UIDevice.current.orientation { 65 | case .landscapeLeft: 66 | self.setFramesForLandscape(with: CGFloat.pi/2) 67 | case .landscapeRight: 68 | self.setFramesForLandscape(with: -(CGFloat.pi/2)) 69 | case .faceUp: 70 | self.setFramesForPortrait() 71 | default: 72 | self.setFramesForPortrait() 73 | } 74 | } 75 | 76 | override func viewWillDisappear(_ animated: Bool) { 77 | super.viewWillDisappear(animated) 78 | NotificationCenter.default.removeObserver(UIDevice.orientationDidChangeNotification) 79 | } 80 | 81 | override func viewDidLayoutSubviews() { 82 | super.viewDidLayoutSubviews() 83 | btnCapture.layer.cornerRadius = btnCapture.bounds.width/2 84 | btnCapture.layer.borderColor = UIColor.white.cgColor 85 | btnCapture.layer.borderWidth = 3 86 | photoPreview.layer.borderWidth = 0.5 87 | photoPreview.layer.borderColor = UIColor.white.cgColor 88 | photoPreview.layer.cornerRadius = 5 89 | btnAdd.layer.cornerRadius = btnAdd.bounds.width/2 90 | btnCount.layer.cornerRadius = btnCount.bounds.width/2 91 | lblMaxAlert.layer.cornerRadius = 3 92 | } 93 | 94 | // MARK: - Actions 95 | // Capture the photo 96 | @IBAction func btnCaptureOnClick(_ sender: UIButton) { 97 | cameraController.captureImage {(image, error) in 98 | guard let image = image else { 99 | print(error ?? "Image capture error") 100 | return 101 | } 102 | 103 | self.photos.append(image) 104 | self.hideOrShowPreview() 105 | 106 | //Save photos to library 107 | //Comment this if you don't want to save to PhotoLibrary 108 | try? PHPhotoLibrary.shared().performChangesAndWait { 109 | PHAssetChangeRequest.creationRequestForAsset(from: image) 110 | } 111 | } 112 | } 113 | 114 | // Action for add button 115 | @IBAction func btnAddOnClick(_ sender: UIButton) { 116 | self.delegate?.getCapturedPhotos(photos: self.photos) 117 | self.dismiss(animated: true, completion: nil) 118 | } 119 | 120 | // Action for cancel button 121 | @IBAction func btnCloseOnClick(_ sender: UIButton) { 122 | self.dismiss(animated: true, completion: nil) 123 | } 124 | 125 | // Action for flash button 126 | @IBAction func btnFlashToggleOnClick(_ sender: UIButton) { 127 | if cameraController.flashMode == .on { 128 | cameraController.flashMode = .off 129 | btnFlashToggle.setImage(#imageLiteral(resourceName: "Flash Off Icon"), for: .normal) 130 | } 131 | else { 132 | cameraController.flashMode = .on 133 | btnFlashToggle.setImage(#imageLiteral(resourceName: "Flash On Icon"), for: .normal) 134 | } 135 | } 136 | 137 | // When tap on preview 138 | @objc func previewTapped(rocignizer: UIGestureRecognizer) { 139 | if let photoPVC = UIStoryboard(name: "Camera", bundle: nil).instantiateViewController(withIdentifier: "PhotoPreviewController") as? PhotoPreviewController{ 140 | photoPVC.delegate = self 141 | photoPVC.previewPhotos = self.photos 142 | photoPVC.modalPresentationStyle = .fullScreen 143 | photoPVC.modalTransitionStyle = .crossDissolve 144 | self.present(photoPVC, animated: true, completion: nil) 145 | } 146 | } 147 | 148 | // MARK: - Helper Methods 149 | 150 | /// Set/change icons when change the orientation 151 | func setFramesForPortrait(){ 152 | UIView.animate(withDuration: 0.3) { 153 | self.btnCapture.transform = CGAffineTransform(rotationAngle: 0) 154 | self.btnFlashToggle.transform = CGAffineTransform(rotationAngle: 0) 155 | self.btnAdd.transform = CGAffineTransform(rotationAngle: 0) 156 | self.photoPreview.transform = CGAffineTransform(rotationAngle: 0) 157 | self.btnCount.transform = CGAffineTransform(rotationAngle: 0) 158 | } 159 | } 160 | 161 | func setFramesForLandscape(with angle: CGFloat){ 162 | UIView.animate(withDuration: 0.3) { 163 | self.btnCapture.transform = CGAffineTransform(rotationAngle: angle) 164 | self.btnFlashToggle.transform = CGAffineTransform(rotationAngle: angle) 165 | self.btnAdd.transform = CGAffineTransform(rotationAngle: angle) 166 | self.photoPreview.transform = CGAffineTransform(rotationAngle: angle) 167 | self.btnCount.transform = CGAffineTransform(rotationAngle: angle) 168 | } 169 | } 170 | 171 | /** 172 | Manage UI respect to photos count / Hide or show elements 173 | */ 174 | func hideOrShowPreview(){ 175 | if photos.count == self.photosCountLimit{ 176 | btnCapture.isUserInteractionEnabled = false 177 | btnCapture.alpha = 0.5 178 | lblMaxAlert.isHidden = false 179 | } 180 | else{ 181 | btnCapture.isUserInteractionEnabled = true 182 | btnCapture.alpha = 1 183 | lblMaxAlert.isHidden = true 184 | } 185 | 186 | if photos.count > 0{ 187 | self.btnAdd.isHidden = false 188 | self.btnCount.isHidden = false 189 | self.photoPreview.isHidden = false 190 | self.photoPreviewView.isHidden = false 191 | self.photoPreview.image = self.photos.last 192 | self.btnCount.setTitle("\(self.photos.count)", for: .normal) 193 | } 194 | else{ 195 | self.btnAdd.isHidden = true 196 | self.btnCount.isHidden = true 197 | self.photoPreview.isHidden = true 198 | self.photoPreviewView.isHidden = true 199 | } 200 | } 201 | 202 | // MARK: - Cofigure camera 203 | func configureCameraController() { 204 | cameraController.prepare {(error) in 205 | if let error = error { 206 | print(error) 207 | } 208 | 209 | try? self.cameraController.displayPreview(on: self.capturePreviewView) 210 | } 211 | } 212 | 213 | } 214 | 215 | // MARK: - PhotoPreviewControllerDelegate 216 | extension CameraViewController: PhotoPreviewControllerDelegate { 217 | func deletedPhotoIndex(index: Int) { 218 | self.photos.remove(at: index) 219 | self.photoPreview.image = self.photos.last 220 | self.btnCount.setTitle("\(self.photos.count)", for: .normal) 221 | self.hideOrShowPreview() 222 | } 223 | 224 | func addPhotosOnClick() { 225 | self.delegate?.getCapturedPhotos(photos: self.photos) 226 | } 227 | } 228 | 229 | 230 | 231 | 232 | -------------------------------------------------------------------------------- /CustomCamera/Camera Controller/PhotoPreviewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PhotoPreviewController.swift 3 | // CustomCamera 4 | // 5 | // Created by 🅐🅝🅐🅢 on 28/06/18. 6 | // Copyright © 2018 nfnlabs. All rights reserved. 7 | // GitHub: https://github.com/anasamanp/AZCameraView 8 | 9 | import UIKit 10 | 11 | protocol PhotoPreviewControllerDelegate { 12 | func deletedPhotoIndex(index:Int) 13 | func addPhotosOnClick() 14 | } 15 | 16 | 17 | class PhotoPreviewController: UIViewController { 18 | 19 | // MARK: - Outlets 20 | @IBOutlet weak var btnPhoto: UIButton! 21 | @IBOutlet weak var btnAdd: UIButton! 22 | @IBOutlet weak var collectionView: UICollectionView! 23 | @IBOutlet weak var imgView: UIImageView! 24 | @IBOutlet weak var btnDelete: UIButton! 25 | @IBOutlet weak var btnRotate: UIButton! 26 | 27 | 28 | // MARK: - Variables 29 | var delegate : PhotoPreviewControllerDelegate? 30 | var previewPhotos = [UIImage]() 31 | var selectedIndex = 0 32 | 33 | // MARK: - View Lifecycle 34 | override func viewDidLoad() { 35 | super.viewDidLoad() 36 | self.btnDelete.isHidden = previewPhotos.count == 1 ? true : false 37 | self.imgView.image = previewPhotos[selectedIndex] 38 | } 39 | 40 | override func viewDidLayoutSubviews() { 41 | super.viewDidLayoutSubviews() 42 | self.btnPhoto.layer.cornerRadius = self.btnPhoto.bounds.width/2 43 | self.btnAdd.layer.cornerRadius = btnAdd.bounds.width/2 44 | } 45 | 46 | 47 | // MARK: - Actions & Targets 48 | @IBAction func btnPhotoOnClick(_ sender: UIButton) { 49 | self.dismiss(animated: true, completion: nil) 50 | } 51 | 52 | @IBAction func btnCloseOnClick(_ sender: UIButton) { 53 | self.view.window?.rootViewController?.dismiss(animated: true, completion: nil) 54 | } 55 | 56 | @IBAction func btnDeleteOnClick(_ sender: UIButton) { 57 | self.previewPhotos.remove(at: selectedIndex) 58 | self.delegate?.deletedPhotoIndex(index: selectedIndex) 59 | if selectedIndex > self.previewPhotos.count - 1 { 60 | self.selectedIndex = 0 61 | } 62 | self.imgView.image = self.previewPhotos[selectedIndex] 63 | self.collectionView.reloadData() 64 | self.btnDelete.isHidden = previewPhotos.count == 1 ? true : false 65 | } 66 | 67 | @IBAction func btnAddOnClick(_ sender: UIButton) { 68 | delegate?.addPhotosOnClick() 69 | self.view.window?.rootViewController?.dismiss(animated: true, completion: nil) 70 | } 71 | 72 | @IBAction func btnRotateOnClick(_ sender: UIButton) { 73 | let image = previewPhotos[self.selectedIndex] 74 | guard let newImage = image.rotate(radians: .pi/2) else { return } 75 | self.previewPhotos.remove(at: self.selectedIndex) 76 | self.previewPhotos.insert(newImage, at: self.selectedIndex) 77 | self.collectionView.reloadData() 78 | self.imgView.image = previewPhotos[self.selectedIndex] 79 | } 80 | 81 | } 82 | 83 | // MARK: - CollectionView DataSource 84 | extension PhotoPreviewController: UICollectionViewDataSource { 85 | 86 | func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 87 | return self.previewPhotos.count 88 | } 89 | 90 | func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 91 | var previewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewsCollectionViewCell", for: indexPath) as? PreviewsCollectionViewCell 92 | 93 | if previewCell == nil { 94 | collectionView.register(UINib(nibName:"PreviewsCollectionViewCell", bundle:nil), forCellWithReuseIdentifier: "PreviewsCollectionViewCell") 95 | previewCell = collectionView.dequeueReusableCell(withReuseIdentifier: "PreviewsCollectionViewCell", for: indexPath) as? PreviewsCollectionViewCell 96 | } 97 | let isSelected = self.selectedIndex == indexPath.row ? true : false 98 | previewCell?.setImage(image: self.previewPhotos[indexPath.row], selectedIndex: isSelected) 99 | return previewCell! 100 | } 101 | 102 | } 103 | 104 | // MARK: - CollectionView Delegate 105 | extension PhotoPreviewController: UICollectionViewDelegate { 106 | func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { 107 | self.selectedIndex = indexPath.row 108 | self.imgView.image = previewPhotos[indexPath.row] 109 | self.collectionView.reloadData() 110 | } 111 | } 112 | 113 | extension UIImage { 114 | /** 115 | Rotate UIImage 116 | - Parameter radians: .pi is 180 deg, .pi/2 is 90 deg, .pi/4 is 45 deg, ..., .pi/180 is 1 deg. 117 | */ 118 | func rotate(radians: Float) -> UIImage? { 119 | var newSize = CGRect(origin: CGPoint.zero, size: self.size).applying(CGAffineTransform(rotationAngle: CGFloat(radians))).size 120 | // Trim off the extremely small float value to prevent core graphics from rounding it up 121 | newSize.width = floor(newSize.width) 122 | newSize.height = floor(newSize.height) 123 | 124 | UIGraphicsBeginImageContextWithOptions(newSize, false, self.scale) 125 | let context = UIGraphicsGetCurrentContext()! 126 | 127 | // Move origin to middle 128 | context.translateBy(x: newSize.width/2, y: newSize.height/2) 129 | // Rotate around middle 130 | context.rotate(by: CGFloat(radians)) 131 | // Draw the image at its center 132 | self.draw(in: CGRect(x: -self.size.width/2, y: -self.size.height/2, width: self.size.width, height: self.size.height)) 133 | 134 | let newImage = UIGraphicsGetImageFromCurrentImageContext() 135 | UIGraphicsEndImageContext() 136 | 137 | return newImage 138 | } 139 | } 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /CustomCamera/Camera Controller/PreviewsCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PreviewsCollectionViewCell.swift 3 | // CustomCamera 4 | // 5 | // Created by 🅐🅝🅐🅢 on 28/06/18. 6 | // Copyright © 2018 nfnlabs. All rights reserved. 7 | // GitHub: https://github.com/anasamanp/AZCameraView 8 | 9 | import UIKit 10 | 11 | class PreviewsCollectionViewCell: UICollectionViewCell { 12 | 13 | @IBOutlet weak var imgView: UIImageView! 14 | 15 | override func awakeFromNib() { 16 | self.layer.borderWidth = 1 17 | self.layer.borderColor = UIColor.white.cgColor 18 | } 19 | 20 | func setImage(image:UIImage, selectedIndex: Bool){ 21 | self.imgView.image = image 22 | if selectedIndex{ 23 | self.layer.borderColor = UIColor.red.cgColor 24 | } 25 | else{ 26 | self.layer.borderColor = UIColor.white.cgColor 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /CustomCamera/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | AZCamera 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSCameraUsageDescription 26 | This app requires access to the camera. 27 | NSPhotoLibraryUsageDescription 28 | This app requires access to the photo library. 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Camera 33 | UIRequiredDeviceCapabilities 34 | 35 | armv7 36 | 37 | UIRequiresFullScreen 38 | 39 | UISupportedInterfaceOrientations 40 | 41 | UIInterfaceOrientationPortrait 42 | 43 | UISupportedInterfaceOrientations~ipad 44 | 45 | UIInterfaceOrientationPortrait 46 | UIInterfaceOrientationPortraitUpsideDown 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AZCameraView 2 | 3 | - Full screen camera view 4 | - Support Orientation 5 | - Flash 6 | - Photo count 7 | - Photos limit 8 | - Photo preview 9 | - Image rotation 10 | - Delete option 11 | 12 | ![](https://github.com/anasamanp/AZCameraView/blob/master/an2.png) 13 | -------------------------------------------------------------------------------- /an2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/anas-p/AZCameraView/6876edb5c6041875c13eb8d495fa82b06aa2497d/an2.png --------------------------------------------------------------------------------