Skip to content

Mhd/camera requester crash #1023

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 20, 2025
Merged

Mhd/camera requester crash #1023

merged 3 commits into from
Feb 20, 2025

Conversation

mhdostal
Copy link
Member

#1022

Uses async version of AVCaptureDevice.requestAccess(for:).

@mhdostal mhdostal requested a review from dfeinzimer January 21, 2025 17:08
@mhdostal mhdostal changed the base branch from main to v.next January 21, 2025 17:37
@mhdostal mhdostal requested a review from rolson January 21, 2025 22:07
@mhdostal mhdostal requested a review from dfeinzimer January 22, 2025 18:46
@@ -23,18 +23,17 @@ import SwiftUI

var onAccessDenied: (() -> Void)?

func request(onAccessGranted: @escaping () -> Void, onAccessDenied: @escaping () -> Void) {
func request(onAccessGranted: @escaping () -> Void, onAccessDenied: @escaping () -> Void) async {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused as to why this method is taking 2 closures. Since it's asynchronous can we not just return a boolean for isAuthorized?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused as to why this method is taking 2 closures. Since it's asynchronous can we not just return a boolean for isAuthorized?

There are code paths in the AVCaptureDevice.authorizationStatus switch that do not specifically set isAuthorized. That's why it can't simply return a boolean.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing to consider is that isAuthorized is not a return value but a published property:

@Published private(set) var isAuthorized = false

I think that might simplify code looking at where the closures are used?

Copy link
Collaborator

@dfeinzimer dfeinzimer Feb 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I investigated using the proposed published isAuthorized property. At face value it does seem like we could potentially simplify this:

await cameraRequester.request {
    cameraAccessIsAuthorized = true
} onAccessDenied: {
    isPresented = false
}

to this:

await cameraRequester.request()
if cameraRequester.isAuthorized {
    cameraAccessIsAuthorized = true
} else {
    isPresented = false
}

but as Mark noted there is a third possibility we have to account for (when we get AVAuthorizationStatus.denied or AVAuthorizationStatus.restricted back) and CameraRequester needs to remain presented in order to present this alert:

The current callback structure makes it simple to keep CameraRequester presented so that the user can respond to this alert.

With this, my recommendation would be to keep the PR as is.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So maybe an isPublished Bool is not enough, but an enum might be?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An enum could work yes, but if we use AVAuthorizationStatus directly then the CameraRequester user has four possible outcomes to handle, rather than the current two.

Alternatively, we could use the proposed boolean property (or create our own simplified enumeration) and just set it false or denied once the user has pressed Cancel but this mean the developer now also needs to install a .task(id: cameraRequester.isAuthorized) { ... } elsewhere to monitor the value, scattering permission handling logic into more locations.

Copy link
Collaborator

@rolson rolson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. I feel like the closure api is a bit of a strange metaphor for SwiftUI in this case, but maybe I'm just not understanding the nuances here.

@dfeinzimer
Copy link
Collaborator

Approving. I feel like the closure api is a bit of a strange metaphor for SwiftUI in this case, but maybe I'm just not understanding the nuances here.

Agreed, I think the strangeness is rooted in the fact that the class has an async method and it's used in conjunction with a view modifier that may or may not ever need to present an alert. The good news is that this is all internal so I've opened #1077 so we can revisit this later on.

@mhdostal mhdostal merged commit 37a932e into v.next Feb 20, 2025
@mhdostal mhdostal deleted the mhd/CameraRequesterCrash branch February 20, 2025 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Feature Form: Barcode scanning crashes in Swift 6 language mode
3 participants