Anatolii Rudenko
Anatolii Rudenko

Reputation: 416

delegate method does not get called second time

I am building a simple currency converter app. When ViewController gets opened it calls a function from CoinManager.swift:

class ViewController: UIViewController {
    var coinManager = CoinManager()

        override func viewDidLoad() {
           super.viewDidLoad()
            
            coinManager.delegate = self
            coinManager.getCoinPrice(for: "AUD", "AZN", firstCall: true)
        }
...
}

CoinManager.swift:

protocol CoinManagerDelegate {
    func didUpdatePrice(price1: Double, currency1: String, price2: Double, currency2: String)
    func tellTableView(descriptions: [String], symbols: [String])
    func didFailWithError(error: Error)
}

struct CoinManager {

    var delegate: CoinManagerDelegate?
    let baseURL = "https://www.cbr-xml-daily.ru/daily_json.js"

    func getCoinPrice (for currency1: String,_ currency2: String, firstCall: Bool) {

        if let url = URL(string: baseURL) {

            let session = URLSession(configuration: .default)
            let task = session.dataTask(with: url) { (data, response, error) in
                if error != nil {
                    self.delegate?.didFailWithError(error: error!)
                    return
                }

                if let safeData = data {
                    if let coinData = self.parseJSON(safeData) {
                        
                        if firstCall {
                            var descriptions = [""]
                            let listOfCoins = Array(coinData.keys)
                            
                            for key in listOfCoins {
                                descriptions.append(coinData[key]!.Name)
                            }
                            descriptions.removeFirst()
                            self.delegate?.tellTableView(descriptions: descriptions, symbols: listOfCoins)
                        }

                        if let coinInfo1 = coinData[currency1] {
                            let value1 = coinInfo1.Value
                            if let coinInfo2 = coinData[currency2] {
                                let value2 = coinInfo2.Value

//this line does not do anything the second time I call getCoinPrice: 
                                self.delegate?.didUpdatePrice(price1: value1, currency1: currency1, price2: value2, currency2: currency2) 
//And this one does work
                                print("delegate:\(currency1)") 
                            } else {
                                print("no name matches currency2")
                            }
                        } else {
                            print("no name matches currency1")
                        }
                    }
                }
            }
            task.resume()
        }
    }
func ParseJSON....
}

The method it calls (ViewController.swift):

extension ViewController: CoinManagerDelegate {

    func didUpdatePrice(price1: Double, currency1: String, price2: Double, currency2: String) {
        
        print("didUpdatePrice called")
        
        DispatchQueue.main.async {
            let price1AsString = String(price1)
            let price2AsString = String(price2)
            self.leftTextField.text = price1AsString
            self.rightTextField.text = price2AsString
            self.leftLabel.text = currency1
            self.rightLabel.text = currency2
        }
    }
...
}

and finally, CurrencyViewController.swift:


var coinManager = CoinManager()

   @IBAction func backButtonPressed(_ sender: UIBarButtonItem) {
        dismiss(animated: true, completion: nil)
        coinManager.getCoinPrice(for: "USD", "AZN", firstCall: false)
    }

So when I launch the app i get following in my debug console:

didUpdatePrice called
delegate:AUD

And when I call getCoinPrice() from CurrencyViewController the delegate method does not get called. I know that my code goes through the delegate function line as I get this in debug console:

delegate:USD

I just can't wrap my head around it. The delegate method does not work when gets called second time. Even though it is called by the same algorithm

Upvotes: 2

Views: 830

Answers (2)

Frankenstein
Frankenstein

Reputation: 16361

It's because you're creating a new object of CoinManager in CurrencyViewController where the delegate is not set. So you've to set the delegate every time you create a new instance of CoinManager.

@IBAction func backButtonPressed(_ sender: UIBarButtonItem) {
    dismiss(animated: true, completion: nil)
    coinManager.delegate = self
    coinManager.getCoinPrice(for: "USD", "AZN", firstCall: false)
}

Update: So, the above solution would require for you to make the delegate conformance in CurrencyViewController. If you're looking for an alternate solution you should probably pass the instance of coinManager in ViewController to CurrencyViewController. For that here are the things you need to update.

In CurrencyViewController:

class CurrencyViewController: UIViewController {
    var coinManager: CoinManager! // you can optional unwrap if you intent to use CurrencyViewController without coinManager
    //...

And in ViewController:

currencyViewController.coinManager = coinManager // passing the instance of coinManager

Upvotes: 3

Alexander Nikolaychuk
Alexander Nikolaychuk

Reputation: 664

Can you share the full code of CoinManager? I see this part

if firstCall {
  ...
}

Maybe some block logic here or unhandled cases? And can you share the full code of protocol?

Also try to print something before this code:

if error != nil {
    self.delegate?.didFailWithError(error: error!)
        return
}

Upvotes: 0

Related Questions