What is the correct approach to setting and accessing global property across ViewControllers?

时间:2015-06-26 10:10:14

标签: ios swift cocoa-touch

In my model I have built an API class that creates a function for a basic API call to http://openweathermap.org/api that returns a closure with the JSON output as a dictionary.

I then call this function in my first ViewController which successfully returns the output as a string when I run println().

The issue I am having is how to store this output (all basic string types) as a globally accessible variable which I can then pass through a Segue to a custom SearchResultViewController view.

My current approach that isn't working attempts to set an empty string at the start of my FirstViewController, optionally unwrap the output as a string, store in a cityName variable and then pass that through as part of the Segue by overriding the prepareForSegue function.

I would then create the corresponding property cityName in my SearchResultViewController.

I have thoroughly checked naming conventions/linking to custom ViewController classes and want to confirm if I am missing a key step in this approach.

Detailed code below.

FirstViewController:

var cityName = ""

@IBAction func searchButton() {
    let api = API()
    api.weatherSearch(urlSearch: searchField.text!) { dictionary in
        println(dictionary)
        if var cityName = dictionary["name"] as? String {
                println(cityName)
        }
    }
    self.performSegueWithIdentifier("Search", sender: nil)
}

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    if(segue.identifier == "Search") {
        var SearchResult = segue!.destinationViewController as SearchResultViewController;
        SearchResult.cityName = cityName
    }
}

SearchResultViewController:

class SearchResultViewController: UIViewController {

  var cityName: String!

  @IBOutlet weak var Picture: UILabel!

  override func viewDidLoad() {
    super.viewDidLoad()
    println(cityName)
  }
}

2 个答案:

答案 0 :(得分:1)

更改您的searchButton()

@IBAction func searchButton() {
    let api = API()
    api.weatherSearch(urlSearch: searchField.text!) { dictionary in
        println(dictionary)
        if var cityName = dictionary["name"] as? String {
           println(cityName)
           self.performSegueWithIdentifier("Search", sender: nil)
        }
    }   
}

如果这样做,那么你的方法不起作用的原因是网络请求通常是异步的

答案 1 :(得分:0)

There are some logic mismatch here, first you don't need to assign cityName to a empty string in ViewController, you can make it an optional string. Check it with if let closure instead of if var.

var cityName:String?

@IBAction func searchButton() {
    let api = API()
    api.weatherSearch(urlSearch: searchField.text!) { dictionary in
        println(dictionary)
        if let value = dictionary["name"] as? String {
            self.cityName = value
        }
    }
    self.performSegueWithIdentifier("Search", sender: self)
}

override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {

     if(segue.identifier == "Search") {
        var SearchResult = segue!.destinationViewController as SearchResultViewController;
        SearchResult.cityName = cityName
    }
}