将部分从JSON文件添加到TableView

时间:2019-01-10 10:12:03

标签: ios swift xcode

大家早上好, 我已经创建了一个使用JSON文件中的数据的TableView。 我可以使用Alamofire将数据放入TableView中,但是为了便于参考,我想按日期对它们进行排序。 因为对于15天以上的每个日期,每个小时都有天气预报。 因此,理想情况下,我希望每天有一个部分可以点击一下打开,并每小时提供一次预测。

这是我的ViewController:

@HystrixProperty

模型:

@HystrixCommand(
  commandProperties = { 
    @HystrixProperty(name = "execution.isolation.strategy", value = "SEMAPHORE"), 
    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "50000")  
}, fallbackMethod = "fallbackActivityCall")
public Optional<ResponseActivityValue> callForActivity() {
 ....
} 

单元格:

import UIKit
import Alamofire
import MapKit

class WeatherProController: UIViewController,  CLLocationManagerDelegate, UITableViewDataSource,UITableViewDelegate  {

private let refreshControl = UIRefreshControl()

var datas = [WeatherProData]()
var locManager = CLLocationManager()
var currentLocation: CLLocation!

var timer = Timer()
var jour = UIColor(red: 0, green: 191 / 255, blue: 1, alpha: 1)
var nuit = UIColor(red: 51 / 255, green: 116 / 255, blue: 255 / 255, alpha: 1)

let didBecomeActiveNotificationName = UIApplication.didBecomeActiveNotification

let identifiantCell = "dataProCell"
let identifiantSegue = "versDetailDonneePro"

@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var menuButton: UIBarButtonItem!
@IBOutlet weak var label: UILabel!
@IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!

override func viewDidLoad() {
    super.viewDidLoad()
    tableView.delegate = self
    tableView.dataSource = self
    locManager.requestAlwaysAuthorization()
    NotificationCenter.default.addObserver(self, selector: #selector(scheduleTimer), name: didBecomeActiveNotificationName, object: nil)
    changeBackground()
    data()

    // Add Refresh Control to Table View
    if #available(iOS 10.0, *) {
        tableView.refreshControl = refreshControl
    } else {
        tableView.addSubview(refreshControl)
    }
    // Configure Refresh Control
    refreshControl.addTarget(self, action: #selector(refreshWeatherData(_:)), for: .valueChanged)
    refreshControl.tintColor = UIColor.white
    let attributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
    refreshControl.attributedTitle = NSAttributedString(string: "Refreshing please wait", attributes: attributes)

}

@objc private func refreshWeatherData(_ sender: Any) {
    fetchWeatherData()
}

private func setupActivityIndicatorView() {
    activityIndicatorView.startAnimating()
}

private func fetchWeatherData() {
    data()
    self.refreshControl.endRefreshing()
  // self.activityIndicatorView.stopAnimating()
}

@objc func scheduleTimer() {
    // schedule the timer
    timer = Timer(fireAt: Calendar.current.nextDate(after: Date(), matching: DateComponents(hour: 6..<21 ~= Date().hour ? 21 : 6), matchingPolicy: .nextTime)!, interval: 0, target: self, selector: #selector(changeBackground), userInfo: nil, repeats: false)
    print(timer.fireDate)
    //        RunLoop.main.add(timer, forMode: .RunLoop.Mode.common)
    print("new background chenge scheduled at:", timer.fireDate.description(with: .current))
}

@objc func changeBackground(){
    // check if day or night shift
    self.view.backgroundColor =  6..<21 ~= Date().hour ? jour : nuit
    // schedule the timer
    scheduleTimer()
}


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return datas.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if let cell = tableView.dequeueReusableCell(withIdentifier: identifiantCell) as? WeatherProCell {
        let data = datas[indexPath.row]
        cell.creerCell(data)
        return cell
    }
    return UITableViewCell()
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if let cell = tableView.cellForRow(at: indexPath) as? WeatherProCell {
        cell.textIsHidden.isHidden = !cell.textIsHidden.isHidden
        cell.textIsHidden1.isHidden = !cell.textIsHidden1.isHidden
        cell.textIsHidden2.isHidden = !cell.textIsHidden2.isHidden
        cell.textIsHidden3.isHidden = !cell.textIsHidden3.isHidden
        cell.textIsHidden4.isHidden = !cell.textIsHidden4.isHidden
        cell.textIsHidden5.isHidden = !cell.textIsHidden5.isHidden
        cell.textIsHidden6.isHidden = !cell.textIsHidden6.isHidden
        cell.textIsHidden7.isHidden = !cell.textIsHidden7.isHidden
        cell.textIsHidden8.isHidden = !cell.textIsHidden8.isHidden
        cell.textIsHidden9.isHidden = !cell.textIsHidden9.isHidden
        cell.cloud.isHidden = !cell.cloud.isHidden
        cell.rTemp.isHidden = !cell.rTemp.isHidden
        cell.cloudBase.isHidden = !cell.cloudBase.isHidden
        cell.dewp.isHidden = !cell.dewp.isHidden
        cell.press.isHidden = !cell.press.isHidden
        cell.pressIcon.isHidden = !cell.pressIcon.isHidden
        cell.hydro.isHidden = !cell.hydro.isHidden
        cell.hydroIcon.isHidden = !cell.hydroIcon.isHidden
        cell.vent.isHidden = !cell.vent.isHidden
        cell.ventIcon.isHidden = !cell.ventIcon.isHidden
        cell.rainIcon.isHidden = !cell.rainIcon.isHidden
        cell.rain.isHidden = !cell.rain.isHidden
        cell.iso0.isHidden = !cell.iso0.isHidden
        cell.freezeRain.isHidden = !cell.freezeRain.isHidden
        cell.noSnow.isHidden = !cell.noSnow.isHidden
        cell.snowUp.isHidden = !cell.snowUp.isHidden
        cell.visibility.isHidden = !cell.visibility.isHidden
        cell.snowProb.isHidden = !cell.snowProb.isHidden

        tableView.beginUpdates()
        tableView.endUpdates()
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

//func numberOfSections(in tableView: UITableView) -> Int {
 //  return datas.count
//}

//func tableView(_ tableView: UITableView, titleForHeaderInSection    section: Int) -> String? {
   // return datas[section].date
//}

func data() {
    if ( CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
        CLLocationManager.authorizationStatus() == .authorizedAlways) {
        currentLocation = locManager.location
    }

    var headers: HTTPHeaders = [
        "Content-Type": "application/json"
    ]

    let user = loginWeatherPro
    let password = motDePasseWeatherPro

    if let authorizationHeader = Request.authorizationHeader(user: user, password: password) {
        headers[authorizationHeader.key] = authorizationHeader.value
    }

    let now = Date()
    let formatter = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
    formatter.calendar = Calendar(identifier: .iso8601)
    formatter.timeZone = TimeZone.init(abbreviation: "UTC")
    formatter.locale = Locale(identifier: "en_US_POSIX")
    print(formatter.string(from: now))
    let days = Calendar.current.date(byAdding: .day, value: 15, to: now)

    let urlB = urlDeBaseWeatherPro
    let locate = "locatedAt=\(currentLocation.coordinate.longitude),\(currentLocation.coordinate.latitude)"
    let period = "&validPeriod=PT0S"
    let validFrom = "&validFrom=\(formatter.string(from: now))"
    let validUntil = "&validUntil=\(formatter.string(from: days!))"
    let fields = "&fields=" + fieldsParameter
    let url = urlB + locate + period + validFrom + validUntil + fields
    print(url)

    Alamofire.request(url, headers:headers).responseJSON{ response in
        if let JSON = response.result.value as? [String: AnyObject] {
            if let forecast = JSON ["forecasts"] as? NSArray {
                for element in forecast {
                    if let dict = element as? [String: AnyObject],
                        let dates = dict ["validFrom"] as? String ,
                        let weatherCode = dict ["weatherCode"] as? Int ,
                        let weatherCodeString = weatherCodesTab[weatherCode],
                        let temp = dict ["airTemperatureInCelsius"] as? Double ,
                        let cloud = dict ["effectiveCloudCoverInPercent"] as? Double ,
                        let rtemp = dict ["feelsLikeTemperatureInCelsius"] as? Double ,
                        let cloudBase = dict ["cloudBaseHeightInMeter"] as? Double ,
                        let dewp = dict ["dewPointTemperatureInCelsius"] as? Double ,
                        let press = dict ["airPressureAtSeaLevelInHectoPascal"] as? Double ,
                        let hydro = dict ["relativeHumidityInPercent"] as? Double ,
                        let vent = dict ["windSpeedInKilometerPerHour"] as? Double ,
                        let rain = dict ["precipitationProbabilityInPercent"] as? Double ,
                        let iso0 = dict ["freezingLevelHeightInMeter"] as? Double ,
                        let freezeRain = dict ["freezingRainProbabilityInPercent"] as? Double ,
                        let noSnow = dict ["noSnowPossibleBelowHeightInMeter"] as? Double ,
                        let snowUp = dict ["snowCertainAboveHeightInMeter"] as? Double ,
                        let visibility = dict ["visibilityInMeter"] as? Double ,
                        let snowProd = dict ["snowfallProbabilityInPercent"] as? Double {


                        self.datas.append(WeatherProData(date: (DateHelper.obtenir.jourDeLaSemaineWeather(dates)!) + " " + DateHelper.obtenir.dateWeatherPro(dates)! + " à " + (DateHelper.obtenir.heures(dates)!), weatherCode: weatherCodeString, temp: temp, cloud: cloud, rtemp: rtemp, cloudBase: cloudBase, dewp: dewp, press: press, hydro: hydro, vent: vent, rain: rain, iso0: iso0, freezeRain: freezeRain, noSnow: noSnow, snowUp: snowUp, visibility: visibility, snowProb: snowProd))

                      //print(weatherCodeString)

                        self.tableView.reloadData()
                    }
                }
            }
        }
    }
}
 }

在此感谢您的帮助,因为我已经为此奋斗了1个月

这是我的GitHub的链接,以获取完整的文件:

https://github.com/superdevil669/MeteoWapi_iOS_App/tree/beta

5 个答案:

答案 0 :(得分:0)

一种方法是修改您的数据模型,该数据模型具有一个保存日期(各部分的值)的数组和一个保存每个日期的天气值数组的字典。 为了简单起见,我已经使用String作为数据类型来“模拟”了这一点。

 library(DBI)
 library(rJava)
 library(RJDBC)

 server <- function(input, output, session){
      con <- dbConnect(drv, url "some url")

      output$table1 <- renderTable({
             my_query = "select * from my_table"
             dbGetQuery(con,my_query)
       })
 }

  ui=shinyUI(fluidPage(
     tableOutput("table1")
  ))

  shinyApp(ui = ui, server = server)

答案 1 :(得分:0)

首先要获取常量的私有后备变量在Swift中很可怕。您只需使用let关键字即可声明常量。

如果您使用struct,甚至可以将WeatherProData减少为

struct WeatherProData { 

    let date: String // must be `Date` for smart grouping
    let weatherCode: String
    let temp: Double
    let cloud: Double
    let rTemp: Double
    let cloudBase: Double
    let dewp: Double
    let press: Double
    let hydro: Double
    let vent: Double
    let rain: Double
    let iso0: Double
    let freezeRain: Double
    let noSnow: Double
    let snowUp: Double
    let visibility: Double
    let snowProb: Double
}

因为您免费获得了init方法

在Swift中将数组分组非常容易。以下建议假定date被声明为Date并将其解码。
Dictionary(grouping:by:根据闭包中的条件将数组分组,在这种情况下,是当前日期的午夜。

let calendar = Calendar.current
let grouped = Dictionary(grouping: datas, by: { calendar.startOfDay(for: $0.date) })
print(grouped)

在Swift 4.2+中,您可以使用否定布尔值

cell.textIsHidden.isHidden.toggle()

还考虑使用Deodable协议来摆脱手动解码。

答案 2 :(得分:0)

我尝试了另一个项目,以免损害我的利益。

import UIKit
import Alamofire

struct WeatherProData {

    let date: String // must be `Date` for smart grouping
//    let weatherCode: String
//    let temp: Double
//    let cloud: Doublea
//    let rTemp: Double
//    let cloudBase: Double
//    let dewp: Double
//    let press: Double
//    let hydro: Double
//    let vent: Double
//    let rain: Double
//    let iso0: Double
//    let freezeRain: Double
//    let noSnow: Double
//    let snowUp: Double
//    let visibility: Double
//    let snowProb: Double
}

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    var data = [WeatherProData]()
    var sections = [Date]()
    var dataT = [Date:[String]]()

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self

        let date = Date()
        let value = "Test"

        if !sections.contains(date) {
            sections.append(date)
            dataT[date] = [String]()
        }

        dataT[date]?.append(value)

        var headers : HTTPHeaders = ["Content-Type":"application.json"]

        //        Ajout lofin et mot de passe pour la connection à weather pro
        let user = loginWeatherPro
        let password = motDePasseWeatherPro

        //        Ajout de l'autorisation de connection
        if let authorizationHeader = Request.authorizationHeader(user: user, password: password) {
            headers[authorizationHeader.key] = authorizationHeader.value
        }

        //        formattage de l'heure
        let now = Date()
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.timeZone = TimeZone.init(abbreviation: "UTC")
        formatter.locale = Locale(identifier: "en_US_POSIX")
        print(formatter.string(from: now))
        let days = Calendar.current.date(byAdding: .day, value: 1, to: now)

        //        preparation de l'url de base
        let urlB = urlDeBaseWeatherPro
        let locate = "locatedAt=3.284752,50.644164"
        let period = "&validPeriod=PT0S"
        let validFrom = "&validFrom=\(formatter.string(from: now))"
        let validUntil = "&validUntil=\(formatter.string(from: days!))"
        let fields = "&fields=" + fieldsParameter
        let url = urlB + locate + period + validFrom + validUntil + fields

        Alamofire.request(url, headers:headers).responseJSON { response in
            if let JSON = response.result.value as? [String: AnyObject] {
                if let forecast = JSON ["forecasts"] as? NSArray {
                    for element in forecast {
                        if let dict = element as? [String: AnyObject],
                            let dates = dict ["validFrom"] as? String {
                            self.data.append(WeatherProData(date: dates))
                            print(dates)
                            self.tableView.reloadData()
                        }
                    }
                }
            }
        }
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return dataT.count
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "test"
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        let datas = data[indexPath.row]
        cell.textLabel?.text = datas.date
        return cell
    }

    override func viewWillAppear(_ animated: Bool) {
        self.tableView.reloadData()
    }
}

我做了最简单的事情,但是我无法对UITableView进行分类,我认为这一定是由于JSON文件将日期发送给我的缘故。

2019-01-14T10:34:04Z
2019-01-14T12:00:00+01:00
2019-01-14T13:00:00+01:00
2019-01-14T14:00:00+01:00
2019-01-14T15:00:00+01:00
2019-01-14T16:00:00+01:00
2019-01-14T17:00:00+01:00
2019-01-14T18:00:00+01:00
2019-01-14T19:00:00+01:00
2019-01-14T20:00:00+01:00
2019-01-14T21:00:00+01:00
2019-01-14T22:00:00+01:00
2019-01-14T23:00:00+01:00
2019-01-15T00:00:00+01:00
2019-01-15T01:00:00+01:00
2019-01-15T02:00:00+01:00
2019-01-15T03:00:00+01:00
2019-01-15T04:00:00+01:00
2019-01-15T05:00:00+01:00
2019-01-15T06:00:00+01:00
2019-01-15T07:00:00+01:00
2019-01-15T08:00:00+01:00
2019-01-15T09:00:00+01:00
2019-01-15T10:00:00+01:00
2019-01-15T11:00:00+01:00

谢谢。谢谢。

答案 3 :(得分:0)

我还在努力。我可以创建我的版块,但是如果没有小时,我将无法显示它们。

我希望每个部分都有当天的标题,并在每天的小时数以下。

import UIKit
import Alamofire

struct WeatherProData {

    let date: String // must be `Date` for smart grouping
//    let weatherCode: String
//    let temp: Double
//    let cloud: Doublea
//    let rTemp: Double
//    let cloudBase: Double
//    let dewp: Double
//    let press: Double
//    let hydro: Double
//    let vent: Double
//    let rain: Double
//    let iso0: Double
//    let freezeRain: Double
//    let noSnow: Double
//    let snowUp: Double
//    let visibility: Double
//    let snowProb: Double
}

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    @objc func refresh(_ sender: Any) {
        // Call webservice here after reload tableview.
        tableView.reloadData()
        refreshControl.endRefreshing()
    }

    var data = [WeatherProData]()
    var sections = [String]()
    var dateSection = [[WeatherProData]]()
    var refreshControl = UIRefreshControl()

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.delegate = self
        tableView.dataSource = self

//        RefrechControl sur UITableVIew
        refreshControl.attributedTitle = NSAttributedString(string: "Tirez pour rafraichir")
        refreshControl.addTarget(self, action: #selector(refresh), for: .valueChanged)
        self.tableView.addSubview(refreshControl)

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")


        var headers : HTTPHeaders = ["Content-Type":"application.json"]

        //        Ajout lofin et mot de passe pour la connection à weather pro
        let user = loginWeatherPro
        let password = motDePasseWeatherPro

        //        Ajout de l'autorisation de connection
        if let authorizationHeader = Request.authorizationHeader(user: user, password: password) {
            headers[authorizationHeader.key] = authorizationHeader.value
        }

        //        formattage de l'heure
        let now = Date()
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
        formatter.calendar = Calendar(identifier: .iso8601)
        formatter.timeZone = TimeZone.init(abbreviation: "UTC")
        formatter.locale = Locale(identifier: "en_US_POSIX")
        print(formatter.string(from: now))
        let days = Calendar.current.date(byAdding: .day, value: 1, to: now)

        let french = DateFormatter()
        french.dateStyle = .full
        french.dateFormat = "dd MMMM"
        french.locale = Locale(identifier: "FR_fr")
        print(french.string(from: now))

        //        preparation de l'url de base
        let urlB = urlDeBaseWeatherPro
        let locate = "locatedAt=3.284752,50.644164"
        let period = "&validPeriod=PT0S"
        let validFrom = "&validFrom=\(formatter.string(from: now))"
        let validUntil = "&validUntil=\(formatter.string(from: days!))"
        let fields = "&fields=" + fieldsParameter
        let url = urlB + locate + period + validFrom + validUntil + fields

        Alamofire.request(url, headers:headers).responseJSON { response in
            if let JSON = response.result.value as? [String: Any] {
                if let forecast = JSON ["forecasts"] as? NSArray {
                    for element in forecast {
                        if let dict = element as? [String: Any],
                            let dates = dict ["validFrom"] as? String {
                            self.data.append(WeatherProData(date: dates))
                            self.sections = Array(Set(self.data.map({ (WeatherProData) -> String in
                                WeatherProData.date
                            })))
                            self.sections.forEach({ (string) in self.dateSection.append([])})
                            for index in 0..<self.sections.count {
                                self.data.forEach({ (data) in
                                    if data.date == self.sections[index] {
                                        self.dateSection[index].append(data)
                                    }
                                })
                            }
                            self.tableView.reloadData()
                        }
                    }
                }
            }
        }
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return sections.count
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return sections[section]
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        for index in 0..<sections.count {
            if index == section {
                return dateSection[index].count
            }
        }
        return 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
//        let datas = data[indexPath.row]
        cell.textLabel?.text = dateSection[indexPath.section] [indexPath.row].date
//        cell.textLabel?.text = datas.date
        self.tableView.addSubview(self.refreshControl)
        return cell

    }
}

这就是我得到的。

My UITableView

答案 4 :(得分:0)

self.sections = Array(Set(self.data.map({ (WeatherProData) -> String in
     WeatherProData.date
})))

,当您拥有-> String时表示该函数正在要求您返回字符串值。因此,您需要在代码中添加带有字符串值的返回值。

这是适合您情况的有效代码:

self.sections = Array(Set(self.data.map({ (WeatherProData) -> String in
     let jsonDateString = WeatherProData.date
     let dateFormatter = DateFormatter()
     dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXX"
     if let weatherProDataDate = dateFormatter.date(from: jsonDateString) {
          return french.string(from: weatherProDataDate)
     } else {
          return ""
     }
})))