【问题标题】:For loop appending array in random orderFor循环以随机顺序附加数组
【发布时间】:2017-07-31 11:50:26
【问题描述】:

我目前正在尝试使用 BEMSimpleLineGraph 快速创建历史汇率图表,并使用 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))")
                }
        }

    }
    }
}

控制台:

    []
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。我正在使用多个经过修改的 URL,例如 api.fixer.io/2017-03-01?base=GB。

【问题讨论】:

  • 你想要什么??是否要对数据进行排序
  • 您同时发起一系列 http 请求,不能保证它们会按照它们被触发的顺序完成。
  • 您好,您到底想要实现什么以及您的输出,为什么您认为它是错误的输出。如果您可以发布从 api.fixer.io 生成的 URL,也会很有帮助。
  • 我希望输出按时间顺序排列,所以日期是 1,2,3,4,5,6,7 而不是 2,3,1,3,3,6,7 .我正在使用多个经过修改的 URL,例如 api.fixer.io/2017-03-01?base=GB。正如 mag_zbc 所建议的那样,可能的解释是,但我如何实现这一目标
  • @user8288212 试试我的解决方案,它可以同步 web 服务调用并生成不同的 url

标签: ios arrays swift for-loop bemsimplelinegraph


【解决方案1】:

问题是所有网络请求都是异步的,不能保证它们会按照调用顺序完成。因此,您在数组中的数据不是您调用请求的顺序。

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

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

【讨论】:

    【解决方案2】:
    • 例如创建一个结构体

      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 在循环结束时收到通知。
    • 最后将historicalRatesdate排序。

    【讨论】:

    • 在这种情况下按日期作为字符串排序就足够了。
    • 谢谢,这有帮助!
    猜你喜欢
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 2017-04-19
    • 2014-04-19
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多