From 9ae6b9d751d0015d307bbce9462c952438e12369 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20G=C3=BCl?= Date: Sun, 4 Jan 2015 11:04:13 +0200 Subject: [PATCH 1/2] memory leak fixed after stopping the camera --- LLSimpleCamera/LLSimpleCamera.m | 86 +++++++++++----------- LLSimpleCameraExample/HomeViewController.m | 2 + 2 files changed, 45 insertions(+), 43 deletions(-) diff --git a/LLSimpleCamera/LLSimpleCamera.m b/LLSimpleCamera/LLSimpleCamera.m index 589845a..1c6391d 100644 --- a/LLSimpleCamera/LLSimpleCamera.m +++ b/LLSimpleCamera/LLSimpleCamera.m @@ -15,12 +15,11 @@ @interface LLSimpleCamera () @property (strong, nonatomic) UIView *preview; @property (strong, nonatomic) AVCaptureStillImageOutput *stillImageOutput; @property (strong, nonatomic) AVCaptureSession *session; -@property (strong, nonatomic) AVCaptureDevice *captureDevice; @property (strong, nonatomic) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; @end @implementation LLSimpleCamera -@synthesize captureDevice = _captureDevice; +//@synthesize captureDevice = _captureDevice; - (instancetype)initWithQuality:(CameraQuality)quality { self = [super initWithNibName:nil bundle:nil]; @@ -91,30 +90,46 @@ - (void)start { [self.preview.layer addSublayer:captureVideoPreviewLayer]; self.captureVideoPreviewLayer = captureVideoPreviewLayer; - - _captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; - - NSError *error = nil; - AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:self.captureDevice error:&error]; - - if (!input) { - // Handle the error appropriately. - NSLog(@"ERROR: trying to open camera: %@", error); - return; - } - [self.session addInput:input]; - - self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; - NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; - [self.stillImageOutput setOutputSettings:outputSettings]; - [self.session addOutput:self.stillImageOutput]; } + // init default device + AVCaptureDevice *captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; + [self changeCameraDevice:captureDevice]; + + // output settings + self.stillImageOutput = [[AVCaptureStillImageOutput alloc] init]; + NSDictionary *outputSettings = [[NSDictionary alloc] initWithObjectsAndKeys: AVVideoCodecJPEG, AVVideoCodecKey, nil]; + [self.stillImageOutput setOutputSettings:outputSettings]; + [self.session addOutput:self.stillImageOutput]; + + // run [self.session startRunning]; } -// stop session +- (void)changeCameraDevice:(AVCaptureDevice *)captureDevice { + NSError *error = nil; + AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:&error]; + + if (!input) { + // Handle the error appropriately. + NSLog(@"ERROR: trying to open camera: %@", error); + return; + } + [self.session addInput:input]; + + if(self.delegate) { + if ([self.delegate respondsToSelector:@selector(cameraViewController:didChangeDevice:)]) { + [self.delegate cameraViewController:self didChangeDevice:captureDevice]; + } + } +} + +// stop the camera, otherwise it will lead to memory crashes - (void)stop { + AVCaptureInput* input = [self.session.inputs objectAtIndex:0]; + [self.session removeInput:input]; + AVCaptureVideoDataOutput* output = [self.session.outputs objectAtIndex:0]; + [self.session removeOutput:output]; [self.session stopRunning]; } @@ -168,16 +183,6 @@ -(void)capture { }]; } -- (void)setCaptureDevice:(AVCaptureDevice *)captureDevice { - _captureDevice = captureDevice; - - if(self.delegate) { - if ([self.delegate respondsToSelector:@selector(cameraViewController:didChangeDevice:)]) { - [self.delegate cameraViewController:self didChangeDevice:captureDevice]; - } - } -} - - (BOOL)isFlashAvailable { AVCaptureInput* currentCameraInput = [self.session.inputs objectAtIndex:0]; AVCaptureDeviceInput *deviceInput = (AVCaptureDeviceInput *)currentCameraInput; @@ -208,7 +213,7 @@ -(void)setCameraFlash:(CameraFlash)cameraFlash { [deviceInput.device unlockForConfiguration]; - //Commit all the configuration changes at once + // commit all the configuration changes at once [self.session commitConfiguration]; } @@ -240,36 +245,31 @@ - (void)setCameraPosition:(CameraPosition)cameraPosition return; } - //Indicate that some changes will be made to the session [self.session beginConfiguration]; - //Remove existing input + // remove existing input AVCaptureInput* currentCameraInput = [self.session.inputs objectAtIndex:0]; [self.session removeInput:currentCameraInput]; - //Get new input - AVCaptureDevice *newCamera = nil; + // get the new input + AVCaptureDevice *newCaptureDevice = nil; if(((AVCaptureDeviceInput*)currentCameraInput).device.position == AVCaptureDevicePositionBack) { - newCamera = [self cameraWithPosition:AVCaptureDevicePositionFront]; + newCaptureDevice = [self cameraWithPosition:AVCaptureDevicePositionFront]; } else { - newCamera = [self cameraWithPosition:AVCaptureDevicePositionBack]; + newCaptureDevice = [self cameraWithPosition:AVCaptureDevicePositionBack]; } - if(!newCamera) { + if(!newCaptureDevice) { return; } _cameraPosition = cameraPosition; - // add input to session - AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:newCamera error:nil]; - [self.session addInput:newVideoInput]; + [self changeCameraDevice:newCaptureDevice]; // commit changes [self.session commitConfiguration]; - - self.captureDevice = newCamera; } diff --git a/LLSimpleCameraExample/HomeViewController.m b/LLSimpleCameraExample/HomeViewController.m index b0e5d8b..c1b6697 100644 --- a/LLSimpleCameraExample/HomeViewController.m +++ b/LLSimpleCameraExample/HomeViewController.m @@ -107,8 +107,10 @@ - (void)snapButtonPressed:(UIButton *)button { - (void)cameraViewController:(LLSimpleCamera *)cameraVC didCaptureImage:(UIImage *)image { // we should stop the camera, since we don't need it anymore. We will open a new vc. + // this very important, otherwise you may experience memory crashes [self.camera stop]; + // show the image ImageViewController *imageVC = [[ImageViewController alloc] initWithImage:image]; [self presentViewController:imageVC animated:NO completion:nil]; } From ec7a5d8d55d47d5a04d3fb3d0d6d6d9ca53d09e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=96mer=20Faruk=20G=C3=BCl?= Date: Sun, 4 Jan 2015 11:22:57 +0200 Subject: [PATCH 2/2] Podspec updated --- LLSimpleCamera.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/LLSimpleCamera.podspec b/LLSimpleCamera.podspec index 9afa97a..0be3c60 100644 --- a/LLSimpleCamera.podspec +++ b/LLSimpleCamera.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "LLSimpleCamera" - s.version = "1.0.0" + s.version = "1.1.0" s.summary = "LLSimpleCamera: A simple customizable camera control." s.description = <<-DESC LLSimpleCamera is a library for creating a customized camera screens similar to snapchat's. You don't have to present the camera in a new view controller. @@ -15,7 +15,7 @@ hides the nitty gritty details from the developer s.license = { :type => 'APACHE', :file => 'LICENSE' } s.author = { "Ömer Faruk Gül" => "omer.gul@louvredigital.com" } s.platform = :ios,'7.0' - s.source = { :git => "https://github.com/omergul123/LLSimpleCamera.git", :tag => "v1.0.0" } + s.source = { :git => "https://github.com/omergul123/LLSimpleCamera.git", :tag => "v1.1.0" } s.source_files = 'LLSimpleCamera/*.{h,m}' s.requires_arc = true s.framework = 'AVFoundation'