简体   繁体   中英

Fetching from CoreData into TableView

I have the following ViewController:

import UIKit    
import CoreData

class DetailedForecastViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var iconViewer: UIImageView!
    @IBOutlet weak var tempLabel: UILabel!
    var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
    var forecastInfo = [String]()
    let appDelegate = UIApplication.shared.delegate as! AppDelegate

    override func viewDidLoad() {
        super.viewDidLoad()

        // Activity Indicator config.
        activityIndicator.center = view.center
        activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.gray
        view.addSubview(activityIndicator)

        getForecastInfo()
    }

    // Downloading forceast Data
    func getForecastInfo() {
        if currentReachabilityStatus == .notReachable {
            errorAlert(title: "", message: "The Internet connection appears to be offline")

            // Fetching Data
            let context = appDelegate.persistentContainer.viewContext
            let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Forecast")
            request.returnsObjectsAsFaults = false
            do {
                let forecastData = try context.fetch(request)
                if forecastData.count > 0 {
                    for data in forecastData as! [NSManagedObject] {
                        if let forecast = data.value(forKey: "forecastDetails") as? String {
                            forecastInfo = [forecast]
            stopAndHideActivityIndicator()

                        }
                    }
                }
            } catch {}
        } // end of reachability

        self.activityIndicator.startAnimating()
        let forecastConstants = ForecastClient(apiKey: ForecastConstants.forecastURL.forecastAPIKey)
        forecastConstants.getForecast(latitude: ForecastConstants.forecastURL.coordinates.latitude, longitude: ForecastConstants.forecastURL.coordinates.longitude) { (currentWeather) in
            if let currentWeather = currentWeather {

                let temperature = currentWeather.temperature
                let humidity = currentWeather.humidity
                let precipProbability = currentWeather.precipProbability
                let precipIntensity = currentWeather.precipIntensity
                let windSpeed = currentWeather.windSpeed
                let windGust = currentWeather.windGust
                let pressure = currentWeather.pressure
                let dewPoint = currentWeather.dewPoint

                if self.forecastInfo.count == 0 {
                    self.forecastInfo = ["Humidity: \(String(humidity!))%", "Precip. Probability: \(String( precipProbability!))%", "Precip. Intensity: \(String(precipIntensity!))%", "Wind Speed: \(String(windSpeed!))mph", "Wind Gust: \(String(windGust!))mph", "Pressure: \(String(pressure!))\"", "Dew Point: \(String(dewPoint!))°"]
                }
                DispatchQueue.main.async {
                    self.tempLabel.text = "\(Int(temperature!))°"

                    // Changing the icon based on the weather conditions
                    let icon = currentWeather.icon

                    switch icon {
                    case "clear-day"?, "clear-night"?:
                        self.iconViewer.image = UIImage(named: "clear")!
                    case "partly-cloudy-day"?, "partly-cloudy-night"?:
                        self.iconViewer.image = UIImage(named: "cloudy")!
                    case "cloudy"?:
                        self.iconViewer.image = UIImage(named: "cloudy")!
                    case "fog"?:
                        self.iconViewer.image = UIImage(named: "fog")!
                    case "rain"?:
                        self.iconViewer.image = UIImage(named: "rain")!
                    case "snow"?, "sleet"?:
                        self.iconViewer.image = UIImage(named: "snow")!
                    default:
                        self.iconViewer.image = UIImage(named: "default")!
                    }
                    self.stopAndHideActivityIndicator()

                    // MARK: Saving data into CoreData
                    let context = self.appDelegate.persistentContainer.viewContext
                    let forecast = NSEntityDescription.insertNewObject(forEntityName: "Forecast", into: context)
                    forecast.setValue("\(self.forecastInfo)", forKey: "forecastDetails")

                    if self.iconViewer.image == nil || self.tempLabel.text == nil {
                        self.iconViewer.image = UIImage(named: "iconNotFound")
                        self.errorAlert(title: "", message: "There seems to be a problem loading the weather icon and/or the temperature, please try again")
                        self.iconViewer.image = UIImage(named: "iconNotFound")
                    }
                    else {
                        let iconData = UIImagePNGRepresentation(self.iconViewer.image!) as NSData?
                        forecast.setValue(iconData, forKey: "weatherIcon")
                    }
                    do {
                        try context.save()
                    } catch {
                        print("Error saving data")
                    }
                }
            } // end of dispatch

        } // end of forecast
    }

    // Stop and hide Activity Indicator func
    func stopAndHideActivityIndicator() {
        activityIndicator.stopAnimating()
        activityIndicator.hidesWhenStopped = true
    }

    // MARK : Populating forceast data into tableView
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if forecastInfo.count == 0 {
            self.errorAlert(title: "", message: "There seems to be a problem downloading the weather forecast, please try again")
        }
        return forecastInfo.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = forecastInfo[indexPath.row]
        return cell
    }
}

It works fine, except for one problem. The data being fetched is not populated on the tableView as it should. It just crams everything with quotes and brackets in one cell instead of listing the items separately. See images: https://imgur.com/a/7v8aL

Any input would be appreciated!

There are 2 places where you are setting forecastInfo array:

Case 1:

// No any problem with this line

if self.forecastInfo.count == 0 {
    self.forecastInfo = ["Humidity: \(String(humidity!))%", "Precip. Probability: \(String( precipProbability!))%", "Precip. Intensity: \(String(precipIntensity!))%", "Wind Speed: \(String(windSpeed!))mph", "Wind Gust: \(String(windGust!))mph", "Pressure: \(String(pressure!))\"", "Dew Point: \(String(dewPoint!))°"]
}

Case 2:

Seems like for loop updating the forcastInfo array each time with data, and cast the obtained string in forecastInfo = [forecast] .

for data in forecastData as! [NSManagedObject] {
    if let forecast = data.value(forKey: "forecastDetails") as? String {
        forecastInfo = [forecast]
        stopAndHideActivityIndicator()
    }
}

Check the forecast value from if let forecast = data.value(forKey: "forecastDetails") as? String if let forecast = data.value(forKey: "forecastDetails") as? String , it should be in array form with different objects of each parameter rather than just one object with all parameter you are showing. it will help you to rectify issue.

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