-
Notifications
You must be signed in to change notification settings - Fork 12
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
Conversation
@@ -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 { |
There was a problem hiding this comment.
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 was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this 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.
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. |
#1022
Uses async version of
AVCaptureDevice.requestAccess(for:)
.