管理任务来填充UITableView



我正在开发的视图执行以下操作:

  1. 向API发送GET请求以检索用户列表
  2. 向API发送GET请求以从用户列表中检索配置文件图像
  3. 在TableViewCells
  4. 中显示图像

然而,我在管理任务和队列方面遇到了问题。确保在填充表视图之前完成所有请求和任务的最佳方法是什么?

代码如下:

import UIKit
class homeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var tableView: UITableView!
    var jsonData : [NSDictionary] = [NSDictionary]()
    var imageUrls: NSDictionary = NSDictionary()
    var urlsArray: [NSURL] = [NSURL]()
    override func viewDidLoad() {
        super.viewDidLoad()    
        let qualityOfServiceClass = QOS_CLASS_BACKGROUND
        let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
        dispatch_async(backgroundQueue, {
            self.refreshData()
            self.getImage()
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                self.tableView.reloadData()
            })
        })
    }
    override func viewWillAppear(animated: Bool) {
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return jsonData.count
    }
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var type = jsonData[indexPath.row]["type"] as! Int
        for typej in jsonData {
            let t : Int = typej["type"] as! Int
            println("type : (t)")
        }
        if type == 1 {
            let cell1 : cellTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! cellTableViewCell
           /* //If images url are retrieved, load them. Otherwise, load the placeholders
            if self.urlsArray.isEmpty == false {
                println("Tiè: (self.urlsArray[indexPath.row])")
                if let data = NSData(contentsOfURL: self.urlsArray[indexPath.row]) {
                    cell1.profileImg?.image = UIImage(data: data)
                }
            } else {
                cell1.profileImg?.image = UIImage(named: "placeholder.png")
            }*/
            let block: SDWebImageCompletionBlock! = {
                (image: UIImage!, error: NSError!, cacheType: SDImageCacheType, imageURL: NSURL!) -> Void in
                println(self)
            }
            println("url Array: (self.urlsArray)")
            let url = NSURL(string: "http://adall.ga/s/profile-1439584252497.png")
            if UIApplication.sharedApplication().canOpenURL(urlsArray[indexPath.row])   {
                cell1.profileImg.sd_setImageWithURL(urlsArray[indexPath.row], completed: block)
            } else {
                cell1.profileImg.sd_setImageWithURL(url, completed: block)
            }

            cell1.testLbl.text = (self.jsonData[indexPath.row]["author"] as? String)!
            return cell1
        } else {
            let cell2 : cell2TableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell2") as! cell2TableViewCell
            return cell2
        }
    }
    func refreshData()   {
        let requestURL = NSURL(string:"http://adall.ga/api/feeds/author/mat/0")!
        var request = NSMutableURLRequest(URL: requestURL)
        request.HTTPMethod = "GET"
        request.addValue(userToken, forHTTPHeaderField: "tb-token")
        let session = NSURLSession.sharedSession()
        let task = session.dataTaskWithRequest(request) {
            data, response, error in
            println(response)
            var dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
            println(dataString)
            //let jsonResult : NSDictionary = (NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers, error: nil) as? NSDictionary)!
            //jsonData = (NSJSONSerialization.JSONObjectWithData(data!, options:NSJSONReadingOptions.MutableContainers , error: nil) as? NSArray)!
            self.jsonData = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil) as! [NSDictionary]
        }
        task.resume()
        var index: Int
        for index = 0; index < 10000; ++index {
            print("Index: (index), Task state: (task.state)")
        }
    }
    func getImage() {
        var i = 0
        for jsonSingleData in jsonData {
            let author = jsonSingleData["author"] as! String       
            let requestURL2 = NSURL(string: "http://adall.ga/api/users/" + author + "/image")!
            var request2 = NSMutableURLRequest(URL: requestURL2)
            request2.HTTPMethod = "GET"
            request2.addValue(userToken!, forHTTPHeaderField: "tb-token")
            let session2 = NSURLSession.sharedSession()
            let task2 = session2.dataTaskWithRequest(request2) {
                data, response, error in
                println("response= (response)")
                var dataString = NSString(data: data, encoding: NSUTF8StringEncoding)
                println(dataString)
                self.imageUrls = (NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: nil) as! NSDictionary)
                if self.imageUrls["url"] != nil {
                //check if exists
                    let imageUrl = self.imageUrls["url"] as! String
                    let url = NSURL(string: "http://" +  imageUrl)
                    self.urlsArray.append(url!)
                } else {
                    let imageUrl = "http://shackmanlab.org/wp-content/uploads/2013/07/person-placeholder.jpg"
                    let url = NSURL(string: imageUrl)
                    self.urlsArray.append(url!)
                }
            }
            task2.resume()
            self.tableView.reloadData()
        }
    }
    /*
    // MARK: - Navigation
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */
}

问题的关键在于以下代码:

dispatch_async(backgroundQueue, {
    self.refreshData()
    self.getImage()
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.tableView.reloadData()
    })
})

NSURLSession在后台线程中工作,所以当self.getImage()reloadData执行时,jsonData是空的。

你可以在这行之后调用self.getImage()

self.jsonData = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil) as! [NSDictionary]

session.dataTaskWithRequest的已完成块中,调用session2.dataTaskWithRequest的已完成块中的reloadData(在dispatch_get_main_queue上)。

我想这会解决你的问题。

最新更新