Skip to content

Commit 299e616

Browse files
authored
[camera_avfoundation] dealloc camera on dispose (flutter#7211)
When is camera disposed in `disposeCamera` it calls `close` and leaves `_camera` untouched so after another call to `sessionQueueCreateCameraWithName` it calls `close` second time and only here is `_camera` disposed by assigning new value into that variable. Calling `close` 2x may be unexpected and prone to later errors if someone adds here something which expects that it will be called only once. Also having dangling `_camera` after dispose (without creating new one) can have other unintended consequences although maybe benign for now. For example there is `[_motionManager stopAccelerometerUpdates]` which is called only in `dealloc`.
1 parent dfcc578 commit 299e616

File tree

4 files changed

+44
-1
lines changed

4 files changed

+44
-1
lines changed

packages/camera/camera_avfoundation/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.9.17+3
2+
3+
* Fixes deallocation of camera on dispose.
4+
15
## 0.9.17+2
26

37
* Fixes stopVideoRecording waiting indefinitely and lag at start of video.

packages/camera/camera_avfoundation/example/ios/RunnerTests/CameraMethodChannelTests.m

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,42 @@ - (void)testCreate_ShouldCallResultOnMainThread {
5050
XCTAssertNotNil(resultValue);
5151
}
5252

53+
- (void)testDisposeShouldDeallocCamera {
54+
CameraPlugin *camera = [[CameraPlugin alloc] initWithRegistry:nil messenger:nil];
55+
56+
id avCaptureDeviceInputMock = OCMClassMock([AVCaptureDeviceInput class]);
57+
OCMStub([avCaptureDeviceInputMock deviceInputWithDevice:[OCMArg any] error:[OCMArg anyObjectRef]])
58+
.andReturn([AVCaptureInput alloc]);
59+
60+
id avCaptureSessionMock = OCMClassMock([AVCaptureSession class]);
61+
OCMStub([avCaptureSessionMock alloc]).andReturn(avCaptureSessionMock);
62+
OCMStub([avCaptureSessionMock canSetSessionPreset:[OCMArg any]]).andReturn(YES);
63+
64+
XCTestExpectation *createExpectation =
65+
[self expectationWithDescription:@"create's result block must be called"];
66+
[camera createCameraOnSessionQueueWithName:@"acamera"
67+
settings:[FCPPlatformMediaSettings
68+
makeWithResolutionPreset:
69+
FCPPlatformResolutionPresetMedium
70+
framesPerSecond:nil
71+
videoBitrate:nil
72+
audioBitrate:nil
73+
enableAudio:YES]
74+
completion:^(NSNumber *_Nullable result,
75+
FlutterError *_Nullable error) {
76+
[createExpectation fulfill];
77+
}];
78+
[self waitForExpectationsWithTimeout:30 handler:nil];
79+
XCTAssertNotNil(camera.camera);
80+
81+
XCTestExpectation *disposeExpectation =
82+
[self expectationWithDescription:@"dispose's result block must be called"];
83+
[camera disposeCamera:0
84+
completion:^(FlutterError *_Nullable error) {
85+
[disposeExpectation fulfill];
86+
}];
87+
[self waitForExpectationsWithTimeout:30 handler:nil];
88+
XCTAssertNil(camera.camera, @"camera should be deallocated after dispose");
89+
}
90+
5391
@end

packages/camera/camera_avfoundation/ios/camera_avfoundation/Sources/camera_avfoundation/CameraPlugin.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ - (void)disposeCamera:(NSInteger)cameraId
416416
__weak typeof(self) weakSelf = self;
417417
dispatch_async(self.captureSessionQueue, ^{
418418
[weakSelf.camera close];
419+
weakSelf.camera = nil;
419420
completion(nil);
420421
});
421422
}

packages/camera/camera_avfoundation/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: camera_avfoundation
22
description: iOS implementation of the camera plugin.
33
repository: https://github.com/flutter/packages/tree/main/packages/camera/camera_avfoundation
44
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+camera%22
5-
version: 0.9.17+2
5+
version: 0.9.17+3
66

77
environment:
88
sdk: ^3.2.3

0 commit comments

Comments
 (0)