简体   繁体   中英

I can't load data from delegate swift

I'm using delegates to pass data collected through JSON to several UIViewControllers .

My setup is like this

I create programaticaly the container for the ContainedViewController inside the MainViewController :

 func createContainer(){
      let controller: UIViewController = (storyboard?.instantiateViewControllerWithIdentifier("containedVC"))! as UIViewController
      controller.view.frame = CGRect(x: 20, y: self.view.frame.height-220, width: self.view.frame.width-40, height: 200)
      view.addSubview(controller.view)
      self.addChildViewController(controller)
}

I call the function after I collect some data with JSON ( and pass them first on the MainViewController ) on another class and pass them to the MainViewController . The code I use for this purpose is:

func setForecast(forecast: Forecast) {
    self.delegateForecast?.loadOnContained(forecast)
    print("did forecast pass to delegate?")
    createContainer()
}

I've also set up a protocol on the MainViewController :

protocol dataForContainedDelegate{
    func loadOnContained(forecast: Forecast)
}

And a variable :

var delegateForecast: dataForContainedDelegate?

My code for the containedVC is:

import UIKit

class ContainedViewController: UIViewController, UIPageViewControllerDataSource, dataForContainedDelegate {

    var forecastService = MainViewController()

    var pageViewController: UIPageViewController!
    var pageDates: NSArray!
    var pageHighTemps: NSArray!
    var pageLowTemps: NSArray!
    var pageDescriptions: NSArray!
    //var pageImages: NSArray!

    func loadOnContained(forecast: Forecast) {
        print("forecast loaded")
        self.pageDates = forecast.dates
        print("dates set")
        self.pageHighTemps = forecast.highTemps
        self.pageLowTemps = forecast.lowTemps
        self.pageDescriptions = forecast.descriptionsArray
        createVCs()
    }
    func createVCs(){
        self.pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as! UIPageViewController
        self.pageViewController.dataSource = self
        let startVC = self.viewControllerAtIndex(0) as ContentViewController
        let viewControllers = NSArray(object: startVC)

        self.pageViewController.setViewControllers(viewControllers as? [UIViewController], direction: .Forward, animated: true, completion: nil)
        self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)

        self.addChildViewController(self.pageViewController)
        self.view.addSubview(self.pageViewController.view)
        self.pageViewController.didMoveToParentViewController(self)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.forecastService.delegateForecast = self
        print("contained load")
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func viewControllerAtIndex(index: Int) -> ContentViewController{

        if(self.pageDates.count == 0) || (index >= self.pageDates.count){  //MARK2: ---ERRON IN THIS LINE "fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)
            return ContentViewController()
        }

        let vc: ContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController

        vc.pageIndex = index
        vc.dateText = self.pageDates[index] as! String
        vc.highTmp = self.pageHighTemps[index] as! String
        vc.lowTmp = self.pageLowTemps[index] as! String
        vc.descText = self.pageDescriptions[index] as! String
        //vc.weatherFile = self.pageImages[index] as! String

        return vc
    }
    func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
        let vc = viewController as! ContentViewController
        var index = vc.pageIndex as Int
        if (index == 0 || index == NSNotFound){
            return nil
        }
        index--
        return self.viewControllerAtIndex(index)
    }

    func pageViewController(pageViewController: UIPageViewController, viewControllerAfterViewController viewController: UIViewController) -> UIViewController? {

        let vc = viewController as! ContentViewController
        var index = vc.pageIndex as Int
        if (index == NSNotFound){
            return nil
        }
        index++
        if (index == self.pageDates.count){
            return nil
        }
        return self.viewControllerAtIndex(index)
    }

    func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int {
        return self.pageDates.count
    }

    func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int {
        return 0
    }
}

When I run the app I get this screen

and on my output window there's nowhere anything about "forecast loaded" or "dates set", but there's "contained load" (which is under viewDidLoad func):

self.weatherService.delegate = self **** at main
from DefaultsSet: Los Angeles
Weather Service class city: Los Angeles
Date: 21 Feb 2016 , High: 20.6 °C , Low: 10.0 °C, Text: Clear
Date: 22 Feb 2016 , High: 28.3 °C , Low: 12.8 °C, Text: Sunny
Date: 23 Feb 2016 , High: 27.8 °C , Low: 12.2 °C, Text: Partly Cloudy
Set Weather main view
did forecast pass to delegate?
contained load

The reason behind this mess

I want when the user press Set City button to be able to select a city and then the data from JSON to be parsed on the MainViewController ( Current Conditions ) and on the PageViewController inside the the containedVC ( Forecast for the following days ).

So my thinking is

  1. User sets city
  2. WeatherService is called and pass all the data to MainViewController
  3. On setWeather func on MainViewController we set the label on MainViewController
  4. On setForecast func on MainViewController we pass data to the containedVC and create the pages dynamically.

but it seems the data never arrive on the containedVC . Any reasons for that?

Furthermore I can load data to containedVC if I make it a WeatherServiceDelegate and on viewDidLoad call setWeather(city: String) but this way I have to set the city again and not automatically load the data on Set City button pressed.

The time at which you call the delegate, actually the delegate was not set(ie delegate is nil).

From my understanding, you just need to pass the data from parent viewController to child for which you could just pass the data through a variable instead of using delegate, as shown below,

func createContainer(){
  let controller: UIViewController = (storyboard?.instantiateViewControllerWithIdentifier("containedVC"))! as UIViewController
  controller.data = forecast // like this
  controller.view.frame = CGRect(x: 20, y: self.view.frame.height-220, width: self.view.frame.width-40, height: 200)
  view.addSubview(controller.view)
  self.addChildViewController(controller)

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM