Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS Enhance a Weather App with Table Views Upgrading Stormy Cleaning Up Our Code

Brian Patterson
Brian Patterson
19,588 Points

A general question about tableViews and the Weather app.

This is question with regards to an App that I am building in that I have a list of Cities in a TableView and want to pass the data from the cell in TableView to a UIViewController. Now when I pass the data I also want to pass the Latitude and Longitude of those Cities to the UIViewController. Here is the TableViewController code. class MasterTableViewController: UITableViewController {

let fruits = ["London", "Melbourne", "Singapore", "Brazil", "Germany"]
let locations: [[Double]] = [[51.50722, -0.12750],[-37.8136, 144.9631],[-23.5475000,-46.6361100],[49.3297,8.57428],[45.58005,9.27246]]
override func awakeFromNib() {
    super.awakeFromNib()
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


// MARK: - Segues

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showDetail" {
        if let indexPath = self.tableView.indexPathForSelectedRow() {
            let fruit = fruits[indexPath.row]
            let location = locations[indexPath.row]


            (segue.destinationViewController as! ViewController).detailItem = fruit
            (segue.destinationViewController as! ViewController).coordinateItem = location
        }
    }
}

// MARK: - Table View

override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return fruits.count
}
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
    if (indexPath.row == 0){

    }
}

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell

    let fruit = fruits[indexPath.row]
    cell.textLabel!.text = fruit
    return cell
}

override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
    // Return false if you do not want the specified item to be editable.
    return true
}

} The problem I am having is in in the UIViewController. Here is the code. class ViewController: UIViewController {

@IBOutlet weak var currentTemperatureLabel: UILabel?
@IBOutlet weak var currentHumidityLabel: UILabel?
@IBOutlet weak var currentPrecipitationLabel: UILabel?
@IBOutlet weak var currentWeatherIcon: UIImageView?
@IBOutlet weak var currentWeatherSummary: UILabel?
@IBOutlet weak var refreshButton: UIButton?
@IBOutlet weak var activityIndicator: UIActivityIndicatorView?
@IBOutlet weak var detailDescriptionLabel: UILabel?

// Location coordinates
var coordinate: (lat: Double, lon: Double) = (37.8267,-122.423)

// TODO: Enter your API key here
private let forecastAPIKey = "f0d72abfce6f28e736388c289376e0c9"

var coordinateItem: AnyObject? {
    didSet {
        // Update the view.
        self.configureView()
    }
}
var detailItem: AnyObject? {
    didSet {
        // Update the view.
        self.configureView()
    }
}

func configureView() {
    if let detail: AnyObject = self.detailItem {
        if let label = self.detailDescriptionLabel {
        label.text = detail.description
        }
    }
}

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    self.configureView()
    retrieveWeatherForecast()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

func retrieveWeatherForecast() {
    let forecastService = ForecastService(APIKey: forecastAPIKey)
    forecastService.getForecast(coordinate.lat, lon: coordinate.lon) {
        (let currently) in

        if let currentWeather = currently {

            dispatch_async(dispatch_get_main_queue()) {

                if let temperature = currentWeather.temperature {
                    self.currentTemperatureLabel?.text = "\(temperature)ยบ"
                }

                if let humidity = currentWeather.humidity {
                    self.currentHumidityLabel?.text = "\(humidity)%"
                }

                if let precipitation = currentWeather.precipProbability {
                    self.currentPrecipitationLabel?.text = "\(precipitation)%"
                }

                if let icon = currentWeather.icon {
                    self.currentWeatherIcon?.image = icon
                }

                if let summary = currentWeather.summary {
                    self.currentWeatherSummary?.text = summary
                }

                self.toggleRefreshAnimation(false)

            }

        }
    }
}

@IBAction func refreshWeather() {
    toggleRefreshAnimation(true)
    retrieveWeatherForecast()
}

func toggleRefreshAnimation(on: Bool) {
    refreshButton?.hidden = on
    if on {
        activityIndicator?.startAnimating()
    } else {
        activityIndicator?.stopAnimating()
    }
}

} Please can someone help me with this. I have tried StackOverflow and they were not helpful. The advice was read the manual.

1 Answer

Richard Lu
Richard Lu
20,185 Points

In your table view controller, change locations into tuple values instead of arrays. There is a method that automatically gets called when segueing from one view controller to another called prepareForSegue which you used.

I've modified this for you and this should work.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "showDetail" {
        if let vc = segue.destinationViewController as? ViewController {
            vc.coordinates = //place which coordinates you'd like to place in
        }
    }
}

Note

When you access IBOutlets in prepareForSegue, they aren't created yet. You may want to change these two lines

(segue.destinationViewController as! ViewController).detailItem = fruit
(segue.destinationViewController as! ViewController).coordinateItem = location

or your property observers.