Swift ios 9: Section header 重载数据后改变位置
Swift ios 9: Section header change position after reload data
我有普通的 UITableView,其中包含许多部分和行。部分工作正常。但有时在重新加载 table 的数据后,部分会更改位置。例如,它发生在我更改标签时。可能是什么问题?
更改标签前的图片:
更改标签后的图像:
更新:
添加以下代码:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.dishesListTableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func customizeCollectionView() {
self.collectionView.delegate = self
self.collectionView.dataSource = self
self.collectionView.dataProviderDelegate = self.dishesListDataProvider
self.collectionView.showsHorizontalScrollIndicator = false
self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast
self.collectionView.registerClass(HPCollectionViewCell.self, forCellWithReuseIdentifier: HPCollectionViewCellConstants.reuseIdentifier)
}
//MARK: - UITableViewDelegate
func customziseDishesListTableView(){
self.dishesListTableView.delegate = self
self.dishesListTableView.dataSource = self
self.dishesListTableView.registerNib(UINib(nibName: DishesListSingleTableViewCell.nibName, bundle: nil), forCellReuseIdentifier: DishesListSingleTableViewCell.nibName)
self.dishesListTableView.registerNib(UINib(nibName: DishesListSinglePizzaTableViewCell.nibName, bundle: nil), forCellReuseIdentifier: DishesListSinglePizzaTableViewCell.nibName)
self.dishesListTableView.estimatedRowHeight = 123
self.dishesListTableView.rowHeight = UITableViewAutomaticDimension
if self.dishesListDataProvider.isPizza() {
self.dishesListTableView.separatorColor = UIColor.clearColor()
}else{
self.dishesListTableView.separatorColor = UIColor.expSilverColor()
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dishesListDataProvider.countOfDishes(section)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.dishesListDataProvider.countOfKitchenTypes()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if self.dishesListDataProvider.getDishItemByIndex(indexPath.section, indexDish: indexPath.row).isPizza() {
let cell = tableView.dequeueReusableCellWithIdentifier(DishesListSinglePizzaTableViewCell.nibName, forIndexPath: indexPath) as! DishesListSinglePizzaTableViewCell
cell.customizeView(self.dishesListDataProvider.getDishItemByIndex(indexPath.section, indexDish: indexPath.row), dishesListSingleTableViewCellProtocol: self, indexPath: indexPath)
return cell
}else{
let cell = tableView.dequeueReusableCellWithIdentifier(DishesListSingleTableViewCell.nibName, forIndexPath: indexPath) as! DishesListSingleTableViewCell
cell.customizeView(self.dishesListDataProvider.getDishItemByIndex(indexPath.section, indexDish: indexPath.row), dishesListSingleTableViewCellProtocol: self, indexPath: indexPath)
return cell
}
}
func tableView(tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) {
self.collectionView.scrollToIndex(section, animated: true)
self.collectionView.changeSelectionForCellAtIndexPath(NSIndexPath(forItem: section, inSection: 0))
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let sectionView = NSBundle.mainBundle().loadNibNamed(DishesListSectionView.nibName, owner: self, options: nil)[0] as! DishesListSectionView
sectionView.customizeView(self.dishesListDataProvider.getKitchenItemByIndex(section).kitchenTypeTitle)
return sectionView
}
//MARK: - UIScrollViewDelegate
func scrollViewDidScroll(scrollView: UIScrollView) {
if currentSectionIndex != self.dishesListTableView.indexPathsForVisibleRows![0].section {
currentSectionIndex = self.dishesListTableView.indexPathsForVisibleRows![0].section
self.collectionView.scrollToIndex(currentSectionIndex, animated: true)
self.collectionView.changeSelectionForCellAtIndexPath(NSIndexPath(forItem: currentSectionIndex, inSection: 0))
}
}
这是因为UIviewcontroller属性。请先 select UIViewController 来自 Storyboard , Attribute Inspector
我知道这是一个旧线程,但取消选中 Adjust Scroll View Insets
没有帮助。我遇到了这个问题并通过重新加载 table 两次解决了它。
在我的项目中,当我拉起 tableView
请求更多数据然后在请求后重新加载数据时发生此错误。我需要在请求数据后创建许多部分,如果我 reloadData
两次,它可能会影响性能。不仅如此,我发现如果我向上或向下滚动 tableView
,部分的 headerView 的位置就会正确。所以我修复了这个错误(我的情况)我通过这个请求数据:
[_tableView reloadData];
CGPoint offSetOrigin = _tableView.contentOffset;
CGPoint offSetSecond = CGPointMake(0, offSet.y-1);
_tableView.contentOffset = offSetSecond;
_tableView.contentOffset = offSet;
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.beginUpdates()
tableView.endUpdates()
这对我有帮助。
双 reloadData
会导致闪烁,而此解决方案不会。
这里的解决方案没有解决我的问题,所以我留下了另一种对我有帮助的可能解决方案。
设置 estimatedSectionHeaderHeight,如果没有它,我的 tableView 似乎无法计算第一部分的初始位置。
调用 reloadData() 两次对我也有效,但我建议在 reloadData() 之后调用 tableView.layoutSubviews(),这对我也有效。
您的 table 视图单元格的估计高度似乎存在问题。由于内部优化系统根据估计的高度值计算缺失单元格的高度,这就是为什么它可以将您的 headers 定位在错误的计算高度上(例如实际单元格大于或小于其估计大小)。当您在列表中间调用 reloadData()
时,通常会发生这种情况。例如,当您想用第二页更新列表的内容时,您应该避免调用 reloadData()
作为正确的解决方案。所以你应该使用 tableView.beginUpdates()
和
tableView.endUpdates()
并为 table 视图更新项目 collection。还有基于 API performBatchUpdates
的新闭包(就像 UICollectionView
一样),但它可以从 iOS 11.
获得
希望对您找到合适的解决方案有所帮助
我有普通的 UITableView,其中包含许多部分和行。部分工作正常。但有时在重新加载 table 的数据后,部分会更改位置。例如,它发生在我更改标签时。可能是什么问题?
更改标签前的图片:
更改标签后的图像:
更新: 添加以下代码:
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.dishesListTableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func customizeCollectionView() {
self.collectionView.delegate = self
self.collectionView.dataSource = self
self.collectionView.dataProviderDelegate = self.dishesListDataProvider
self.collectionView.showsHorizontalScrollIndicator = false
self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast
self.collectionView.registerClass(HPCollectionViewCell.self, forCellWithReuseIdentifier: HPCollectionViewCellConstants.reuseIdentifier)
}
//MARK: - UITableViewDelegate
func customziseDishesListTableView(){
self.dishesListTableView.delegate = self
self.dishesListTableView.dataSource = self
self.dishesListTableView.registerNib(UINib(nibName: DishesListSingleTableViewCell.nibName, bundle: nil), forCellReuseIdentifier: DishesListSingleTableViewCell.nibName)
self.dishesListTableView.registerNib(UINib(nibName: DishesListSinglePizzaTableViewCell.nibName, bundle: nil), forCellReuseIdentifier: DishesListSinglePizzaTableViewCell.nibName)
self.dishesListTableView.estimatedRowHeight = 123
self.dishesListTableView.rowHeight = UITableViewAutomaticDimension
if self.dishesListDataProvider.isPizza() {
self.dishesListTableView.separatorColor = UIColor.clearColor()
}else{
self.dishesListTableView.separatorColor = UIColor.expSilverColor()
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dishesListDataProvider.countOfDishes(section)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return self.dishesListDataProvider.countOfKitchenTypes()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if self.dishesListDataProvider.getDishItemByIndex(indexPath.section, indexDish: indexPath.row).isPizza() {
let cell = tableView.dequeueReusableCellWithIdentifier(DishesListSinglePizzaTableViewCell.nibName, forIndexPath: indexPath) as! DishesListSinglePizzaTableViewCell
cell.customizeView(self.dishesListDataProvider.getDishItemByIndex(indexPath.section, indexDish: indexPath.row), dishesListSingleTableViewCellProtocol: self, indexPath: indexPath)
return cell
}else{
let cell = tableView.dequeueReusableCellWithIdentifier(DishesListSingleTableViewCell.nibName, forIndexPath: indexPath) as! DishesListSingleTableViewCell
cell.customizeView(self.dishesListDataProvider.getDishItemByIndex(indexPath.section, indexDish: indexPath.row), dishesListSingleTableViewCellProtocol: self, indexPath: indexPath)
return cell
}
}
func tableView(tableView: UITableView, willDisplayFooterView view: UIView, forSection section: Int) {
self.collectionView.scrollToIndex(section, animated: true)
self.collectionView.changeSelectionForCellAtIndexPath(NSIndexPath(forItem: section, inSection: 0))
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let sectionView = NSBundle.mainBundle().loadNibNamed(DishesListSectionView.nibName, owner: self, options: nil)[0] as! DishesListSectionView
sectionView.customizeView(self.dishesListDataProvider.getKitchenItemByIndex(section).kitchenTypeTitle)
return sectionView
}
//MARK: - UIScrollViewDelegate
func scrollViewDidScroll(scrollView: UIScrollView) {
if currentSectionIndex != self.dishesListTableView.indexPathsForVisibleRows![0].section {
currentSectionIndex = self.dishesListTableView.indexPathsForVisibleRows![0].section
self.collectionView.scrollToIndex(currentSectionIndex, animated: true)
self.collectionView.changeSelectionForCellAtIndexPath(NSIndexPath(forItem: currentSectionIndex, inSection: 0))
}
}
这是因为UIviewcontroller属性。请先 select UIViewController 来自 Storyboard , Attribute Inspector
我知道这是一个旧线程,但取消选中 Adjust Scroll View Insets
没有帮助。我遇到了这个问题并通过重新加载 table 两次解决了它。
在我的项目中,当我拉起 tableView
请求更多数据然后在请求后重新加载数据时发生此错误。我需要在请求数据后创建许多部分,如果我 reloadData
两次,它可能会影响性能。不仅如此,我发现如果我向上或向下滚动 tableView
,部分的 headerView 的位置就会正确。所以我修复了这个错误(我的情况)我通过这个请求数据:
[_tableView reloadData];
CGPoint offSetOrigin = _tableView.contentOffset;
CGPoint offSetSecond = CGPointMake(0, offSet.y-1);
_tableView.contentOffset = offSetSecond;
_tableView.contentOffset = offSet;
tableView.reloadData()
tableView.layoutIfNeeded()
tableView.beginUpdates()
tableView.endUpdates()
这对我有帮助。
双 reloadData
会导致闪烁,而此解决方案不会。
这里的解决方案没有解决我的问题,所以我留下了另一种对我有帮助的可能解决方案。
设置 estimatedSectionHeaderHeight,如果没有它,我的 tableView 似乎无法计算第一部分的初始位置。
调用 reloadData() 两次对我也有效,但我建议在 reloadData() 之后调用 tableView.layoutSubviews(),这对我也有效。
您的 table 视图单元格的估计高度似乎存在问题。由于内部优化系统根据估计的高度值计算缺失单元格的高度,这就是为什么它可以将您的 headers 定位在错误的计算高度上(例如实际单元格大于或小于其估计大小)。当您在列表中间调用 reloadData()
时,通常会发生这种情况。例如,当您想用第二页更新列表的内容时,您应该避免调用 reloadData()
作为正确的解决方案。所以你应该使用 tableView.beginUpdates()
和
tableView.endUpdates()
并为 table 视图更新项目 collection。还有基于 API performBatchUpdates
的新闭包(就像 UICollectionView
一样),但它可以从 iOS 11.
希望对您找到合适的解决方案有所帮助