【问题标题】:iOS UITableView Not ShowingiOS UITableView 不显示
【发布时间】:2021-12-31 19:05:12
【问题描述】:

我对 iOS 有点陌生,正在从 GitHub API 进行网络获取,但无法在表格视图中显示用户。下面是代码,

视图控制器:

    import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var avatarImage: UIImageView!
    @IBOutlet weak var userName: UILabel!
    @IBOutlet weak var usersTableView: UITableView!

    var network = Network()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        network.delegate = self
        usersTableView.dataSource = self
    }

    override func viewWillAppear(_ animated: Bool) {
        network.network()
    }
}

extension ViewController: NetworkDelegate {
    func updateTableView() {
        DispatchQueue.main.async {
            self.usersTableView.reloadData()
        }
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if let users = network.users {
            print(users.count)
            return users.count
        } else {
            return 0
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        print("CALLED")
        let cell = tableView.dequeueReusableCell(withIdentifier: "userCell", for: indexPath) as! UserViewCell
        return cell
    }
}

顺便说一句,标识符来自 .xib 文件,标识符匹配,我不认为这里出现问题。

网络文件

import Foundation

protocol NetworkDelegate {
    func updateTableView()
}

class Network {
    var users: [GitHub]?
    var delegate: NetworkDelegate?

    func network() {
        let url = "https://api.github.com/users"
        let request: URLRequest?

        if let URL = URL(string: url) {
            request = URLRequest(url: URL)
            URLSession.shared.dataTask(with: request!) { result, response, error in
                if let data = result {
    //                print(String(data: data, encoding: .utf8)!)

                    self.users = self.parseJSON(data)
                    self.delegate?.updateTableView()
                } else {
                    print(error!.localizedDescription)
                }
            }
            .resume()
        }
    }

    private func parseJSON(_ data: Data) -> [GitHub]? {
        let json = JSONDecoder()
        do {
            let decodedData = try json.decode([GitHub].self, from: data)
//            print(decodedData)
            return decodedData
        } catch {
            print(error.localizedDescription)
        }
        return nil
    }
}

GitHub API 模型

struct GitHub: Codable {
    let login: String
    let id: Int
    let node_id: String
    let avatar_url: String
    let gravatar_id: String
    let url: String
    let html_url: String
    let followers_url: String
    let following_url: String
    let gists_url: String
    let starred_url: String
    let subscriptions_url: String
    let organizations_url: String
    let repos_url: String
    let events_url: String
    let received_events_url: String
    let type: String
    let site_admin: Bool
}

当我在模拟器上运行此代码时,输​​出为空白(标签下方)

无法弄清楚我做错了什么

提前致谢。

【问题讨论】:

  • 如果你在URLSession.shared.dataTask 中放置一个断点,它可能永远不会被触发。您应该使用完成处理程序(而不是委托),因为您不会立即从服务器获得响应。你评论打印功能有用吗?
  • 是的,打印语句有效,“您应该使用完成处理程序”意味着我应该使用 dispatchQueue 直接在完成处理程序内更新表视图吗?
  • 你能检查故事板吗?如果表格视图正确连接到情节提要中的表格视图
  • 你确定你得到任何数据吗?是否调用了 tableView 数据源方法(numberOfRows、cellForRowAt...)?
  • 它已正确连接,我正在使用 XIB 作为也已连接的视图单元。

标签: ios swift uitableview


【解决方案1】:

尝试使用完成处理程序重构您的代码,而不使用委托模式。

在你的network file:

enum ApiError: Error {
    case network(Error)
    case genericError
    case httpResponseError
    case invalidData
    case decoding
    // you can handle your specific case 
}


  func network(completion: @escaping ( _ error: ApiError?, _ users: [GitHub]?)-> Void) {
        let url = "https://api.github.com/users"
        let request: URLRequest?
        
        if let URL = URL(string: url) {
            request = URLRequest(url: URL)
            URLSession.shared.dataTask(with: request!) { result, response, error in
                if let error = error {
                    completion(.network(error), nil)
                    return
                }
                guard let httpResponse = response as? HTTPURLResponse,
                      (200...299).contains(httpResponse.statusCode) else {
                          completion( .httpResponseError, nil)
                          return
                      }
                guard let data = result else {
                    completion(.invalidData, nil)
                    return
                }
                do {
                    let decodedData = try JSONDecoder().decode([GitHub].self, from: data)
                    completion(nil, decodedData)
                } catch {
                    completion(.decoding, nil)
                }
            }
            .resume()
        }
    }

然后在你的 ViewController 中你可以这样使用它:

   override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        network.network { [weak self] error, users in
            guard let self = self else { return }
            if let error = error {
                print(error)
                return
            }
            DispatchQueue.main.async {
                guard let users = users else { return }
                self.users = users
                self.tableView.reloadData()
            }
        }
    }

如果它仍然没有显示并且cellForRow 没有被调用,您的约束可能有问题并且tableView 框架为零(高度、宽度或两者)。

尝试调试在numberOfRowsInSection 中设置断点,然后在调试区域po tableView 中设置断点,或者只打印 tableView 并检查宽度或高度是否为零。它可能会被调用几次。第一次框架应该为零,但在某些时候你应该得到一个具有高度和宽度的框架。如果没有,请检查您的约束。

您可以查看我的示例,该示例具有 375 x 641 的表格视图

【讨论】:

  • 嘿,谢谢你的帮助,它成功了,问题是由于限制而出现的。
  • @AaratChopra 不错!如果答案对您有所帮助,您可以接受。快乐编码。但是,我仍然不会使用委托将数据发送到您的表格视图。 ;)
【解决方案2】:

如果您的单元格是 xib 文件,那么您必须使用 tableView 注册您的单元格。

viewDidLoad中调用数据源之前

override func viewDidLoad() {
    super.viewDidLoad()
        // Do any additional setup after loading the view.
    usersTableView(UINib(nibName: "userCell", bundle: nil), forCellReuseIdentifier: "userCell")
    network.delegate = self
    usersTableView.dataSource = self
    }

【讨论】:

  • 我认为如果这是问题所在,应用程序会崩溃,不是吗?
  • 我确实在没有这一行的情况下运行它,但没有崩溃,忘记将这一行放在代码中。
猜你喜欢
  • 2015-10-21
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多