tableView单元格未在该单元格中显示任何内容,但正在控制台中打印内容

时间:2019-06-07 06:22:05

标签: ios swift xcode api uitableview

我已创建一个UITableView,并希望将我的结果从api显示到UITableView中的单元格。有一个带有标签出口的单元格类别,但该单元格中未显示任何内容。结果显示在控制台中,而不显示在单元格标签中

我尝试删除并添加新的约束。 我还添加了一个按钮来重新加载UITableView的内容,但是没有任何帮助。

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! customCellTableViewCell
        var result: String!
        Alamofire.request(booksUrl, method: .get).responseJSON { (response) in

            if response.result.isSuccess{
                let bookJSON : JSON = JSON(response.result.value)
                let tempResult = bookJSON["items"][0]["volumeInfo"]["title"].stringValue
                result = tempResult
                print(tempResult)
            }
        }

        cell.bookNameLabel?.text = result
       return cell
    }

1 个答案:

答案 0 :(得分:0)

请注意,Alamofire(和大多数网络请求)是异步的,这意味着在分派请求时,结果是未知的。

但是,tableview的数据源功能是一个同步方法,必须立即返回单元格。

最终结果是,当请求单元格时,结果是未知的,并且该单元格返回到要显示的表格视图中。一段时间后,收到了网络请求的结果,并打印在屏幕上,但是该单元永远不会更新。

要显示您的信息所需的最少更改为:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! customCellTableViewCell
        Alamofire.request(booksUrl, method: .get).responseJSON { (response) in

            if response.result.isSuccess{
                let bookJSON : JSON = JSON(response.result.value)
                let tempResult = bookJSON["items"][0]["volumeInfo"]["title"].stringValue
                print(tempResult)
                cell.bookNameLabel?.text = tempResult
            }
        }
       return cell
    }

此更新的代码的作用是使用Alamofire回调中的“单元”变量实例来更新单元标签。请注意,这并不是应该采取的方法,因为如果您开始拥有许多单元,其中的许多单元可能会被重用,并且最终您的数据将出现在整个位置并变得非常混乱。

您可能希望将网络请求移出该功能之外,并在自定义UITableViewCell中执行网络请求,请确保在单元被重用时取消网络请求,或者从视图控制器发出的viewDidLoad函数调度该请求完整/部分tableView.reloadData()。

鉴于您的API调用似乎是检索一本书的列表,并且每个单元格都显示一个书名,因此我建议执行一次请求,将所有书本结果存储到一个数组中,然后返回等于数组中的图书数量。

另一方面,您应努力将任何功能内执行的不同任务的数量保持在最低水平。因此,应该返回一个单元格的函数应该返回一个单元格,仅此而已……不执行网络请求。

推荐的代码结构将更接近此:

   var books: JSON?

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

   func retrieveListOfBooks() {
        Alamofire.request(booksUrl, method: .get).responseJSON { (response) in
            DispatchQueue.main.async {
                if response.result.isSuccess{
                    self.books = JSON(response.result.value)
                    self.tableView.reloadData()
                }
            }
        }
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return books?["items"].count ?? 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! customCellTableViewCell
        if indexPath.row < (books?["items"].count ?? 0) {
             let book = books!["items"][indexPath.row]
             let bookTitle = book["volumeInfo"]["title"].stringValue
             cell.bookNameLabel?.text = bookTitle
        }
       return cell
    }

警告:我尚未测试上面的代码,您可能还应该使用Codable来表示您的图书数据模型。