Swift中如何解决‘() throws -> Bool无法转换为Bool’报错?
Hey there! I know how frustrating it is to get stuck on a syntax snag when you're just starting out with Swift—let's break this down and get your code working.
What's Causing the Error?
The core issue here is a type mismatch. Your ThrowableCallBack defines a closure that throws an error and returns a Bool, but it looks like the authenticated parameter in services.login is expecting either a plain Bool value or a closure that accepts a Bool (not one that returns a throwing Bool). The compiler is yelling because it can't convert your throwing closure to the type the method is asking for.
Step-by-Step Fixes
1. Adjust the Closure to Match the Expected Type
First, let's assume your login method's authenticated parameter is meant to handle a success/failure boolean result. Here's how to rewrite your authenticate() function correctly, with safer practices:
// Update the callback type to match what login expects typealias AuthCallback = (Bool) -> Void func authenticate() { let services = ServiceManager() // Safely unwrap text fields to avoid crashes (no more force ! unwraps!) guard let email = emailField.text, !email.isEmpty, let password = passwordField.text, !password.isEmpty else { let alert = UIAlertController(title: "Oops", message: "Please fill in both email and password.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) return } services.login(username: email, password: password, authenticated: { authResult in self.loadingDialog.dismiss(animated: true) if authResult { // Handle successful authentication (e.g., navigate to home screen) self.navigationController?.pushViewController(HomeViewController(), animated: true) } else { // Handle failed login let alert = UIAlertController(title: "Login Failed", message: "Invalid email or password.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Try Again", style: .default)) self.present(alert, animated: true) } }) }
2. If You Need to Handle Errors in the Callback
If you do need the callback to handle errors (not just a success/failure flag), you'll need to adjust both the callback type and how you use it with do/catch:
First, update the callback type and your login method (if you control it) to support throwing closures:
typealias ThrowableAuthCallback = (Bool) throws -> Void // Inside ServiceManager, update the login method signature: func login(username: String, password: String, authenticated: ThrowableAuthCallback) throws { // Perform your network request and check the response code... let isAuthenticated = true // Replace with actual response logic // Call the callback (which might throw an error) try authenticated(isAuthenticated) }
Then update your authenticate() function to catch any thrown errors:
func authenticate() { let services = ServiceManager() guard let email = emailField.text, !email.isEmpty, let password = passwordField.text, !password.isEmpty else { let alert = UIAlertController(title: "Oops", message: "Please fill in both email and password.", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) present(alert, animated: true) return } do { try services.login(username: email, password: password, authenticated: { authResult in self.loadingDialog.dismiss(animated: true) if authResult { // Success case: navigate to home self.navigationController?.pushViewController(HomeViewController(), animated: true) } else { // Throw an error for failed authentication throw LoginError.invalidCredentials } }) } catch { // Handle any thrown errors self.loadingDialog.dismiss(animated: true) let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) self.present(alert, animated: true) } } // Custom error type for login-specific issues enum LoginError: Error, LocalizedError { case invalidCredentials var localizedDescription: String { switch self { case .invalidCredentials: return "Invalid email or password. Please try again." } } }
Quick Tips for Swift Newbies
- Ditch force unwraps (
!) whenever you can—useguard letorif letto safely handle optional values and avoid unexpected crashes. - Closure types are strict: Always make sure the closure you pass matches exactly what the function expects (parameters, return type, and whether it throws).
- Use
do/catchfor thrown errors: Any time you call a function or closure markedthrows, wrap it in adoblock and catch errors in thecatchblock.
内容的提问来源于stack exchange,提问作者João Serra

