Reputation: 938
I have this piece of code in my app:
func saveContact2(contact: String) throws {
let contactStore = CNContactStore()
contactStore.requestAccess(for: .contacts, completionHandler: {(granted, error) in
if granted && error == nil {
//...
} else {
if !granted {
throw contactErrors.contactAccessNotGranted(["Error","Access to Contacts is not granted."])
}
}
})
}
I'd like to throw all errors raising in closure to calling function.
Compiler shows error:
Invalid conversion from throwing function of type '(_, _) throws -> ()' to non-throwing function type '(Bool, Error?) -> Void'
Could anyone help me please with the right syntax?
Upvotes: 1
Views: 248
Reputation: 438487
You cannot throw errors from an @escaping
closure that is called asynchronously. And this makes sense because your app has carried on with its execution and there’s no where to catch the error.
So, instead, adopt completion handler pattern yourself:
func saveContact2(_ contact: String, completion: @escaping: (Result<Bool, Error>) -> Void) {
let contactStore = CNContactStore()
contactStore.requestAccess(for: .contacts) { (granted, error) in
guard granted else {
completion(.failure(error!)
return
}
//...
completion(.success(true))
}
}
And then you’d call it like:
saveContact2(contactName) { result in
switch result {
case .failure:
// handler error here
case .success:
// handle confirmation of success here
}
}
If you’re using an old compiler that doesn’t have the Result
type, it’s basically:
enum Result<Success, Failure> where Failure: Error {
case success(Success)
case failure(Failure)
}
Upvotes: 1