0
votes

I have attached my sample project with github and provided the link below

I have a table view and in that tableview the cell consists of a UICollectionView. This means that every cell can scroll horizontally upto a certain limit,lets say 5.

Both the tableView cell and collectionview cell have custom cell classes

The tableview cell has also a UIPageControl which will change when we will scroll the UICollectionViewCells horizontally

I managed to do this part of work but suppose I have scrolled the 2nd tableview cell's collectionview to 3rd Position and this repeats somewhat around on 9th tableview cell.
The 9th tableview cell also has the same data. But I havent set anything yet on 9th.
So this means the problem is of reusability and data in getting incorrect while scrolling.

My Code so far is

//ViewController.h
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout>
@property (weak, nonatomic) IBOutlet UITableView *tableView;

@end

Implementation Class

//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

Cells classes

//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

View is Something like

enter image description here

My concern is that whenever I make any change lets say on cell 1 on table viewcell and scroll the collection in it to lets say 2nd index, then this is re repeated whenever i scroll the complete table

NOTE: I have kept number of cells of table to 10 to see the repeated impact.
The Github link of my sample project is https://github.com/RajanMaheshwari/TableAndCollection

1
You have two ways to maintain Tableview state i.e. one is with datasource means maintain the state with model for each row that maintain the information for each view on it. Second, create the new cell like Grzegorz Krukowski explained in his answer below. But second one is costlier one. One suggestion for you is that move the collection view flow layout setup in awakefromnib method in tableview cell also move all the default set up code in awakefromnib. - Sandeep Ahuja
Hi Rajan. Did you got the solution for this issue? Please tell if you get that. - ashForIos
we have to maintain a data source in order to avoid duplication - Rajan Maheshwari
@RajanMaheshwari your code is updated with changes on github? - Bhavesh Dhaduk
@BhaveshDhaduk I don’t remember whether it’s updated or not. It was long back I posted this question when I was learning the things - Rajan Maheshwari

1 Answers

0
votes

First of all:

[collectionView dequeueReusableCellWithReuseIdentifier:@"MyCollectionViewCell" forIndexPath:indexPath]

always returns a view, so you don't need that:

if(cell==nil)
{
    cell=[[MyCollectionViewCell alloc]initWithFrame:CGRectMake(0, 0, collectionView.frame.size.width, collectionView.frame.size.height)];
}

since it's not gonna happen.

And the real reason for you is that you have only one cell for all UITableView... Where the idea of keeping tableCell as property comes from ?

    MyTableViewCell* tableViewCell;

You need to create a cell instance for each indexPath separately, right now you have one instance which is displayed several times, that's why changing collection view page on one of them is affecting other rows - since it's the same object (view).

After you remove that problem, you need to remember that elements will be reused - which means your first row instance, you be reused again on 5th row, after it dissapears from the screen, so after you dequeue the elements, you need to set all variables to this row. You cannot keep your variables inside this row, because it will be reused, so even though you have 100 rows, you will around 5-6 instances (depends on row height) that will be reused across whole table.

You need to keep important variables, necessary to render every row, outside of the views and configure views based on those.

In your case you should keep page index of pageControl for every row - use NSDictionary for that and keep a NSNumber for every indexPath in your UITableView. Whenever page is changing, update the value in this NSDictionary (defaults to zero). When you create a cell with collection view, set proper value to pageControl based on what you have in NSDictionary for this indexPath