tableView.reloadData() 不起作用,可能没有在主线程上调用

Posted

技术标签:

【中文标题】tableView.reloadData() 不起作用,可能没有在主线程上调用【英文标题】:tableView.reloadData() not working, possibly not being called on main thread 【发布时间】:2018-03-06 00:00:07 【问题描述】:

我有一个包含 3 个部分的 tableView。现在我只真正测试第一部分,即添加朋友。我有一个搜索栏,当我输入文本时,我会搜索用户是否存在,如果存在则重新加载表格。

据我了解,我正在尝试将搜索任务添加到 OperationQueue,以便在用户编辑搜索字段时取消它。

我确认可以搜索到某个用户,我的电话正在返回该用户。但是,当我将用户添加到我的 addFriendsSection 并刷新我的 tableView 时,什么都没有发生。我期望使用搜索用户的用户名添加一个新单元格。

class AddFriendTableViewController: UITableViewController, UISearchDisplayDelegate, UISearchBarDelegate 

    private var sectionTitles = ["Add Friends", "Added Me", "My Followers"]

    private var addFriendsSection = [User]()
    private var addedMeSection    = [FollowRequest]()
    private var myFriendsSection  = [Follower]()

    private var sections: [[Any]]!

    private var searchUserBackgroundQueue = OperationQueue()

    @IBOutlet weak var searchBar: UISearchBar!

    override func viewDidLoad() 
        super.viewDidLoad()

        sections = [
            addFriendsSection,
            addedMeSection,
            myFriendsSection
        ]

        searchBar.isTranslucent = true
        searchBar.alpha = 1
        searchBar.backgroundImage = UIImage()
        searchBar.barTintColor = .clear
        searchBar.delegate = self
    

    override func numberOfSections(in tableView: UITableView) -> Int 
        return sections.count
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return sections[section].count
    

    // User edits the search bar
    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) 
        searchUserBackgroundQueue.cancelAllOperations()

        addFriendsSection = []
        tableView.reloadData()

        if searchText.count >= SignupUsernameViewController.minimumUsernameLength 

            searchUserBackgroundQueue.addOperation 
                UserHandler.shared.exists(username: searchText)  (error, user) in
                    if let user = user 

                        // ATTEMPTING TO RELOAD HERE
                        DispatchQueue.main.async 
                            self.addFriendsSection.append(user)
                            self.tableView.reloadData()
                        
                    
                
            
        
    

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

        switch(sectionTitles[indexPath.section]) 
        case sectionTitles[0]:
            let cell = tableView.dequeueReusableCell(withIdentifier: "addFriendsCell", for: indexPath) as! AddFriendsCell

            cell.usernameLabel.text = addFriendsSection[indexPath.row].username

            return cell
        case sectionTitles[1]:
            let cell = tableView.dequeueReusableCell(withIdentifier: "addedMeCell", for: indexPath)

            return cell
        case sectionTitles[2]:
            let cell = tableView.dequeueReusableCell(withIdentifier: "myFollowersCell", for: indexPath)

            return cell
        default:
            print("AddFriendsTableViewController cellForRowAt error!")
        

        var cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
        return cell
    


【问题讨论】:

只是一种预感,但请尝试将其移到调度异步块之前:self.addFriendsSection.append(user) 你试过viewDidAppear()吗? @MikeTaverne 我试过了,没有结果 @RutgerHuijsmans 我很困惑你的意思 @Brejuro 而不是 viewDidLoad() 尝试在 viewDidAppear() 中运行该代码 【参考方案1】:

问题是您将新朋友存储在self.addFriendsSection 数组中,但UITableViewDataSource 方法如tableView(_:numberOfRowsInSection:) 访问sections[section].count 数组。 当您习惯于 Objective-C、Java、C# 等时,这会很好,但在 Swift 中,数组是 值类型,它复制值。

因此,当您初始化sections 数组(在viewDidLoad 中)时,这将复制来自addFriendsSection 数组(最初为空)的值,而numberOfRows... 将返回0。然后,在搜索之后,你更新addFriendsSection,但这不会影响sections数组的内容,所以numberOfRows仍然会返回0

最快的解决方案是:要么

删除 sections 数组,只使用三个不同的数组 或删除三个不同的数组,只使用sections

查看第一个提案的 uglyquick and dirty 代码 - 你肯定需要做得更好,使用枚举、常量或其他东西:

override func numberOfSections(in tableView: UITableView) -> Int 
    return 3


override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    switch section 
        case 0: return addFriendsSection.count
        case 1: return addedMeSection.count
        case 2: return myFriendsSection.count
        default: return 0
    

【讨论】:

谢谢!我在写它的时候实际上认为这可能是一个问题,然后完全忘记了,但现在它是有道理的。

以上是关于tableView.reloadData() 不起作用,可能没有在主线程上调用的主要内容,如果未能解决你的问题,请参考以下文章

tableView reloadData 不起作用

tableView.reloadData() 不起作用,可能没有在主线程上调用

tableview.reloaddata() 在使用 coredata 时搜索栏取消按钮后不起作用

在AFNetworking中成功调用后self.tableView reloadData不起作用

在AFNetworking中成功调用后self.tableView reloadData不起作用

iOS:tableView.reloadData() 不能快速工作