【问题标题】:Json data not showing on tableViewJson 数据未显示在 tableView 上
【发布时间】:2016-12-20 10:54:44
【问题描述】:

我正在使用 Swift 为 iOS 构建一个小部件。主应用程序的目的是连接到 URL 新闻提要并获取最新消息,而小部件仅获取标题以显示在 Today 视图中的 tableView 中。

我已经为小部件编写了此方法,以便获取数据以填充表格,但由于某种原因没有显示任何内容。我试图调试它,但作为一个小部件,它似乎实际上是不可能的。

这是 cellForRowAt,我连接到提要并尝试提取数据。有趣的是,主应用程序使用基本相同的代码,并且运行良好。

     override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
      let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)


      let urlRequest = URLRequest(url: URL(string: "https://newsapi.org/v1/articles?source=techcrunch&sortBy=top&apiKey=c64849bc30eb484fb820b80a136c9b0a")!)


      let task = URLSession.shared.dataTask(with: urlRequest) { (data,response,error) in

           do{

                let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]

                if let articlesFromJson = json["articles"] as? [[String: AnyObject]] {

                     if !(error != nil) {

                          var resultArray: NSMutableArray = NSMutableArray()

                          for articlesFromJson in articlesFromJson {

                               if let title = articlesFromJson["title"] as? String{
                                    resultArray.add(title)

                               }

                               let array:NSArray = resultArray.reverseObjectEnumerator().allObjects as NSArray
                               resultArray = array as! NSMutableArray
                               let title:String = resultArray.object(at: indexPath.row) as! String
                               cell.textLabel?.text = title

                          }
                     }            
                }

                //reload on main thread to speed it up
                DispatchQueue.main.async {
                 self.tableView.reloadData()
                }

           } catch let error {
                print(error)
           }            
      }
      task.resume()

      return cell
 }

如果有人可以帮助我找出错误在哪里,那将是一个巨大的帮助,我已经被这个问题困扰了好几天了。谢谢

【问题讨论】:

  • 不要试图在 Swift 中复制你的 Objective-C 习惯。例如,不要使用 NSArray/NSMutableArray/NSDictionary/NSMutableDictionary,而是使用 Swift 集合等。并避免强制展开和强制转换。最后建议:不要在tableView里面做网络和解析。让 tableView 使用另一个类的准备好的内容,该类的工作是下载和解析。
  • 谢谢,我已经把所有的网络都放在了 Justin 下面建议的另一种方法中,我会考虑使用集合而不是 NSMutableArrays。

标签: ios json swift uitableview widget


【解决方案1】:

您希望在 cellForRow 之外发出网络请求,然后在完成后 reloadData 让 tableView 重新加载调用 cellForRow 的单元格。

将数据数组存储在请求之外,以便您可以从函数外部引用它。

var resultArray: NSMutableArray = []

override func viewDidLoad() {
   super.viewDidLoad()
   getData()
 }     

func getData() {
  let urlRequest = URLRequest(url: URL(string: "https://newsapi.org/v1/articles?source=techcrunch&sortBy=top&apiKey=c64849bc30eb484fb820b80a136c9b0a")!)

  let task = URLSession.shared.dataTask(with: urlRequest) {[weak self] (data,response,error) in
    guard let strongSelf = self else { return }
    do{
        let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
        if let articlesFromJson = json["articles"] as? [[String: AnyObject]] {
            if error == nil {
                for articlesFromJson in articlesFromJson {
                    if let title = articlesFromJson["title"] as? String{
                        strongSelf.resultArray.add(title)
                    }
                    let array:NSArray = strongSelf.resultArray.reverseObjectEnumerator().allObjects as NSArray
                    strongSelf.resultArray = array as! NSMutableArray

                    DispatchQueue.main.async {
                        strongSelf.tableView.reloadData()
                    }

                } catch let error {
                    print(error)
                }            
            }
            task.resume()
     }

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

  let title:String = resultArray.object(at: indexPath.row) as! String

  cell.textLabel?.text = title

  return cell
}

【讨论】:

  • 一定要遵循 Eric Aya 上面的建议。这个答案的重点是重组以获得预期的结果。
  • 感谢您的回答,很遗憾我尝试了您的建议,但它也没有加载数据,它实际上现在说“无法加载”而不是之前的三个空表行。
  • 我确实注意到我在原始答案中犯了一个错误。我把它写成'如果错误!= nil'{如果没有错误,你会做什么}。我将其更改为 ' if error == nil '。这可能就是您遇到问题的原因。进行更改并让我知道您是否仍有问题
  • 我尝试了更改,但仍然收到相同的无法加载消息
  • 无法加载似乎是与小部件相关的错误。我不熟悉它是如何工作的,但我只是在谷歌上搜索了一下,发现其他人过去曾遇到过问题。我不认为错误来自这个函数。我建议你谷歌这个错误,看看你是否能找到有帮助的东西。如果没有,请打开一个带有该错误的单独问题。
【解决方案2】:
checks proper if TableView delegate or datasource proper connected. and check array count before load data in cell 
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
if (resultArray.count > 0){
      let title:String = resultArray.object(at: indexPath.row) as! String

  cell.textLabel?.text = title
}
else
{
  print("Error: resultArray contain nil value ")
}


  return cell
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多