【问题标题】:tableView not refreshing表视图不刷新
【发布时间】:2018-12-07 13:00:39
【问题描述】:

我是编程新手,目前正在构建一个从 Firebase 收集数据的应用。

当视图被拉下时,我认为实现这个令人耳目一新的动画会很好。现在我遇到的问题是根本没有刷新(一开始工作正常)。此外,每次应用启动时,tableView 一开始都是空的,当您进行下推时,它会重新加载,但错误。

我真的很挣扎。有人能看出我的代码有什么问题吗?

class ViewController: BaseViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet var newsfeedTableView: UITableView!
    @IBOutlet weak var activityIndicatorView: UIActivityIndicatorView!

    private let refreshControl = UIRefreshControl()

    var ref: DatabaseReference!

    var posts = [String]()
    var timeRef = [String]()
    var userRef = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()
        addSlideMenuButton()
        setupTableView()

        ref = Database.database().reference()

        ref.child("posts").observe( .childAdded, with: { snapshot in

            let newPost = snapshot.value as? NSDictionary
            let post_title:String = newPost!["post_title"] as? String ?? "error"

            let newPostTime = snapshot.value as? NSDictionary
            let post_time:String = newPostTime!["post_time"] as? String ?? "error collecting timestamp"

            let newPostUser = snapshot.value as? NSDictionary
            let post_user:String = newPostUser!["post_user"] as? String ?? "Team"

            self.posts.insert(post_title, at: 0)
            self.timeRef.insert(post_time, at: 0)
            self.userRef.insert(post_user, at: 0)

            self.newsfeedTableView.reloadData()
        })
    }

    private func setupTableView() {
        if #available(iOS 10.0, *) {
            newsfeedTableView.refreshControl = refreshControl
        } else {
            newsfeedTableView.addSubview(refreshControl)
        }
        refreshControl.addTarget(self, action: #selector(refreshNewsFeedTableView(_:)), for: .valueChanged)
    }

    @objc private func refreshNewsFeedTableView(_ sender: Any) {

        //self.refreshControl.beginRefreshing()
        self.newsfeedTableView.reloadData()
        self.refreshControl.endRefreshing()
        self.activityIndicatorView.stopAnimating()
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return posts.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! NewsfeedCell

        cell.customTextLabel?.text = posts[indexPath.row]
        cell.customTimeLabel?.text = timeRef[indexPath.row]
        cell.customNameLabel?.text = userRef[indexPath.row]

        return cell
    }
    }

    class NewsfeedCell: UITableViewCell {
    @IBOutlet weak var customTextLabel: UILabel!
    @IBOutlet weak var customNameLabel: UILabel!
    @IBOutlet weak var customTimeLabel: UILabel!

    }

【问题讨论】:

  • 数据库操作是异步的吗?重新加载表格视图时是否需要使用dispatchQueue.main.async{ } 才能在正确的线程上执行此操作?
  • @TommyBs firebase 回调默认在主线程中

标签: ios swift firebase tableview


【解决方案1】:

这里

@objc private func refreshNewsFeedTableView(_ sender: Any)

您无需执行任何 API 请求来获取数据然后重新加载表并结束刷新,并且由于您在此处使用了观察

ref.child("posts").observe( .childAdded, with: { snapshot in

然后你会得到任何新数据,如果你需要实现刷新然后在一个函数中插入所有数据库代码并将observe替换为observeSingleEvent并从viewDidLoad和刷新选择器方法调用它

ref.child("posts").observeSingleEvent( .value, with: { snapshot in

注意使用建议的方法,您将一次获取所有子对象,因此不要忘记清理 observeSingleEvent 回调中的数组以避免重复值,还可以考虑在此处创建一个 dataSource 数组而不是 3 个

 self.posts.insert(post_title, at: 0)
 self.timeRef.insert(post_time, at: 0)
 self.userRef.insert(post_user, at: 0)

可能会创建一个模型

struct Item {
  let post:String
  let time:String
  let user:String
}

【讨论】:

    【解决方案2】:

    我在代码中看到的唯一问题是,您使用 .childAdded 来观察来自 firebase 的事件,但根据 firebase 文档:

    child_added 事件通常在检索列表时使用 数据库中的项目。与返回整个值的值不同 位置的内容,child_added 每触发一次 现有的孩子,然后每次将新的孩子添加到 指定的路径。事件回调传递了一个快照,其中包含 新孩子的数据。出于订购目的,它还传递了第二个 包含前一个孩子的键的参数。

    所以,如果你想接收任何特定节点的所有数据,你需要使用 value 事件而不是 child_added 如下所述:

    value 事件用于读取内容的静态快照 在给定的数据库路径上,因为它们在读取时存在 事件。使用初始数据触发一次,每次触发一次 数据变化。事件回调传递了一个快照,其中包含 该位置的所有数据,包括子数据。在代码示例中 上面, value 返回了您应用中的所有博客文章。每次一个 新增博文,回调函数将返回所有的 帖子。

    【讨论】:

      【解决方案3】:

      在 DispatchQueue.main 中重新加载 UItableView,试试这段代码。

      override func viewDidLoad() {
              super.viewDidLoad()
              addSlideMenuButton()
              setupTableView()
      
              ref = Database.database().reference()
      
              ref.child("posts").observe( .childAdded, with: { snapshot in
      
                  let newPost = snapshot.value as? NSDictionary
                  let post_title:String = newPost!["post_title"] as? String ?? "error"
      
                  let newPostTime = snapshot.value as? NSDictionary
                  let post_time:String = newPostTime!["post_time"] as? String ?? "error collecting timestamp"
      
                  let newPostUser = snapshot.value as? NSDictionary
                  let post_user:String = newPostUser!["post_user"] as? String ?? "Team"
      
                  self.posts.insert(post_title, at: 0)
                  self.timeRef.insert(post_time, at: 0)
      
      
                  self.userRef.insert(post_user, at: 0)
                  DispatchQueue.main.async() {
                      self.newsfeedTableView.reloadData()
                  }
      
              })
          }
      

      【讨论】:

      • 什么都没有改变 :(
      猜你喜欢
      • 1970-01-01
      • 2010-11-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-23
      • 2018-04-14
      • 2016-12-25
      • 1970-01-01
      相关资源
      最近更新 更多