Alamofire http json request block ui

前端 未结 2 782
清歌不尽
清歌不尽 2021-01-26 09:50

I\'ve been creating a function which retrieve objects from a JSON script. I\'ve chosen for this to use alamofire for async request and swiftyJSON for easy parsing. However i see

相关标签:
2条回答
  • 2021-01-26 10:18

    The response closure is executed on the main thread. If you are doing your JSON parsing there (and you have a large amount of data) it will block the main thread for a while.

    In that case, you should use dispatch_async for the JSON parsing and only when you are completed update the main thread.

    Just do your parsing like this

    func getRecent() {
    
    var url = "http://URL/recent.php?lastid=\(lastObjectIndex)&limit=\(numberOfRecordsPerAPICall)"
    
    
    isApiCalling = true
    request(.GET, url, parameters: nil)
        .response { (request, response, data, error) in
            if error == nil {
    
        let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
        dispatch_async(dispatch_get_global_queue(priority, 0)) {
    
            // Parse stuff here
    
            let data: AnyObject = data!
            let jsonArray = JSON(data: data as! NSData)
            if jsonArray.count < self.numberOfRecordsPerAPICall {
                self.recentCount = 0
                self.tableVIew.tableFooterView = nil
            } else {
                self.recentCount = jsonArray.count
                self.tableVIew.tableFooterView = self.footerView
            }
            for (key: String, subJson: JSON) in jsonArray {
                // Create an object and parse your JSON one by one to append it to your array
                var httpUrl = subJson["image_url"].stringValue
                let url = NSURL(string: httpUrl)
                let data = NSData(contentsOfURL: url!)
    
                if UIImage(data: data!) != nil {
    
                // Create an object and parse your JSON one by one to append it to your array
                var newNewsObject = News(id: subJson["id"].intValue, title: subJson["title"].stringValue, link: subJson["url"].stringValue, imageLink: UIImage(data: data!)!, summary: subJson["news_text"].stringValue, date: self.getDate(subJson["date"].stringValue))
    
                self.recentArray.append(newNewsObject)
                }
            }
    
            dispatch_async(dispatch_get_main_queue()) {
    
                // Update your UI here
    
                self.lastObjectIndex = self.lastObjectIndex + self.numberOfRecordsPerAPICall
                self.isApiCalling = false
                self.tableVIew.reloadData()
                self.refreshControl?.endRefreshing()
            }
        }
        }
        }
    }
    
    0 讨论(0)
  • 2021-01-26 10:33

    Swift5 An update to Stefan Salatic's answer, if you are parsing a large amount of json data from the Alamofire response it is better you use a global dispatch Queue and if for any reason you need to update the UI in the main thread switch to DispatchQueue.main.async.

    So a sample code will look like this.

    AF.request(UrlGetLayers, method: .post, parameters: parameters, headers: headers)
                .responseJSON { response in
                 DispatchQueue.global(qos: .background).async {
                    
                    //parse your json response here
                    
                    //oops... we need to update the main thread again after parsing json
                    DispatchQueue.main.async {
                        
                    }
                    
                 }
    
            }
            
    
    0 讨论(0)
提交回复
热议问题