SoFunction
Updated on 2025-04-13

iOS custom camera features

Most apps involve uploading photos, and the source of the picture is nothing more than obtaining it from the album or taking it at the camera. If it is not a special requirement, the calling system has met the requirements. But for special needs, you need to customize the camera shooting interface.

For cameras that do not require customization, use the UIImagePickerController class in the system's UIKit library, a few lines of code and a few proxy methods to meet the needs. But if you want to deeply customize, you need related classes inside the system library AVFoundation.

Create your own camera management class CameraManager (inherited from NSObject)

.h file

#import <Foundation/>
#import <AVFoundation/>
//Callback after taking a photo, transfer the taken photostypedef void(^DidCapturePhotoBlock)(UIImage *stillImage);

@interface PXCameraManager : NSObject

@property (nonatomic, strong) AVCaptureSession *session;// AVCaptureSession object to perform data transfer between input device and output device
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;//Preview the layer to display the picture taken by the camera
@property (nonatomic, strong) AVCaptureDeviceInput *deviceInput;//AVCaptureDeviceInput object is the input stream
@property (nonatomic, strong) AVCaptureStillImageOutput *stillImageOutput;//Photo output stream object
@property (nonatomic, assign) CGRect previewLayerFrame;//Photo area
/* Custom interfaces provided for other classes */

//Set the photo area (where targetView is the view to display the photo interface)- (void)configureWithtargetViewLayer:(UIView *)targetView previewRect:(CGRect)preivewRect;

//A successful callback- (void)takePicture:(DidCapturePhotoBlock)block;

//Add/Remove the camera floating layer (If you have any requirements, use it when adding floating layer in the camera photography area)- (void)addCoverImageWithImage:(UIImage *)image;
- (void)removeCoverImageWithImage:(UIImage *)image;

//Front and rear camera switching- (void)switchCameras;

//Flash switch- (void)configCameraFlashlight;


@end

.m file

@property (nonatomic, strong) UIView *preview;//Show the view of the photo area@property (nonatomic, strong) UIImageView *coverImageView;//Floating layer of the photo area
@property (nonatomic, assign) BOOL isCaremaBack;
@property (nonatomic, assign) AVCaptureFlashMode flashMode;

//Set the default properties you want when initializing- (instancetype)init{

    self = [super init];
    if (self) {

         = YES;//Default rear camera         = AVCaptureFlashModeAuto;//Default automatic flash    }
    return  self;
}

Methods to implement interfaces

1. Prepare related hardware

- (void)configureWithTargetViewLayer:(UIView *)targetView previewRect:(CGRect)preivewRect{

     = targetView;

    //Start some camera-related hardware configurations    [self addSession];//Create session
    [self addVideoPreviewLayerWithRect:preivewRect];//Create with session Create layer
    [self addvideoInputBackCamera:];//Configure the camera for session
    [self addVideoFlashlightWithFlashModel:];//Configure flash
    [self addStillImageOutput];//Configure the output for session}

2. Take photos

#pragma mark - 
- (void)takePicture:(DidCapturePhotoBlock)block{

    AVCaptureConnection *captureConnection = [self findCaptureConnection];

    [captureConnection setVideoScaleAndCropFactor:1.0f];

    [_stillImageOutput captureStillImageAsynchronouslyFromConnection:captureConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {

        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];

        UIImage *image = [UIImage imageWithData:imageData];
        // Here you can compress or crop the photos you take according to different needs, so I will be lazy here.        if (block) {
            block(image);
        }
    }];

}

3. Switch the camera

- (void)switchCameras{
    if (!_deviceInput) {
        return;
    }
    [_session beginConfiguration];

    [_session removeInput:_deviceInput];
     = !;
    [self addvideoInputBackCamera:];

    [_session commitConfiguration];
}

4. Switch the flash

- (void)configCameraFlashlight{

    switch () {
        case AVCaptureFlashModeAuto:
        {
             = AVCaptureFlashModeOff;
        }
            break;
        case AVCaptureFlashModeOff:
        {
             = AVCaptureFlashModeOn;
        }
            break;
        case AVCaptureFlashModeOn:
        {
             = AVCaptureFlashModeAuto;
        }
            break;
        default:
            break;
    }

    [self addVideoFlashlightWithFlashModel:];

 }

Add/remove floating layers

- (void)addCoverImageWithImage:(UIImage *)image{

    _coverImageView.image = image;
}
- (void)removeCoverImageWithImage:(UIImage *)image{

    _coverImageView.image = nil;

}

Here are a few ways to configure hardware

- (void)addSession{

    if (!) {
        AVCaptureSession *session = [[AVCaptureSession alloc]init];
         = session;
    }
}
- (void)addVideoPreviewLayerWithRect:(CGRect)previewRect{

    if (!) {
        AVCaptureVideoPreviewLayer *previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:_session];
         = AVLayerVideoGravityResizeAspectFill;

         = previewLayer;

        [ addSublayer:];

    }

     = previewRect;
}
- (void)addvideoInputBackCamera:(BOOL)back{

    NSArray *devices = [AVCaptureDevice devices];

    AVCaptureDevice *frontCamera;
    AVCaptureDevice *backCamera;
    //Get front and rear cameras    for (AVCaptureDevice *device in devices) {

        if ([device hasMediaType:AVMediaTypeVideo]) {

            if ([device position] == AVCaptureDevicePositionBack) {

                backCamera = device;

            }else if([device position] == AVCaptureDevicePositionFront){

                frontCamera = device;

            }
        }
    }

    NSError *error = nil;


    if(back){
        AVCaptureDeviceInput *backCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:backCamera error:&error];
        if (!error) {

            if ([_session canAddInput:backCameraDeviceInput]) {

                [_session addInput:backCameraDeviceInput];
                  = backCameraDeviceInput;

            }else{
                NSLog(@"It's wrong");
            }
        }

    }else{

        AVCaptureDeviceInput *frontCameraDeviceInput = [AVCaptureDeviceInput deviceInputWithDevice:frontCamera error:&error];
        if (!error) {

            if ([_session canAddInput:frontCameraDeviceInput]) {

                [_session addInput:frontCameraDeviceInput];
                  = frontCameraDeviceInput;

            }else{
                NSLog(@"It's wrong");
            }
        }
    }


}
- (void)addVideoFlashlightWithFlashModel:(AVCaptureFlashMode )flashModel{

    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    [device lockForConfiguration:nil];

    if ([device hasFlash]) {
         = ;
    }

    [device unlockForConfiguration];
}
- (void)addStillImageOutput{

    if (!) {

        AVCaptureStillImageOutput *stillImageOutput = [[AVCaptureStillImageOutput alloc]init];
        NSDictionary *outPutSettingDict = [[NSDictionary alloc]initWithObjectsAndKeys:AVVideoCodecJPEG,AVVideoCodecKey, nil];
         = outPutSettingDict;

        [_session addOutput:stillImageOutput];

         = stillImageOutput;
    }


}
- (AVCaptureConnection *)findCaptureConnection{


    AVCaptureConnection *videoConnection;

    for (AVCaptureConnection *connection in _stillImageOutput.connections ) {
        for (AVCaptureInputPort *port in ) {

            if ([[port mediaType] isEqual:AVMediaTypeVideo]) {

                videoConnection = connection;

                return videoConnection;
            }
        }
    }

    return nil;

}

At this point, a custom camera class is available. When you want to use it, just call it.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.