user9883052
user9883052

Reputation: 17

Is there a way to allow an optional to be nil when force unwrapping?

I'm using Yelp's API to get annotations on a map. I have a table view filled of search queries and I'm using a switch statement to decide what to do when one is selected.

case "Dining":
    self.mapView.removeAnnotations(allAnnotations)
    getAnnotations(query: "Restaurant", category: .restaurants, price: .twoDollarSigns)
    handleHideBlurView()
case "Fast Food":
    self.mapView.removeAnnotations(allAnnotations)
    getAnnotations(query: "Fast Food", category: .food, price: nil)
    handleHideBlurView()
case "Desserts":
    self.mapView.removeAnnotations(allAnnotations)
    getAnnotations(query: "Ice Cream", category: .food, price: nil)
    handleHideBlurView()

For the "Dining" cell, I want annotations for fine dining restaurants but Yelp's categories do not provide anything that describes this well enough. To get around this I just searched restaurants but add a price constraint.

The problems occurs when adding the other annotations. For "Fast food" and "Desserts", I don't want there to be a price constraint so I pass nil (the priceTiers parameter can be nil when searching). In order for this to work I had to make price an optional and force unwrap it in the search parameters, causing an error. If I don't make it an optional I can't pass nil.

func getAnnotations(query : String, category : CDYelpBusinessCategoryFilter, price : CDYelpPriceTier?) {
    CDYelpFusionKitManager.shared.apiClient.searchBusinesses(byTerm: query, location: nil, latitude: (self.mapView.userLocation.location?.coordinate.latitude)!, longitude: (self.mapView.userLocation.location?.coordinate.longitude)!, radius: 30000, categories: [category], locale: nil, limit: 30, offset: nil, sortBy: .rating, priceTiers: [price!], openNow: nil, openAt: nil, attributes: nil, completion: { (response) in
        if let response = response {
            let businesses = response.businesses

            //print("There are \(businesses?.count) \(query) businesses")
            for business in businesses! {
                var b : CDYelpBusiness?
                b = business

                let lat = b?.coordinates?.latitude
                let long = b?.coordinates?.longitude
                let phoneNumber = (b?.phone)!

                let annotation = GetAnnotationPins(coordinate: CLLocationCoordinate2D(latitude: lat!, longitude: long!), subtitle: phoneNumber, title: (b?.name)!)

                self.mapView.addAnnotation(annotation)
            }

            self.mapView.fitAll()
        }
    })
}

Is there any way I can force unwrap the optional and expect it to be nil? Or is there a better solution than what I am doing?

Upvotes: 0

Views: 59

Answers (1)

rmaddy
rmaddy

Reputation: 318944

The whole point of "forced unwrapping" is to claim "trust me, I know this can't actually be nil". And if you are wrong, your app crashes.

So you have a problem. If the Yelp API requires a non-nil, non-empty array of prices, but your price is nil, you need to convert the nil price parameter into some default that you can pass to the API call.

I know nothing of the Yelp API but it seems odd that it requires a non-nil, non-empty price array.

If it does allow an empty array, then change:

, priceTiers: [price!],

to:

, priceTiers: price != nil ? [price!] : [],

If it allows an optional array, then change it to:

, priceTiers: price != nil ? [price!] : nil,

If it actually requires a non-nil, non-empty array, then provide a default:

, priceTiers: [price ?? CDYelpPriceTier(someDefault)],

Adjust that last one to correctly create some default price tier.

Upvotes: 2

Related Questions