From 25576899d847a7a20fc1141eea9e16bded99a1c4 Mon Sep 17 00:00:00 2001 From: Cal Moody Date: Tue, 25 Jun 2024 22:27:16 -0400 Subject: [PATCH 1/5] add support for changing which back camera is being used --- iOS/GBViewController.m | 96 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 6 deletions(-) diff --git a/iOS/GBViewController.m b/iOS/GBViewController.m index df4a0a1a5..8030ae9a3 100644 --- a/iOS/GBViewController.m +++ b/iOS/GBViewController.m @@ -52,6 +52,10 @@ @implementation GBViewController NSTimer *_disableCameraTimer; AVCaptureDevicePosition _cameraPosition; UIButton *_cameraPositionButton; + NSArray *_allCaptureDevices; + NSArray *_backCaptureDevices; + AVCaptureDevice *_selectedCaptureDevice; + UIButton *_changeCameraButton; __weak GCController *_lastController; @@ -241,30 +245,82 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( _motionManager = [[CMMotionManager alloc] init]; _cameraPosition = AVCaptureDevicePositionBack; + _selectedCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; + + // Back camera setup + NSArray *deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera, + AVCaptureDeviceTypeBuiltInTelephotoCamera]; + if (@available(iOS 13.0, *)) { + // AVCaptureDeviceTypeBuiltInUltraWideCamera is only available in iOS 13+ + deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera, + AVCaptureDeviceTypeBuiltInUltraWideCamera, + AVCaptureDeviceTypeBuiltInTelephotoCamera]; + } + + // Use a discovery session to gather the capture devices (all back cameras as well as the front camera) + AVCaptureDeviceDiscoverySession *cameraDiscoverySession = [AVCaptureDeviceDiscoverySession + discoverySessionWithDeviceTypes:deviceTypes + mediaType:AVMediaTypeVideo + position:AVCaptureDevicePositionUnspecified]; + _allCaptureDevices = cameraDiscoverySession.devices; + + // Filter only the back cameras into a list used for switching between them + NSMutableArray *filteredBackCameras = [NSMutableArray array]; + for (AVCaptureDevice *device in _allCaptureDevices) { + if ([device position] == AVCaptureDevicePositionBack) { + [filteredBackCameras addObject:device]; + } + } + _backCaptureDevices = filteredBackCameras; + _cameraPositionButton = [[UIButton alloc] initWithFrame:CGRectMake(8, 0, 32, 32)]; + _changeCameraButton = [[UIButton alloc] initWithFrame:CGRectMake(8, + 0, + 32, + 32)]; [self didRotateFromInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation]; if (@available(iOS 13.0, *)) { [_cameraPositionButton setImage:[UIImage systemImageNamed:@"camera.rotate" withConfiguration:[UIImageSymbolConfiguration configurationWithScale:UIImageSymbolScaleLarge]] forState:UIControlStateNormal]; _cameraPositionButton.backgroundColor = [UIColor systemBackgroundColor]; + + [_changeCameraButton setImage:[UIImage systemImageNamed:@"camera" + withConfiguration:[UIImageSymbolConfiguration configurationWithScale:UIImageSymbolScaleLarge]] + forState:UIControlStateNormal]; + _changeCameraButton.backgroundColor = [UIColor systemBackgroundColor]; } else { - UIImage *image = [[UIImage imageNamed:@"CameraRotateTemplate"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - [_cameraPositionButton setImage:image + UIImage *rotateImage = [[UIImage imageNamed:@"CameraRotateTemplate"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + [_cameraPositionButton setImage:rotateImage forState:UIControlStateNormal]; _cameraPositionButton.backgroundColor = [UIColor whiteColor]; + + UIImage *selectCameraImage = [[UIImage imageNamed:@"CameraTemplate"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + [_changeCameraButton setImage:selectCameraImage + forState:UIControlStateNormal]; + _changeCameraButton.backgroundColor = [UIColor whiteColor]; } _cameraPositionButton.layer.cornerRadius = 6; _cameraPositionButton.alpha = 0; [_cameraPositionButton addTarget:self action:@selector(rotateCamera) forControlEvents:UIControlEventTouchUpInside]; + _changeCameraButton.layer.cornerRadius = 6; + _changeCameraButton.alpha = 0; + [_changeCameraButton addTarget:self + action:@selector(changeCamera) + forControlEvents:UIControlEventTouchUpInside]; + [_backgroundView addSubview:_cameraPositionButton]; - + // Only show the select camera button if we have more than one back camera to swap between. + if ([_backCaptureDevices count] > 1) { + [_backgroundView addSubview:_changeCameraButton]; + } + _cameraQueue = dispatch_queue_create("SameBoy Camera Queue", NULL); [UNUserNotificationCenter currentNotificationCenter].delegate = self; @@ -686,6 +742,7 @@ - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceO { UIEdgeInsets insets = self.window.safeAreaInsets; _cameraPositionButton.frame = CGRectMake(insets.left + 8, _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32); + _changeCameraButton.frame = CGRectMake(insets.right - 8, _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32); } - (UIInterfaceOrientationMask)supportedInterfaceOrientations @@ -1123,12 +1180,20 @@ - (void)setRunMode:(GBRunMode)runMode - (AVCaptureDevice *)captureDevice { - NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; - for (AVCaptureDevice *device in devices) { + for (AVCaptureDevice *device in _allCaptureDevices) { if ([device position] == _cameraPosition) { - return device; + // There is only one front camera, return it + if (_cameraPosition == AVCaptureDevicePositionFront) { + return device; + } + + // There may be several back cameras, return the one with the matching type + if ([device deviceType] == [_selectedCaptureDevice deviceType]) { + return device; + } } } + // Return the default camera return [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; } @@ -1292,4 +1357,23 @@ - (void)rotateCamera }); } +- (void)changeCamera +{ + dispatch_async(_cameraQueue, ^{ + // Get index of selected camera and select the next one, wrapping to the beginning + NSUInteger i = [_backCaptureDevices indexOfObject:_selectedCaptureDevice]; + int nextIndex = (i + 1) % _backCaptureDevices.count; + _selectedCaptureDevice = _backCaptureDevices[nextIndex]; + + [_cameraSession stopRunning]; + _cameraSession = nil; + _cameraConnection = nil; + _cameraOutput = nil; + if (_cameraNeedsUpdate) { + _cameraNeedsUpdate = false; + GB_camera_updated(&_gb); + } + }); +} + @end From 5c21c5e985aabe69f1c4af4500febcd3b9560e57 Mon Sep 17 00:00:00 2001 From: Cal Moody Date: Tue, 25 Jun 2024 22:31:47 -0400 Subject: [PATCH 2/5] fix spacing --- iOS/GBViewController.m | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/iOS/GBViewController.m b/iOS/GBViewController.m index 8030ae9a3..74db934e3 100644 --- a/iOS/GBViewController.m +++ b/iOS/GBViewController.m @@ -253,15 +253,15 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( if (@available(iOS 13.0, *)) { // AVCaptureDeviceTypeBuiltInUltraWideCamera is only available in iOS 13+ deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera, - AVCaptureDeviceTypeBuiltInUltraWideCamera, - AVCaptureDeviceTypeBuiltInTelephotoCamera]; + AVCaptureDeviceTypeBuiltInUltraWideCamera, + AVCaptureDeviceTypeBuiltInTelephotoCamera]; } // Use a discovery session to gather the capture devices (all back cameras as well as the front camera) AVCaptureDeviceDiscoverySession *cameraDiscoverySession = [AVCaptureDeviceDiscoverySession - discoverySessionWithDeviceTypes:deviceTypes - mediaType:AVMediaTypeVideo - position:AVCaptureDevicePositionUnspecified]; + discoverySessionWithDeviceTypes:deviceTypes + mediaType:AVMediaTypeVideo + position:AVCaptureDevicePositionUnspecified]; _allCaptureDevices = cameraDiscoverySession.devices; // Filter only the back cameras into a list used for switching between them @@ -301,19 +301,19 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( UIImage *selectCameraImage = [[UIImage imageNamed:@"CameraTemplate"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [_changeCameraButton setImage:selectCameraImage - forState:UIControlStateNormal]; + forState:UIControlStateNormal]; _changeCameraButton.backgroundColor = [UIColor whiteColor]; } _cameraPositionButton.layer.cornerRadius = 6; _cameraPositionButton.alpha = 0; [_cameraPositionButton addTarget:self - action:@selector(rotateCamera) - forControlEvents:UIControlEventTouchUpInside]; + action:@selector(rotateCamera) + forControlEvents:UIControlEventTouchUpInside]; _changeCameraButton.layer.cornerRadius = 6; _changeCameraButton.alpha = 0; [_changeCameraButton addTarget:self - action:@selector(changeCamera) - forControlEvents:UIControlEventTouchUpInside]; + action:@selector(changeCamera) + forControlEvents:UIControlEventTouchUpInside]; [_backgroundView addSubview:_cameraPositionButton]; // Only show the select camera button if we have more than one back camera to swap between. From 66da5fd530985f701e1f5fdccd12572bed768070 Mon Sep 17 00:00:00 2001 From: Cal Moody Date: Wed, 26 Jun 2024 15:02:24 -0400 Subject: [PATCH 3/5] move camera change button into @available check; fix change camera button position --- iOS/GBViewController.m | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/iOS/GBViewController.m b/iOS/GBViewController.m index 74db934e3..725a3eef3 100644 --- a/iOS/GBViewController.m +++ b/iOS/GBViewController.m @@ -277,10 +277,6 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( 0, 32, 32)]; - _changeCameraButton = [[UIButton alloc] initWithFrame:CGRectMake(8, - 0, - 32, - 32)]; [self didRotateFromInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation]; if (@available(iOS 13.0, *)) { [_cameraPositionButton setImage:[UIImage systemImageNamed:@"camera.rotate" @@ -288,38 +284,38 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( forState:UIControlStateNormal]; _cameraPositionButton.backgroundColor = [UIColor systemBackgroundColor]; + // Configure the change camera button + _changeCameraButton = [[UIButton alloc] initWithFrame:CGRectMake(8, + 0, + 32, + 32)]; [_changeCameraButton setImage:[UIImage systemImageNamed:@"camera" withConfiguration:[UIImageSymbolConfiguration configurationWithScale:UIImageSymbolScaleLarge]] forState:UIControlStateNormal]; _changeCameraButton.backgroundColor = [UIColor systemBackgroundColor]; + _changeCameraButton.layer.cornerRadius = 6; + _changeCameraButton.alpha = 0; + [_changeCameraButton addTarget:self + action:@selector(changeCamera) + forControlEvents:UIControlEventTouchUpInside]; + // Only show the change camera button if we have more than one back camera to swap between. + if ([_backCaptureDevices count] > 1) { + [_backgroundView addSubview:_changeCameraButton]; + } } else { UIImage *rotateImage = [[UIImage imageNamed:@"CameraRotateTemplate"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [_cameraPositionButton setImage:rotateImage forState:UIControlStateNormal]; _cameraPositionButton.backgroundColor = [UIColor whiteColor]; - - UIImage *selectCameraImage = [[UIImage imageNamed:@"CameraTemplate"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - [_changeCameraButton setImage:selectCameraImage - forState:UIControlStateNormal]; - _changeCameraButton.backgroundColor = [UIColor whiteColor]; } _cameraPositionButton.layer.cornerRadius = 6; _cameraPositionButton.alpha = 0; [_cameraPositionButton addTarget:self action:@selector(rotateCamera) forControlEvents:UIControlEventTouchUpInside]; - _changeCameraButton.layer.cornerRadius = 6; - _changeCameraButton.alpha = 0; - [_changeCameraButton addTarget:self - action:@selector(changeCamera) - forControlEvents:UIControlEventTouchUpInside]; [_backgroundView addSubview:_cameraPositionButton]; - // Only show the select camera button if we have more than one back camera to swap between. - if ([_backCaptureDevices count] > 1) { - [_backgroundView addSubview:_changeCameraButton]; - } _cameraQueue = dispatch_queue_create("SameBoy Camera Queue", NULL); @@ -742,7 +738,9 @@ - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceO { UIEdgeInsets insets = self.window.safeAreaInsets; _cameraPositionButton.frame = CGRectMake(insets.left + 8, _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32); - _changeCameraButton.frame = CGRectMake(insets.right - 8, _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32); + if (@available(iOS 13.0, *)) { + _changeCameraButton.frame = CGRectMake(_backgroundView.bounds.size.width - 8 - insets.right - 32, _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32); + } } - (UIInterfaceOrientationMask)supportedInterfaceOrientations From 3bf94d281a6ff283a637e38a5faf66d131ac0d06 Mon Sep 17 00:00:00 2001 From: Cal Moody Date: Wed, 26 Jun 2024 19:06:05 -0400 Subject: [PATCH 4/5] fix issues with change camera button --- iOS/GBViewController.m | 61 +++++++++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/iOS/GBViewController.m b/iOS/GBViewController.m index 725a3eef3..3c6926b1f 100644 --- a/iOS/GBViewController.m +++ b/iOS/GBViewController.m @@ -52,10 +52,10 @@ @implementation GBViewController NSTimer *_disableCameraTimer; AVCaptureDevicePosition _cameraPosition; UIButton *_cameraPositionButton; + UIButton *_changeCameraButton; NSArray *_allCaptureDevices; NSArray *_backCaptureDevices; - AVCaptureDevice *_selectedCaptureDevice; - UIButton *_changeCameraButton; + AVCaptureDevice *_selectedBackCaptureDevice; __weak GCController *_lastController; @@ -245,7 +245,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( _motionManager = [[CMMotionManager alloc] init]; _cameraPosition = AVCaptureDevicePositionBack; - _selectedCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; + _selectedBackCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType: AVMediaTypeVideo]; // Back camera setup NSArray *deviceTypes = @[AVCaptureDeviceTypeBuiltInWideAngleCamera, @@ -273,8 +273,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( } _backCaptureDevices = filteredBackCameras; - _cameraPositionButton = [[UIButton alloc] initWithFrame:CGRectMake(8, - 0, + UIEdgeInsets insets = self.window.safeAreaInsets; + _cameraPositionButton = [[UIButton alloc] initWithFrame:CGRectMake(insets.left + 8, + _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32)]; [self didRotateFromInterfaceOrientation:[UIApplication sharedApplication].statusBarOrientation]; @@ -284,20 +285,20 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( forState:UIControlStateNormal]; _cameraPositionButton.backgroundColor = [UIColor systemBackgroundColor]; - // Configure the change camera button - _changeCameraButton = [[UIButton alloc] initWithFrame:CGRectMake(8, - 0, + // Configure the change camera button stacked on top of the camera position button + _changeCameraButton = [[UIButton alloc] initWithFrame:CGRectMake(insets.left + 8, + _backgroundView.bounds.size.height - 8 - insets.bottom - 32 - 32 - 8, 32, 32)]; - [_changeCameraButton setImage:[UIImage systemImageNamed:@"camera" + [_changeCameraButton setImage:[UIImage systemImageNamed:@"camera.aperture" withConfiguration:[UIImageSymbolConfiguration configurationWithScale:UIImageSymbolScaleLarge]] forState:UIControlStateNormal]; _changeCameraButton.backgroundColor = [UIColor systemBackgroundColor]; _changeCameraButton.layer.cornerRadius = 6; _changeCameraButton.alpha = 0; [_changeCameraButton addTarget:self - action:@selector(changeCamera) - forControlEvents:UIControlEventTouchUpInside]; + action:@selector(changeCamera) + forControlEvents:UIControlEventTouchUpInside]; // Only show the change camera button if we have more than one back camera to swap between. if ([_backCaptureDevices count] > 1) { [_backgroundView addSubview:_changeCameraButton]; @@ -309,11 +310,12 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( forState:UIControlStateNormal]; _cameraPositionButton.backgroundColor = [UIColor whiteColor]; } + _cameraPositionButton.layer.cornerRadius = 6; _cameraPositionButton.alpha = 0; [_cameraPositionButton addTarget:self - action:@selector(rotateCamera) - forControlEvents:UIControlEventTouchUpInside]; + action:@selector(rotateCamera) + forControlEvents:UIControlEventTouchUpInside]; [_backgroundView addSubview:_cameraPositionButton]; @@ -737,9 +739,15 @@ - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)orientation dur - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { UIEdgeInsets insets = self.window.safeAreaInsets; - _cameraPositionButton.frame = CGRectMake(insets.left + 8, _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32); - if (@available(iOS 13.0, *)) { - _changeCameraButton.frame = CGRectMake(_backgroundView.bounds.size.width - 8 - insets.right - 32, _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32); + _cameraPositionButton.frame = CGRectMake(insets.left + 8, + _backgroundView.bounds.size.height - 8 - insets.bottom - 32, + 32, + 32); + if (_changeCameraButton != nil) { + _changeCameraButton.frame = CGRectMake(insets.left + 8, + _backgroundView.bounds.size.height - 8 - insets.bottom - 32 - 32 - 8, + 32, + 32); } } @@ -1186,7 +1194,7 @@ - (AVCaptureDevice *)captureDevice } // There may be several back cameras, return the one with the matching type - if ([device deviceType] == [_selectedCaptureDevice deviceType]) { + if ([device deviceType] == [_selectedBackCaptureDevice deviceType]) { return device; } } @@ -1242,6 +1250,14 @@ - (void)cameraRequestUpdate _cameraPositionButton.alpha = 1; }]; } + if (_changeCameraButton != nil) { + // The change camera button is only available when we are using a capture device on the back of the device + int changeCameraButtonAlpha = (_cameraPosition == AVCaptureDevicePositionFront) ? 0 : 1; + [UIView animateWithDuration:0.25 animations:^{ + _changeCameraButton.alpha = changeCameraButtonAlpha; + }]; + } + _disableCameraTimer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:false block:^(NSTimer *timer) { @@ -1250,6 +1266,13 @@ - (void)cameraRequestUpdate _cameraPositionButton.alpha = 0; }]; } + if (_changeCameraButton != nil) { + if (_changeCameraButton.alpha) { + [UIView animateWithDuration:0.25 animations:^{ + _changeCameraButton.alpha = 0; + }]; + } + } dispatch_async(_cameraQueue, ^{ [_cameraSession stopRunning]; _cameraSession = nil; @@ -1359,9 +1382,9 @@ - (void)changeCamera { dispatch_async(_cameraQueue, ^{ // Get index of selected camera and select the next one, wrapping to the beginning - NSUInteger i = [_backCaptureDevices indexOfObject:_selectedCaptureDevice]; + NSUInteger i = [_backCaptureDevices indexOfObject:_selectedBackCaptureDevice]; int nextIndex = (i + 1) % _backCaptureDevices.count; - _selectedCaptureDevice = _backCaptureDevices[nextIndex]; + _selectedBackCaptureDevice = _backCaptureDevices[nextIndex]; [_cameraSession stopRunning]; _cameraSession = nil; From d42aad2b8487d92b424e0f12712ed10c2c28a88e Mon Sep 17 00:00:00 2001 From: Lior Halphon Date: Fri, 28 Jun 2024 16:54:20 +0300 Subject: [PATCH 5/5] Minor stylistic changes --- iOS/GBViewController.m | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/iOS/GBViewController.m b/iOS/GBViewController.m index 3c6926b1f..5100eea43 100644 --- a/iOS/GBViewController.m +++ b/iOS/GBViewController.m @@ -258,10 +258,9 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( } // Use a discovery session to gather the capture devices (all back cameras as well as the front camera) - AVCaptureDeviceDiscoverySession *cameraDiscoverySession = [AVCaptureDeviceDiscoverySession - discoverySessionWithDeviceTypes:deviceTypes - mediaType:AVMediaTypeVideo - position:AVCaptureDevicePositionUnspecified]; + AVCaptureDeviceDiscoverySession *cameraDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceTypes + mediaType:AVMediaTypeVideo + position:AVCaptureDevicePositionUnspecified]; _allCaptureDevices = cameraDiscoverySession.devices; // Filter only the back cameras into a list used for switching between them @@ -306,8 +305,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( } else { UIImage *rotateImage = [[UIImage imageNamed:@"CameraRotateTemplate"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - [_cameraPositionButton setImage:rotateImage - forState:UIControlStateNormal]; + [_cameraPositionButton setImage:rotateImage + forState:UIControlStateNormal]; _cameraPositionButton.backgroundColor = [UIColor whiteColor]; } @@ -743,7 +742,7 @@ - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceO _backgroundView.bounds.size.height - 8 - insets.bottom - 32, 32, 32); - if (_changeCameraButton != nil) { + if (_changeCameraButton) { _changeCameraButton.frame = CGRectMake(insets.left + 8, _backgroundView.bounds.size.height - 8 - insets.bottom - 32 - 32 - 8, 32, @@ -1250,12 +1249,14 @@ - (void)cameraRequestUpdate _cameraPositionButton.alpha = 1; }]; } - if (_changeCameraButton != nil) { + if (_changeCameraButton) { // The change camera button is only available when we are using a capture device on the back of the device - int changeCameraButtonAlpha = (_cameraPosition == AVCaptureDevicePositionFront) ? 0 : 1; - [UIView animateWithDuration:0.25 animations:^{ - _changeCameraButton.alpha = changeCameraButtonAlpha; - }]; + double changeCameraButtonAlpha = (_cameraPosition == AVCaptureDevicePositionFront) ? 0 : 1; + if (changeCameraButtonAlpha != _changeCameraButton.alpha) { + [UIView animateWithDuration:0.25 animations:^{ + _changeCameraButton.alpha = changeCameraButtonAlpha; + }]; + } } _disableCameraTimer = [NSTimer scheduledTimerWithTimeInterval:1 @@ -1266,12 +1267,10 @@ - (void)cameraRequestUpdate _cameraPositionButton.alpha = 0; }]; } - if (_changeCameraButton != nil) { - if (_changeCameraButton.alpha) { - [UIView animateWithDuration:0.25 animations:^{ - _changeCameraButton.alpha = 0; - }]; - } + if (_changeCameraButton.alpha) { + [UIView animateWithDuration:0.25 animations:^{ + _changeCameraButton.alpha = 0; + }]; } dispatch_async(_cameraQueue, ^{ [_cameraSession stopRunning];