检索到的值位置(顺序)每次都在swift3中更改

时间:2017-09-07 09:43:09

标签: json swift

我从Json检索了值,每次都打印检索到的值更改顺序(位置已更改)。请检查我的下面代码一次:

override func viewDidLoad() {
  super.viewDidLoad()
  var myIds = [104016, 104010, 104014, 104018, 104000, 104038, 104015, 104011, 104015, 104010, 104010, 104010, 104003, 104003, 104011]

  for arr in 0 ..< myIds.count-1 {
    let url = URL(string: "http://.........\(myIds[arr])")
    print("myIds[\(arr)]:\(myIds[arr])")
    let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
        if error != nil
        {
          print ("ERROR")
        }
        else
        {
          if let content = data
          {
            do
            {
               //Array
               let myJson = try JSONSerialization.jsonObject(with: content, options: JSONSerialization.ReadingOptions.mutableContainers) as AnyObject
               var i = myJson["Job_title_name"]!
               var ist = ""
               // print("i=\(i)")
               ist = String(describing: i!)
               print("myIds[\(arr)]=\(ist)")

            }
            catch
            {

            }
          }
        }
      }
      task.resume()

    }

}

**output:**

 myIds[0]:104016
 myIds[1]:104010
 myIds[2]:104014
 myIds[3]:104018
 myIds[4]:104000
 myIds[5]:104038
 myIds[6]:104015
 myIds[7]:104011
 myIds[8]:104015
 myIds[9]:104010
 myIds[10]:104010
 myIds[11]:104010
 myIds[12]:104003
 myIds[13]:104003
 myIds[0]=WebLogic Admin
 myIds[3]=OracleDevloper
 myIds[2]=Node Js Developer
 myIds[1]=Angular Developer
 myIds[6]=HTML&CSS Developer
 myIds[5]=Senior Manager
 myIds[7]=CRM Developer
 myIds[4]=Windows Manager
 myIds[8]=HTML&CSS Developer
 myIds[9]=Angular Developer
 myIds[11]=Angular Developer
 myIds[10]=Angular Developer
 myIds[12]=java developer
 myIds[13]=java developer

每次停止并运行应用程序时,此输出都会更改。但我无法找到问题。请检查我的代码一次。

必填项:

myIds[0]:104016
myIds[1]:104010
myIds[2]:104014
myIds[3]:104018
myIds[4]:104000
myIds[5]:104038
myIds[6]:104015
myIds[7]:104011
myIds[8]:104015
myIds[9]:104010
myIds[10]:104010
myIds[11]:104010
myIds[12]:104003
myIds[13]:104003
myIds[0]=WebLogic Admin
myIds[1]=Angular Developer
myIds[2]=Node Js Developer
myIds[3]=OracleDevloper
myIds[4]=Windows Manager
myIds[5]=Senior Manager
myIds[6]=HTML&CSS Developer
myIds[7]=CRM Developer
myIds[8]=HTML&CSS Developer
myIds[9]=Angular Developer
myIds[10]=Angular Developer
myIds[11]=Angular Developer
myIds[12]=java developer
myIds[13]=java developer

我想要上面的输出。在上面的代码中是我的错误。

2 个答案:

答案 0 :(得分:1)

网络请求以异步方式运行,因此这是预期的行为。请求不会按照与启动时相同的顺序完成。

如果您需要按顺序运行请求,则可以使用DispatchGroups运行它们,但这会导致性能降低,因为您的异步请求是按顺序而不是并行执行的。更好的解决方案是将结果存储在数据结构中,您可以根据索引之外的唯一标识符来识别对象。对于您当前的问题,最佳解决方案是将结果存储在字典中,其中键是id,值是网络请求中的值。

使用Dictionary存储输出值的并发解决方案:

override func viewDidLoad() {
    super.viewDidLoad()
    var myIds = [104016, 104010, 104014, 104018, 104000, 104038, 104015, 104011, 104015, 104010, 104010, 104010, 104003, 104003, 104011]

    var jobTitles = [Int:String]()
    let group = DispatchGroup()
    for arr in 0 ..< myIds.count-1 {
        let url = URL(string: "http://.........\(myIds[arr])")
        print("myIds[\(arr)]:\(myIds[arr])")
        group.enter()
        let task = URLSession.shared.dataTask(with: url!) { (data, response, error) in
                if error != nil{
                    print ("ERROR")
                } else {
                    if let content = data{
                        do {
                            guard let myJson = try JSONSerialization.jsonObject(with: content, options: []) as? [String:Any] else {return}
                            guard let jobTitle = myJson["Job_title_name"] as? String else {return}
                            jobTitles[myIds[arr]] = jobTitle
                            group.leave()
                        } catch {

                        }
                    }
                }
            }
            task.resume()
        }
    }
}

group.notify(queue: DispatchQueue.main, execute: {
    print(jobTitles)
})

一些一般性建议:不要强制从服务器响应中解包值,也不要使用String(describing:)来创建字符串。使用可选的绑定或默认值来安全地解包选项,如果它们是字符串值,则将值转换为String;或者只使用String(value)表示可以直接初始化字符串的值(例如Int)。

答案 1 :(得分:1)

URLSession.shared.dataTask()通常在并行执行中调用API,因此无论调用请求顺序是否与响应顺序相同。

如果您想以相同的顺序调用请求并获得响应,那么您应该创建NSOperation队列并依赖它。