0

I have a method, which parses JSON for me and then in closure loads and saves images to disk. This method is being called in viewDidLoad. Then loads table. The problem is that when table loads it has only one cell inside it, because the it is not enough time for dataTaskWithRequest to download all the info when table is loaded. So it loads up with one cell and then if I press a button which linked to function tableView.reloadData() then other cell appear.

How to make tableView to wait for dataTaskWithRequest and showup it self only when fetch from internet is finished ?

Here how method that I call in viewDidLoad looks like

var JSONStorage : [Article?]?
var objects = [Article?]()
var imgPath : String?

var battlesArticlesListImgPath : String?
var battleArticlesListHash : String?
var battleArticlesListArray = [ArticlesList?]()

@IBOutlet weak var tableView: UITableView!

@IBAction func button(sender: AnyObject) {

    print(battleArticlesListArray)
    print(battleArticlesListHash)
    dump(battleArticlesListArray)
    self.tableView.reloadData()

}

override func viewDidLoad() {
    super.viewDidLoad()

    downloadBattlesArticlesList()

func downloadBattlesArticlesList() {

    let number = arc4random_uniform(1000)
    let urlString = "http://78.27.190.58:3200/api/category_listing/0/0/?\(number)"


    if let url = NSURL(string: urlString) {
        if let data = try? NSData(contentsOfURL: url, options: []) {
            var json = JSON(data: data)

            self.battleArticlesListHash = json["content_version"].stringValue

            let UserDefaults = NSUserDefaults.standardUserDefaults()
            UserDefaults.setValue(self.battleArticlesListHash, forKey: "battleArticlesListHash")

            print("preved")

            for element in json["listing"].arrayValue {

                let id = Int(element["id"].stringValue)
                let title = element["title"].stringValue
                let subtitle = element["subtitle"].stringValue
                let img = element["image"].stringValue

                let url = NSURL(string: img)
                let urlRequest = NSURLRequest(URL: url!)
                let task = NSURLSession.sharedSession().dataTaskWithRequest(urlRequest, completionHandler: {

                    (data, response, error) -> Void in

                    let image = UIImage(data: data!)

                    var documentsDirectory:String?

                    var paths:[AnyObject] = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)

                    if paths.count > 0 {

                        documentsDirectory = paths[0] as? String

                        var savePath = documentsDirectory! + "/\(self.randomStringWithLength(5)).jpg"

                        self.battlesArticlesListImgPath = savePath

                        NSFileManager.defaultManager().createFileAtPath(savePath, contents: data, attributes: nil)

                        let obj:ArticlesList = ArticlesList(id: id!, title: title, subtitle: subtitle, image: self.battlesArticlesListImgPath!)

                        self.battleArticlesListArray.append(obj)

                    }
                })

            task.resume()

            }

        }
    }

    print(battleArticlesListArray)
}

Final print is also shows empty array when executed.

MSU_Bulldog
  • 3,501
  • 5
  • 37
  • 73
Alexey K
  • 6,537
  • 18
  • 60
  • 118
  • Check out my answer here http://stackoverflow.com/questions/31279369/capturing-closure-values-in-swift/31279784#31279784 it can help you – Victor Sigler Oct 14 '15 at 15:35

1 Answers1

0

In your viewDidLoad, hide your tableView:

tableView.hidden = true

Just call tableView.reloadData() after here

     if paths.count > 0 {

                            documentsDirectory = paths[0] as? String

                            var savePath = documentsDirectory! + "/\(self.randomStringWithLength(5)).jpg"

                            self.battlesArticlesListImgPath = savePath

                            NSFileManager.defaultManager().createFileAtPath(savePath, contents: data, attributes: nil)

                            let obj:ArticlesList = ArticlesList(id: id!, title: title, subtitle: subtitle, image: self.battlesArticlesListImgPath!)

                            self.battleArticlesListArray.append(obj)

                        }
tableView.hidden = false
tableView.reloadData()

This is because your task is being put on a background tread. Once it is returned some value, and all your tasks are done, just refresh the tableview.

The reason why you print prints empty value is because it is getting executed before the data would have been returned.

Also, it is not a bad idea to see documentation on threading under iOS: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/Introduction/Introduction.html

dirtydanee
  • 6,081
  • 2
  • 27
  • 43