How to call a function from another controller in swift

Viewed 3193

I set the Show Charts button on the DetailView Controller which triggers the getChartData function and shows me the values in display view in charts, now I want to call that function in the didselectrow on the main Viewcontroller so that the chart is loaded automatically, but it fails. When I tried to call that function in didselectrow (DVC.getChartsData) I got the error "Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value"

DVC.getChartsData

Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

ViewController:

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {        
        let Storyboard = UIStoryboard(name: "Main", bundle: nil)
        let DVC = Storyboard.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController
        DVC.getDetailName = coin[indexPath.row].name
        let formatedRoundingPrice = (coin[indexPath.row].price as NSString).floatValue * currencymodel.indexValue
        let formatedPrice = String (format: "%.3f", formatedRoundingPrice)
        DVC.getDetailPrice = formatedPrice
        self.navigationController?.pushViewController(DVC, animated: true)
        let percentage = String ((coin[indexPath.row].percent as NSString).floatValue)
        DVC.getDetailPercent = percentage
        tableView.deselectRow(at: indexPath, animated: true)
        //DVC.getChartData()
}

DetailViewController:

    @IBAction func tapLineChart(_ sender: Any) {


       getChartData()


    }

    func getChartData () {

        let chart = HITLineChartView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: displayView.bounds.height))
        displayView.addSubview(chart)
        let max = String((priceResult.max() ?? 0.0).rounded(.up))
        let min = String((priceResult.min() ?? 0.0).rounded(.down))
        let maxChange = abs((listOfChanges.max()) ?? 0.0).rounded(.up)
        let minChange = abs((listOfChanges.min()) ?? 0.0).rounded(.up)
        absMaxPercentage = Int(maxChange > minChange ? maxChange : minChange)
        titles = ["\(getDetailName) closing price is \(getDetailPrice)"]

        print(data)
        chart.draw(absMaxPercentage,
                   values: listOfChanges,
                   label: (max: max, center: "", min: min),
                   dates: namesArray,
                   titles: titles)

        addCloseEvent(chart)

        finalURL = baseURL + "bitcoin" + "/market_chart?vs_currency=usd&days=5"
        print(finalURL)
        getBitcoinData(url: finalURL)

    }

How to load my charts tap on a specific tableview cell instead of tapping on tapLineChart.

https://imgur.com/fg2502P

https://imgur.com/C4AzaRY

https://imgur.com/jOrwujy

2 Answers

if you want to call a function on viewControllerB that you declare from viewController A.

just create the object of the class file you want to use the function from

var obj mainVC = MainViewController()



class MainViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }
    func commonMethod() {
        print("From the main class")
    }
}

Using that object, call the function in another file where you mean to use it

class OtherViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        mainVC.commonMethod()
        // Do any additional setup after loading the view, typically from a nib.
    }
}

Additionally, You can also create a new swift file, name it Global.swift, create all your functions that you want to use throughout the application here. They become "global functions"

You will want to use delegates or observers to pass data between view controllers.

I'm new to tutorials, but I wrote a bit about this here: https://www.eankrenzin.com/swift-blog/pass-data-throughout-your-app-with-observers-and-notifications-xcode-11-amp-swift-5

You should use optional binding to unwrap your VC let DVC = Storyboard.instantiateViewController(withIdentifier: "DetailViewController") as! DetailViewController

Your code is crashing because of that line. Check your interface builder to make sure the identifier is correct. Edit: this line was not causing a crash, but it is still better to use optional binding.The line is: https://imgur.com/CVP1x6H

NOTE: It is terrible practice to litter your app with instances when delegates and observers could work. Also do NOT have globals. Globals are disastrous for debugging and create tech debt.

Related