【问题标题】:Download JSON Data THEN Reload Collection View下载 JSON 数据然后重新加载集合视图
【发布时间】:2016-10-01 19:30:44
【问题描述】:

这里是快速的。我有一个名为 NetworkService 的类。它有一个设置NSURLSession 和完成块的方法。我的 Object 类 NewsItem 有一个方法 downloadNewsItems,它调用第一个方法并转到一个 url,下载 JSON 数据,将其附加到一个数组并返回它。直到那时一切都按我想要的那样工作。我创建对象并附加它,然后返回它(该方法名为 downloadImage,但它可以处理任何类型的数据)。

func downloadImage(completion: (NSData -> Void)) {
    let request = NSURLRequest(URL: self.url)
    let dataTask = session.dataTaskWithRequest(request) { (data, response, error) in

        if error == nil {
            if let httpResponse = response as? NSHTTPURLResponse {
                switch (httpResponse.statusCode) {
                case 200:
                    if let data = data {
                        completion(data)
                    }
                default:
                    print(httpResponse.statusCode)
                }
            }
        } else {
            print("Error: \(error?.localizedDescription)")
        }
    }

    dataTask.resume()
}

这是我的对象类上相同方法的实现。

static func downloadNewsItems() -> [NewsItem] {

  var newsItems = [NewsItem]()

  let url = NSURL(string: "http://my-url.com.json")
  let networkService = NetworkService(url: url!)

  networkService.downloadImage { (data) -> Void in

    let jsonData = JSON(data:data)

    for item in jsonData["stories"].arrayValue {

     // print(item["title"])

      let newsArticle = NewsItem()
      newsArticle.category = item["category"].string
      newsArticle.titleText = item["title"].string
      newsArticle.paragraph1 = item["paragraph1"].string
      newsArticle.paragraph2 = item["paragraph2"].string
      newsArticle.featureImage = NSURL(string: "\(item["headerImage"].string)")
      newsArticle.date = item["date"].string
      newsArticle.majorReference = item["majorReference"].string
      newsArticle.fact = item["fact"].string

      newsItems.append(newsArticle)

    }

  print(newsItems.count)


  }

  return newsItems

}

print(newsItems.count) 表明我已将我的对象正确下载并更新到字典中。现在问题来了。我有一个CollectionViewController。我想用从方法调用中获得的数据填充它。我创建了一个数组并调用了在ViewDidLoad: 内部返回对象的方法,但是不!当我打印时,我得到 0 并且我的 collectionView 不显示任何单元格。

var newsItems = [NewsItem]()

然后在viewDidLoad中:

newsItems = NewsItem.downloadNewsItems()
print(newsItems.count) 
collectionView.reloadData()

对象已下载,由我的 init() 方法设置,并在 NetworkService / NewsItem 类中添加到方法中的数组中,但是当我从 Collection View Controller 调用该方法时,什么都没有。最初我尝试了默认的 JSONSerialisation 路由,但我遇到了同样的问题。我想也许我做得不对。切换到第 3 方 JSON 库(SwiftyJSON)...完全相同的问题。请帮忙。我已经有 3 周的时间了。我..我不能。没有了。。

【问题讨论】:

    标签: ios json swift2


    【解决方案1】:

    用户2361090,

    您正在调用 web 服务以获取 downloadNewsItems 中的所有 newsItems。这是一个异步调用。所以它需要一点时间来获取进程然后填充 newsItems 数组。但是即使在它被填充之前你也不会等待它被填充你已经返回它因此你将在newsItems = NewsItem.downloadNewsItems() 中返回空数组。使用块来移交数据。将您的方法更改为

    static func downloadNewsItems(completionBlock block : ([NewsItem]) -> ()){
    
        var newsItems = [NewsItem]()
    
        let url = NSURL(string: "http://my-url.com.json")
        let networkService = NetworkService(url: url!)
    
        networkService.downloadImage { (data) -> Void in
    
            let jsonData = JSON(data:data)
    
            for item in jsonData["stories"].arrayValue {
    
                // print(item["title"])
    
                let newsArticle = NewsItem()
                newsArticle.category = item["category"].string
                newsArticle.titleText = item["title"].string
                newsArticle.paragraph1 = item["paragraph1"].string
                newsArticle.paragraph2 = item["paragraph2"].string
                newsArticle.featureImage = NSURL(string: "\(item["headerImage"].string)")
                newsArticle.date = item["date"].string
                newsArticle.majorReference = item["majorReference"].string
                newsArticle.fact = item["fact"].string
    
                newsItems.append(newsArticle)
    
            }
    
            print(newsItems.count)
            //if the control comes here in background thread because you know you have to reload the collection view which is UI operation change it main thread
             dispatch_async(dispatch_get_main_queue(), { () -> Void in
                block(newsItems)
            })
        }
    
    }
    

    最后你可以这样称呼它,

    NewsItem.downloadNewsItems{ (passedArray) -> () in
          newsItems = passedArray
          collectionView.reloadData()
    }
    

    【讨论】:

    • 先生,愿您的代码永远不会崩溃,也愿您的咖啡永远不会用完。你是一个真正的英雄。谢谢。完美运行!
    • @user2361090 : hehehehehehe :) 永远欢迎你,伙计 :) 编码快乐 :)
    猜你喜欢
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    相关资源
    最近更新 更多