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
查看第一个提案的 ugly 和 quick 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() 在使用 coredata 时搜索栏取消按钮后不起作用
在AFNetworking中成功调用后self.tableView reloadData不起作用