There are many possible variants of this question, but take as an example the CNAuthorizationStatus
returned by CNContactStore.authorizationStatus(for: .contacts)
, which can be notDetermined
, restricted
, denied
, or authorized
. My goal is to always show the current authorization status in my app's UI.
To expose this to SwiftUI, I might make an ObservableObject
called ModelData
with a contacts
property:
final class ModelData: ObservableObject {
@Published var contacts = Contacts.shared
}
Where contacts
contains my contact-specific model code, including Authorization:
class Contacts {
fileprivate let store = CNContactStore()
static let shared = Contacts()
enum Authorization {
case notDetermined
case restricted
case denied
case authorized
}
var authorization: Authorization {
switch CNContactStore.authorizationStatus(for: .contacts) {
case .notDetermined:
return .notDetermined
case .restricted:
return .restricted
case .denied:
return .denied
case .authorized:
return .authorized
@unknown default:
return .notDetermined
}
}
}
And I might add a method that a button could call to request access:
func requestAccess(handler: @escaping (Bool, Error?) -> Void) {
store.requestAccess(for: .contacts) { (granted, error) in
// TODO: tell SwiftUI views to re-check authorization
DispatchQueue.main.async {
handler(granted, error)
}
}
}
And for the sake of simplicity, say my view is just:
Text(String(describing: modelData.contacts.authorization))
So my questions are:
- Given that
ModelData().contacts.authorization
calls a getter function, not a property, how can I inform the SwiftUI view when I know it's changed (e.g. where the TODO is in therequestAccess()
function)? - Given that the user can toggle the permission in the Settings app (i.e., the value might change out from under me), how can I ensure the view state is always updated? (Do I need to subscribe to an NSNotification and similarly force a refresh? Or is there a better way?)
@Published
with aclass
(especially a singleton that never changes) is probably not going to yield any useful results. What you'll probably want is a@Published
property that stores the result of the last check of the authorization status.contacts
can probably turn into aprivate
property, in fact. – jnpdx.notDetermined > .authorized > .denied
– Tarun Tyagi