滚动 UITableView 和 UICollectionView 的数据不正确
Posted
技术标签:
【中文标题】滚动 UITableView 和 UICollectionView 的数据不正确【英文标题】:Incorrect data on scrolling UITableView and UICollectionView 【发布时间】:2015-06-21 07:34:30 【问题描述】:我已将我的示例项目附加到 github,并提供了下面的链接我有一个表格视图,在该表格视图中,单元格包含一个 UICollectionView。这意味着每个单元格都可以水平滚动到某个限制,比如说 5。tableView 单元格和 collectionview 单元格都有自定义单元格类tableview 单元格还有一个 UIPageControl,它会改变当我们水平滚动 UICollectionViewCells 我设法完成了这部分工作,但假设我已将第 2 个 tableview 单元格的 collectionview 滚动到第 3 个位置,并且这在第 9 个 tableview 单元格上有所重复。 第 9 个 tableview 单元格也有相同的数据。但是我在 9 号还没有设置任何东西。 所以这意味着问题在于可重用性和滚动时数据不正确。
到目前为止我的代码是
//ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@end
实现类
//ViewController.m
#import "ViewController.h"
#import "MyCollectionViewCell.h"
#import "MyTableViewCell.h"
@interface ViewController ()
MyTableViewCell* tableViewCell;
@end
@implementation ViewController
- (void)viewDidLoad
[super viewDidLoad];
#pragma mark TableView Delegates
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section
return 10;
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
tableViewCell=(MyTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell"];
if(tableViewCell==nil)
tableViewCell=[[MyTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyTableViewCell"];
UICollectionViewFlowLayout *flowLayout =
[[UICollectionViewFlowLayout alloc] init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
[flowLayout setMinimumInteritemSpacing:0.0f];
[flowLayout setMinimumLineSpacing:0.0f];
[tableViewCell.collectionView setPagingEnabled:YES];
[tableViewCell.collectionView setCollectionViewLayout:flowLayout];
[tableViewCell.collectionView setBackgroundColor:[UIColor whiteColor]];
tableViewCell.pageControl.tag=indexPath.row;
tableViewCell.collectionView.tag=indexPath.row;
NSLog(@"Index path row %ld",indexPath.row);
[tableViewCell setSelectionStyle:UITableViewCellSelectionStyleNone];
tableViewCell.path=indexPath;
return tableViewCell;
#pragma mark CollectionView Delegates
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
return 5;
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
MyCollectionViewCell* cell=(MyCollectionViewCell*)[collectionView dequeueReusableCellWithReuseIdentifier:@"MyCollectionViewCell" forIndexPath:indexPath];
if(cell==nil)
cell=[[MyCollectionViewCell alloc]initWithFrame:CGRectMake(0, 0, collectionView.frame.size.width, collectionView.frame.size.height)];
[cell.myLabel setText:[NSString stringWithFormat:@"%ld",(long)indexPath.row]];
return cell;
-(CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
return collectionView.frame.size;
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout: (UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
return UIEdgeInsetsMake(0, 0, 0, 0);
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
if ([scrollView isKindOfClass:[UICollectionView class]])
UICollectionView *mainCollection = (UICollectionView *) scrollView;
NSIndexPath *myIP = [NSIndexPath indexPathForRow:mainCollection.tag inSection:0];
MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:myIP];
CGRect visibleRect = (CGRect).origin = mainCollection.contentOffset, .size = mainCollection.bounds.size;
CGPoint visiblePoint = CGPointMake(CGRectGetMidX(visibleRect), CGRectGetMidY(visibleRect));
NSIndexPath *visibleIndexPath = [mainCollection indexPathForItemAtPoint:visiblePoint];
NSLog(@"visibleIndexPath %ld",(long)visibleIndexPath.row);
[cell.pageControl setCurrentPage:visibleIndexPath.row];
@end
细胞类
//MyTableViewCell.h
#import <UIKit/UIKit.h>
@interface MyTableViewCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UICollectionView *collectionView;
@property (weak, nonatomic) IBOutlet UIPageControl *pageControl;
@property (strong, nonatomic) NSIndexPath * path;
@end
MyCollectionViewCell.h
//MyCollectionViewCell.h
#import <UIKit/UIKit.h>
@interface MyCollectionViewCell : UICollectionViewCell
@property (weak, nonatomic) IBOutlet UILabel *myLabel;
@end
视图类似于
我担心的是,每当我进行任何更改时,让我们在表格 viewcell 上的单元格 1 上说并滚动其中的集合以让我们说第二个索引,然后每当我滚动整个表格时都会重复此操作
注意:我已将表格的单元格数保持为 10,以查看重复影响。 我的示例项目的 Github 链接是https://github.com/RajanMaheshwari/TableAndCollection
【问题讨论】:
您有两种方法来维护 Tableview 状态,即一种是使用数据源表示使用模型为每一行维护状态,该模型维护其上每个视图的信息。其次,像 Grzegorz Krukowski 在下面的回答中解释的那样创建新单元格。但是第二个是更昂贵的一个。给您的一个建议是,在 tableview 单元格中的 awakefromnib 方法中移动集合视图流布局设置,同时在 awakefromnib 中移动所有默认设置代码。 嗨拉詹。你有解决这个问题的方法吗?请告诉你是否明白。 我们必须维护一个数据源以避免重复 @RajanMaheshwari 你的代码在 github 上更新了吗? @BhaveshDhaduk 我不记得它是否更新了。很久以前我在学习这些东西时发布了这个问题 【参考方案1】:首先:
[collectionView dequeueReusableCellWithReuseIdentifier:@"MyCollectionViewCell" forIndexPath:indexPath]
总是返回一个视图,所以你不需要那个:
if(cell==nil)
cell=[[MyCollectionViewCell alloc]initWithFrame:CGRectMake(0, 0, collectionView.frame.size.width, collectionView.frame.size.height)];
因为它不会发生。
你真正的原因是你只有一个单元格用于所有 UITableView... 将 tableCell 保留为属性的想法来自哪里?
MyTableViewCell* tableViewCell;
您需要为每个 indexPath 分别创建一个单元格实例,现在您有一个显示多次的实例,这就是为什么在其中一个上更改集合视图页面会影响其他行 - 因为它是同一个对象(视图) .
消除该问题后,您需要记住元素将被重用 - 这意味着您的第一行实例,在它从屏幕上消失后,您将在第 5 行再次重用,因此在元素出列后,您需要将所有变量设置到该行。 您不能将变量保留在此行中,因为它将被重复使用,因此即使您有 100 行,您也将在整个表中重复使用大约 5-6 个实例(取决于行高)。
您需要保留重要的变量,这是在视图之外渲染每一行所必需的,并基于这些变量配置视图。
在您的情况下,您应该为每一行保留 pageControl 的页面索引 - 为此使用 NSDictionary 并为 UITableView 中的每个 indexPath 保留一个 NSNumber。 每当页面发生变化时,更新此 NSDictionary 中的值(默认为零)。 当您使用集合视图创建单元格时,请根据您在 NSDictionary 中为此 indexPath 的内容为 pageControl 设置适当的值
【讨论】:
我找不到你。我必须删除双端队列.. 行吗? 我已将我的项目附加为 github 链接。你能看看并找出我的错误吗..? 好的,现在我已经在单元格中为行 MyTableViewCell* tableViewCell=(MyTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell"];.. 但问题仍然存在 现在代码是 -(UITableViewCell*)tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath MyTableViewCell tableViewCell=(MyTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@ "MyTableViewCell"]; if(tableViewCell==nil) tableViewCell=[[MyTableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"MyTableViewCell"]; ....... 返回 tableViewCell; //问题依旧存在 抱歉迟到了..我必须维护一个数据源才能达到同样的效果..以上是关于滚动 UITableView 和 UICollectionView 的数据不正确的主要内容,如果未能解决你的问题,请参考以下文章
如何滚动uitableview和顶部的部分标题,可见并滚动到
使用 prefersLargeTitles 和 UITableView 平滑滚动