【问题标题】:Why isn't my function reloading the UITableView's data?为什么我的函数没有重新加载 UITableView 的数据?
【发布时间】:2020-10-10 09:24:13
【问题描述】:

我正在创建一个表格视图,用于监控来自几个帐户的前 20 条推文并按时间顺序显示它们。它调用 Twitter API,然后遍历推文并将它们添加到 tableview。我的问题是,当我尝试刷新 tableview 中的数据时,什么也没有发生。我尝试再次调用 getTwitterInfo() ,但即使有新的推文要显示,它也不会做任何事情。我已经尝试了所有可以在网上找到的方法,但似乎没有任何解决方法。任何帮助将不胜感激——这是我的视图控制器的代码。

class TwitterViewController: UIViewController {

    var tableView = UITableView()

    var tweets = [Tweet]()

    let cellID = "cellID"

    var accounts: [String:String] = [
        //this is just a dictionary of the accounts I'm monitoring and their corresponding profile picture
    ]

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationController?.setNavigationBarHidden(true, animated: false)

        configureTableView()
        getTwitterInfo()
    }

    func configureTableView(){
        view.addSubview(tableView)
        tableView.delegate = self
        tableView.dataSource = self

        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 150

        tableView.register(TweetCell.self, forCellReuseIdentifier: cellID)

        tableView.translatesAutoresizingMaskIntoConstraints = false
        tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true


    }

    func getTwitterInfo(){

        print("getting new info...")


        tweets = [Tweet]()

        var counter = 1

        for (name, pfpLink) in accounts{
            let imageURL = URL(string:pfpLink)!

            var image = UIImage()

            let imageDataTask = URLSession.shared.dataTask(with: imageURL) { (data,response,error) in
                image = UIImage(data:data!)!
            }

            imageDataTask.resume()


            let url = URL(string: "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=\(name)&count=20&tweet_mode=extended")!

            var request = URLRequest(url: url)
            request.allHTTPHeaderFields = ["Authorization": Constants.bearer]

            let dataTask = URLSession.shared.dataTask(with: request){ (data,response,error) in
                do{
                    let data = try JSONSerialization.jsonObject(with: data!, options: []) as? [[String:Any]]

                    let _ = data!.map{
                        let htmlEncodedString = $0["full_text"] as! String

                        let message: String
                        if let newDict = $0["retweeted_status"] as? Dictionary<String,Any>{
                            let newEncodedString = newDict["full_text"] as! String
                            message = Constants.decodeTwitterString(newEncodedString)
                        }else{
                            message = Constants.decodeTwitterString(htmlEncodedString)
                        }

                        let userInfo = $0["user"] as! Dictionary<String,Any>

                        let screenName = userInfo["screen_name"] as! String
                        let username = userInfo["name"] as! String

                        let twitterID = userInfo["id_str"] as! String

                        let dateString = $0["created_at"] as! String

                        let tweet = Tweet(name: username, username: screenName, message: message, twitterID: twitterID, image:image, dateString: dateString)
                        self.tweets.append(tweet)
                    }

                    if (counter == self.accounts.keys.count) {
                            let formatter = DateFormatter()
                            formatter.dateFormat = "EE LLL dd HH:mm:ss Z yyyy"

                            self.tweets = self.tweets.sorted{
                                formatter.date(from: $0.dateString)! > formatter.date(from: $1.dateString)!
                            }
                        DispatchQueue.main.async{
                            self.tableView.reloadData()
                        }

                    }

                    counter += 1

                }catch let err{
                    print(err)
                }
            }

            dataTask.resume()

        }
    }
}

extension TwitterViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return tweets.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellID, for: indexPath) as! TweetCell
        let tweet = tweets[indexPath.row]

        cell.set(tweet:tweet)
        cell.selectionStyle = .none

        return cell
    }


}

【问题讨论】:

    标签: ios swift uitableview twitter


    【解决方案1】:

    我假设你已经验证了 try 没有抛出异常,并且强制 unwrap 没有崩溃。我认为你应该做的是移动

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

    到它所在的 if 块的外部和之后。我怀疑 tableView.reloadData() 没有被调用,因为它所在的 if 块中的条件检查失败。试试看,让我知道它是否对您有帮助。如果没有,您最好从 GitHub 向我发送指向您项目的链接。

    如果您不想向后兼容运行 iOS 13 更低版本的设备,请使用 Google UITableViewDiffableDataSource。用新方法来做这件事要容易得多,特别是当项目变得有点复杂时,需要管理许多 tableview 状态更改,从而为您省去很多麻烦。如果您想查看它,这是一个很好的起点:[https://developer.apple.com/videos/play/wwdc2019/220/][1]

    【讨论】:

    • 我只是在该块内放了一个打印语句,它确实最终打印了 - 似乎一切都在运行,但由于某种原因它无法正常工作。
    • 我刚刚发现似乎是问题所在。我从另一个视图控制器调用 getTwitterInfo(),我想当我调用它时我必须把它放在它自己的 Dispatch.main.async 块中。我真的不明白为什么,但是嘿,它有效。无论如何感谢您的帮助!
    • 跟进:我还必须以编程方式创建 TwitterVIewController 的实例,而不是通过情节提要实例化它。超级奇怪——我不确定这会如何改变任何事情,但它只能这样工作。
    猜你喜欢
    • 1970-01-01
    • 2011-09-26
    • 2023-03-31
    • 2022-01-19
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    相关资源
    最近更新 更多