chrisdhaan / CDYelpFusionKit

An extensive Swift wrapper for the Yelp Fusion API.
MIT License
54 stars 18 forks source link

apiClient.fetchBusiness sometimes returns nil for a business that does exist. #17

Closed Static-Flow closed 4 years ago

Static-Flow commented 4 years ago

What did you do?

I am trying to fetch a business when constructing a VIewController with apiClient.fetchBusiness like so:

YelpAPI.shared.apiClient.fetchBusiness(forId: businessId, locale: .english_unitedStates) { (business) -> Void in
                self.business = business!
                self.businessImage.load(url: business!.imageUrl!)
                self.businessName.text = business!.name
                self.businessAddress.text = business!.location?.addressOne
                self.businessDistance.text = String(format:"%.1f miles", (currentLoc!.distance(from: CLLocation(latitude: business!.coordinates!.latitude!, longitude: business!.coordinates!.longitude!))) * 0.00062137)
                self.businessRating.text = String(format:"%.1f", business!.rating!)
                self.businessImage.layer.cornerRadius = 20
                self.businessImage.clipsToBounds = true
            }

For context this code is eventually called from inside a Google Firestore closure where I am pulling the user's businesses from the cloud and then populating the UI with the details from the YelpApi.

I've checked to make sure the businessId String I pass in is valid so that's not the issue. What's also peculiar is if I put a breakpoint at the fetchBusiness call and the first line of the closure it works. So it's almost like I need to slow it down.

What did you expect to happen?

I expect the CDYelpBusiness object business to be filled and not nil

What happened instead?

Instead the business object is nil and the closure fails

CDYelpFusionKit Environment

CDYelpFusionKit version: 1.5.1 Xcode version: 11 Swift version: 5 Platform(s) running CDYelpFusionKit: ios macOS version running Xcode: 10.15.3

Demo Project

I don't have a public repo code but I can show you the view controller:

import UIKit
import CDYelpFusionKit
import CoreLocation
class MatchViewController: UIViewController {
    var business: CDYelpBusiness?
    @IBOutlet weak var businessImage: UIImageView!
    @IBOutlet weak var businessName: UILabel!
    @IBOutlet weak var businessAddress: UILabel!
    @IBOutlet weak var businessDistance: UILabel!
    @IBOutlet weak var businessRating: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func touchedImage(_ sender: Any) {
        print("touched")
        UIApplication.shared.openURL((business?.url!)!)
    }

    func setBusiness(businessId: String){
        CLLocationManager().requestWhenInUseAuthorization()
        if(CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
            CLLocationManager.authorizationStatus() == .authorizedAlways) {
            let currentLoc = CLLocationManager().location
            YelpAPI.shared.apiClient.fetchBusiness(forId: businessId, locale: .english_unitedStates) { (business) -> Void in
                self.business = business!
                self.businessImage.load(url: business!.imageUrl!)
                self.businessName.text = business!.name
                self.businessAddress.text = business!.location?.addressOne
                self.businessDistance.text = String(format:"%.1f miles", (currentLoc!.distance(from: CLLocation(latitude: business!.coordinates!.latitude!, longitude: business!.coordinates!.longitude!))) * 0.00062137)
                self.businessRating.text = String(format:"%.1f", business!.rating!)
                self.businessImage.layer.cornerRadius = 20
                self.businessImage.clipsToBounds = true
            }
        }

    }

    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

}
Static-Flow commented 4 years ago

My hunch is it has something to do with calling it inside another closure because if I defer the creation of the ViewController until after the Firestore call I don't get any errors. I was wanting to preload them so when the user opens the view there isn't a delay while the Yelp API call finishes.