对于循环以随机顺序附加数组

时间:2017-07-31 11:50:27

标签: ios arrays swift for-loop bemsimplelinegraph

我目前正在尝试使用BEMSimpleLineGraph在swift中创建历史汇率图表,并使用AlomoFire从http://fixer.io/获取数据。我正在使用for循环来循环7天(只是为了看看我是否可以使它正常工作)然后将值附加到(或称为任何名称)数组到一个名为xAxisData的数组

func updateGraphData(timeInterval: Int){
    if selectedCurrency1 != nil && selectedCurrency2 != nil { // checking if both currencies have been selected 
        self.xAxisData.removeAll() // removing some default values

        for i in 1...timeInterval { // don't know exactly if i'm doing this the optimal way?
            print("passed")
            let date = Date()
            let dateComponents = Calendar.current.dateComponents([.month, .day,.year], from: date) //getting the the year(again, just to see if it's working)
            historyURL = "http://api.fixer.io/\(dateComponents.year!.description)-03-0\(String(i))?base=\(selectedCurrency1!.rawValue)" //modifying the url to my needs 


            Alamofire.request(historyURL, method: .get).responseJSON { // requesting data
                response in
                if response.result.isSuccess{
                    let json = JSON(response.result.value!)
                    self.xAxisData.append(json["rates"] [self.selectedCurrency2!.rawValue].doubleValue) // using SwiftyJSON btw to convert, but shouldn't this in theory append in the correct order?
                    print(json["date"].stringValue) // printing out the date


                }
                else{
                    print("Error \(String(describing: response.result.error))")
                }
        }

    }
    }
}

CONSOLE:

    []
2017-03-02
2017-03-03
2017-03-01
2017-03-03
2017-03-03
2017-03-06
2017-03-07
[4.5359999999999996, 4.5316000000000001, 4.4739000000000004, 4.5316000000000001, 4.5316000000000001, 4.5133000000000001, 4.4844999999999997]

我知道我错误地将货币价值变为双倍,因为它可能应该是一个浮动货币。如果需要,请随时提出更多信息,或以任何其他方式纠正我,因为我只是想学习。

我希望输出按时间顺序排列,因此日期为1,2,3,4,5,6,7而不是2,3,1,3,3,6,7。我正在使用多个已修改的网址,例如api.fixer.io/2017-03-01?base=GB。

2 个答案:

答案 0 :(得分:1)

问题是所有网络请求都是异步的,并且无法保证它们将按照调用的顺序完成执行。因此,数组中的数据不是您调用请求的顺序。

您可以使用序列DispatchQueue按照您调用它们的顺序运行请求,但这会使您的程序变慢,因为它一次只执行一个请求而不是运行所有他们并行。

针对此特定问题的更好解决方案是将完成处理程序内部的值插入到某个索引中,而不是仅仅附加它们。这样,即使您不必同步API调用,也可以使订单与API调用的顺序相同。或者,您可以将返回的值存储在字典中,其中键是您发出网络请求的日期的字符串表示形式。

答案 1 :(得分:0)

  • 创建一个结构例如

    struct Rate {
        let currency : String
        let date : Date
        var value : Double
    }
    
  • 创建数组var historicalRates = [Rate]()

  • for循环

    • 使用Calendar API计算日期,您的方式在下个月溢出时遇到麻烦。例如

      let calendar = Calendar.current
      // set the date to noon to avoid daylight saving changes at midnight in a few countries
      let today = calendar.date(bySettingHour: 12, minute: 0, second: 0, of:  Date())!
      
      let formatter = DateFormatter()
      formatter.dateFormat = "yyyy-MM-dd"
      
      for dayOffset in 0...7 {
          let currentDate = calendar.date(byAdding: .day, value: dayOffset, to: today)!
          let currentDateAsString = formatter.string(from: currentDate)
          print(currentDate, currentDateAsString)
      }
      
    • 从当前日期创建Date

    • 创建一个包含实际日期和名称的Rate实例,将其添加到historicalRates并将其传递给异步任务。
  • 在完成块中分配费率value
  • 使用DispatchGroup在循环结束时收到通知。
  • 最后按historicalRates排序date