0

As title. I thought I've got it to work but it only appended 3 items into my array of NSMutableDictionary. I think maybe it's because the performsegue got called before the items are completely appended? How should I fix this problem?

(Also I dont know why but when I print(someDict.count) it gave me 17... it should only be 5 though since there are only 5 businesses)

Here's the code:

var searchBusinessDictionary: [NSMutableDictionary] = []

    func retrieveBusinessFromAPI(id: String){
    let url = URL(string: "https://api.yelp.com/v3/businesses/\(id)")
    var request: URLRequest = URLRequest(url: url!)
    request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
    request.httpMethod = "GET"
    let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
        let businessData = JSON(data)
            var someDict = NSMutableDictionary()
            someDict.setValue(businessData["name"], forKey: "Business Name")
            someDict.setValue(businessData["url"], forKey: "Business Yelp URL")
            someDict.setValue(businessData["image_url"], forKey: "Business image URL")
            someDict.setValue(businessData["hours"][0]["is_open_now"], forKey: "Business Is Open Now")
            someDict.setValue(businessData["price"], forKey: "Business Price")
            someDict.setValue(businessData["rating"], forKey: "Business Rating")
            someDict.setValue(businessData["location"]["display_address"], forKey: "Business Location")
        self.searchBusinessDictionary.append(someDict)
        self.performSegue(withIdentifier: "businessListSegue", sender: self)
    })
    task.resume()
}

Tried dispatching my performsegue to my main thread however I dont think the perform segue is called since my view didn't change

Here's the code for that:

@IBAction func saerch(_ sender: UIButton) {
    self.yelpAPIRequest(completion: {
        OperationQueue.main.addOperation {
            self.performSegue(withIdentifier: "businessListSegue", sender: self)
        }
    })
}

 func yelpAPIRequest(completion: ()->()){
    let coordinate = YLPCoordinate(latitude: self.userLatitude, longitude: self.userLongitude)
    let query = YLPQuery(coordinate: coordinate)
    query.term = "dessert"
    query.limit = 5

    YLPClient.authorize(withAppId: clientId, secret: clientSecret).flatMap { client in
        client.search(withQuery: query)
        }.onSuccess { search in
            if search.businesses.isEmpty == false {
                let topBusiness = search.businesses

                for i in topBusiness{
                    print(i.identifier)
                    self.retrieveBusinessFromAPI(id: i.identifier)
                }

            } else {
                print("No businesses found")
            }
        }.onFailure { error in
            print("Search errored: \(error)")
        }
}
John Doe
  • 185
  • 2
  • 13
  • suggestion: you may want to perform your segue inside the main thread `DispatchQueue.main.async { ...performSegue... }` – mugx Jan 25 '18 at 05:32
  • 1
    Why are you even creating an object with NSMutableDictionary in Swift? – El Tomato Jan 25 '18 at 05:36
  • @AndreaMugnaini thank you for your reply. Can you explain to me the benefit of doing that ? Like what are the differences between doing it in DispatchQueue.main.async{} vs where I have it now? Also the reason why i put the performsegue in there is because if I call it in my button click it seems that performsegue will be called first before all I get all my data from my json call – John Doe Jan 25 '18 at 05:40
  • And even if choose to use `NSMutableDictionary` for some strange reason, do not use `setValue(_:forKey:)`. Use `setObject(_:forKey)`. – rmaddy Jan 25 '18 at 05:40
  • @ElTomato Why not? Or is making an array of Dictionary better? – John Doe Jan 25 '18 at 05:41
  • @rmaddy can I ask why is NSMutableDictionary so frowned upon? and also what're the pros and cons of using setObjects instead of setValue? – John Doe Jan 25 '18 at 05:42
  • @JohnDoe about `DispatchQueue.main.async `, check here: https://stackoverflow.com/questions/40509159/call-performsegue-after-urlsession-shared-datatask – mugx Jan 25 '18 at 05:43
  • @JohnDoe Swift has it's own collections. Use them over the old Objective-C classes. And `setValue` is part of key-value coding. Unless you have a clearly understood need to use key-value coding, avoid `setValue(_:forKey:)` and `value(forKey:)`. – rmaddy Jan 25 '18 at 05:50
  • 1
    @AndreaMugnaini Thanks – John Doe Jan 25 '18 at 05:50
  • @rmaddy thank you for your reply. So instead of using NSMutableDictionary I should go for Dictionary (since I have values that are int and string)? – John Doe Jan 25 '18 at 05:52
  • @JohnDoe Yes. Use `let` and `var` to determine mutability. – rmaddy Jan 25 '18 at 05:53
  • @rmaddy i meant [[String:Any]] – John Doe Jan 25 '18 at 05:54
  • @JohnDoe Same thing with different syntax. – rmaddy Jan 25 '18 at 05:55
  • @AndreaMugnaini I've tried doing that in my button but it doesnt seem like the self.performsegue was called... the view didnt change to my intended view – John Doe Jan 25 '18 at 06:23
  • @JohnDoe you may follow all the received suggestions, stuff about main thread it's just one of them. To be more specific about mine: you Can't update/run UI stuff, expecting a good result, from a background thread, to do that you have to switch on the main thread. Since you are executing a UI operation (perform segue), from a background thread (completion of URLSession), I guess it will be a source of troubles. – mugx Jan 25 '18 at 06:26

0 Answers0