1
\$\begingroup\$

I've recently began trying to put more error handling in to my code so I thought I'd post a use-case to check I'm on the right path. I feel like this is going to make my functions much larger and more indented/nested than before. Is this the right way to go about things or should I be utilising try? instead? Where do people generally put these Error enum definitions?

fileprivate enum LocationError: Error {
 case noAuthorization
 case noBeaconSupport
 case rangingUnavailable
}
class ViewController: UIViewController, CLLocationManagerDelegate {
 @IBOutlet weak var distanceReading: UILabel!
 var locationManager: CLLocationManager!
override func viewDidLoad() {
 super.viewDidLoad()
 locationManager = CLLocationManager()
 locationManager.delegate = self
 locationManager.requestWhenInUseAuthorization()
 view.backgroundColor = UIColor.gray
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
 do {
 guard status == .authorizedWhenInUse else {
 throw LocationError.noAuthorization
 }
 guard CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self) else {
 throw LocationError.noBeaconSupport
 }
 guard CLLocationManager.isRangingAvailable() else {
 throw LocationError.rangingUnavailable
 }
 startScanning()
 }
 catch LocationError.noAuthorization {
 print("User has not authorized us to use location")
 }
 catch LocationError.noBeaconSupport {
 print("User's device does not support Beacons")
 }
 catch LocationError.rangingUnavailable {
 print("User's device does not support ranging")
 }
 catch {
 fatalError()
 }
}
asked Dec 5, 2017 at 20:08
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Throwing Swift errors is a mechanism how a function/method can report a failure to its caller. Your code throws and catches the error within the same method, and I can see no advantage of using try/catch in that situation. Your code is equivalent to

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
 guard status == .authorizedWhenInUse else {
 print("User has not authorized us to use location")
 return
 }
 guard CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self) else {
 print("User has not authorized us to use location")
 return
 }
 guard CLLocationManager.isRangingAvailable() else {
 print("User's device does not support ranging")
 return
 }
 startScanning()
}

which is

  • shorter and easy to understand,
  • makes the enum LocationError obsolete (which is fileprivate, and therefore apparently not used anywhere else),
  • makes the catch-all with fatalError() obsolete.

I would even go a step further: guard is useful in connection with optional binding (to avoid the "optional binding pyramid of doom"). In your case, the same can be achieved with a simple if/else if/.../else statement:

func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
 if status != .authorizedWhenInUse {
 print("User has not authorized us to use location")
 } else if !CLLocationManager.isMonitoringAvailable(for: CLBeaconRegion.self) {
 print("User has not authorized us to use location")
 } else if !CLLocationManager.isRangingAvailable() {
 print("User's device does not support ranging")
 } else {
 startScanning()
 }
}
answered Dec 7, 2017 at 20:03
\$\endgroup\$
2
  • \$\begingroup\$ Thanks. In what case would I want to use Error and try catch? When I do more than just print? \$\endgroup\$ Commented Dec 8, 2017 at 14:15
  • \$\begingroup\$ @Deco: A function throws an Error to report a failure to its caller. You use try/catch when calling functions that throw an Error. \$\endgroup\$ Commented Dec 8, 2017 at 14:22

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.