0

I have some problem when trying to implement UICollectionView with custom cell inside custom cell in tableView. I have custom table view cell which works fine, showing my label as I want.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
    TemperatureTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath: indexPath];
    Node *node = [[Node alloc] init];
    if(_nodes != nil){
        node = [_nodes objectAtIndex:indexPath.row];
        if(_tempSensorsDictionary.count > 0){
            NSArray *allSensors = [_tempSensorsDictionary objectForKey:node.number];
            TemperatureSensor *ts = allSensors[0];
            if(node.name != nil && ![node.name  isEqual: @""]){
                cell.unitNameLabel.text = node.name;
            } else {
                cell.unitNameLabel.text = node.number;
            }
            cell.collection = [_tempSensorsDictionary objectForKey:node.number];
        }
    }
    return cell;
}

I have set up CollectionView background to gray colour and I can see this "box". So I guess that CollectionView is initialised properly in my TemperatureTaleViewCell class where I putted:

@implementation TemperatureTableViewCell
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

    if (!(self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) return nil;

    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    flowLayout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
    [flowLayout setItemSize:CGSizeMake(50, 50)];
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    self.collectionView = [[CollectionView alloc] initWithFrame: CGRectZero collectionViewLayout:flowLayout];
    [self.collectionView registerClass:[TemperatureItemCollectionViewCell class] forCellWithReuseIdentifier:@"TemperatureItemCollectionCell"];
    self.collectionView.showsHorizontalScrollIndicator = NO;
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;

    [self.collectionView reloadData];
    [self.contentView addSubview:self.collectionView];
    return self;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return 2;
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    TemperatureItemCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"TemperatureItemCollectionCell" forIndexPath:indexPath];
    cell.tempValTempCollViewCell.text = @"21oC";
    cell.backgroundColor = [UIColor redColor];

    return cell;

}
@end

But then my table view looks like this:

enter image description here

What is wrong in my code and where is wrong direction?

Micgal
  • 133
  • 1
  • 1
  • 11

2 Answers2

2

Need to reload collection view data inside tableview cellForRowAtIndexPath method.

-(void)tableView:(UITableView *)tableView willDisplayCell:(CategoryCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    [cell setCollectionViewDelegate:self indexPath:indexPath];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath {
    TemperatureTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath: indexPath];
    Node *node = [[Node alloc] init];
    if(_nodes != nil){
        node = [_nodes objectAtIndex:indexPath.row];
        if(_tempSensorsDictionary.count > 0){
            NSArray *allSensors = [_tempSensorsDictionary objectForKey:node.number];
            TemperatureSensor *ts = allSensors[0];
            if(node.name != nil && ![node.name  isEqual: @""]){
                cell.unitNameLabel.text = node.name;
            } else {
                cell.unitNameLabel.text = node.number;
            }
            cell.collection = [_tempSensorsDictionary objectForKey:node.number];

            //Reload collection view data
            [cell.collectionView reloadData];
        }
    }
    return cell;
}

Use awakeFromNib method insted of table view initWithStyle method.

- (void)awakeFromNib
{
    [super awakeFromNib];
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    flowLayout.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
    [flowLayout setItemSize:CGSizeMake(50, 50)];
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    self.collectionView = [[CollectionView alloc] initWithFrame: CGRectZero collectionViewLayout:flowLayout];
    [self.collectionView registerClass:[TemperatureItemCollectionViewCell class] forCellWithReuseIdentifier:@"TemperatureItemCollectionCell"];
    self.collectionView.showsHorizontalScrollIndicator = NO;
    self.collectionView.dataSource = self;
    self.collectionView.delegate = self;

    [self.contentView addSubview:self.collectionView];
}

Set delegate of collection view inside TemperatureTaleViewCell class

- (void)setCollectionViewDelegate:(id)dataSourceDelegate indexPath:(NSIndexPath *)indexPath
{
    self.collectionView.delegate = dataSourceDelegate;
}
Rahul Mayani
  • 3,761
  • 4
  • 25
  • 40
  • Unfortunately didn't help. Reload is done in CustomCell init method. – Micgal Nov 15 '17 at 12:06
  • This method works as expected as well as another one provided in comments. Which way is better and what is the difference? – Micgal Nov 15 '17 at 12:29
1

As I can see, you designed your TemperatureTaleViewCell via XIB/storyboard, and you create the cell via

[tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath: indexPath];

It's ok so far, but you're setting your collectionView's delegate and dataSource inside initWithStyle, which will not be called in this case. So your collection view's delegate and datasource methods will not be called.

hoang Cap
  • 704
  • 6
  • 18
  • Please read this document carefully and update your answer https://developer.apple.com/documentation/uikit/uitableview/1614891-dequeuereusablecellwithidentifie – trungduc Nov 15 '17 at 11:54
  • **If you registered a class for the specified identifier and a new cell must be created, this method initializes the cell by calling its initWithStyle:reuseIdentifier: method.** – trungduc Nov 15 '17 at 11:54
  • So should I just insert if(cell == nil) { cell = [[TemperatureTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; } after TemperatureTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath: indexPath]; ?? – Micgal Nov 15 '17 at 12:06
  • @Micgal for initialization, you are doing right way. Don't insert it. – trungduc Nov 15 '17 at 12:16
  • @trungduc: Nah, if I don't register the cell's class (via code) and just add the cell to my UITableView directly on Xib/storyboard, the method initWithStyle:reuseIdentifier will not be called by dequeueReusableCellWithIdentifier. – hoang Cap Nov 15 '17 at 12:16
  • @hoangCap if you do it, you will got crash instead of not calling method ;) – trungduc Nov 15 '17 at 12:17
  • @Micgal: You can just right-click on your collection view, then connect its delegate and dataSource to your TemperatureTableViewCell on the storyboard/xib – hoang Cap Nov 15 '17 at 12:18
  • @trungduc seems that initWithStyle is being called, as stopping the app when put there breakpoint. – Micgal Nov 15 '17 at 12:21
  • @Micgal of course, i said it in my above comment which is bold ;) – trungduc Nov 15 '17 at 12:23
  • Not to be rude here, but as you can see from my screenshot, initWithStyle is never called, configureCellForEvent is a method called after the cell is created. And I'm using storyboard to design my cell https://monosnap.com/file/ZCFgre0x6h32doFPeC27vf4hRmfgCR – hoang Cap Nov 15 '17 at 12:25
  • @trungduc Yep, you're right. Sorry. So seems better, if connected the dataSource from collectionView to TemperatureTableViewCell on storyboard. Is it the same what done in the second answer in code? Sorry for my problems with understand – Micgal Nov 15 '17 at 12:28
  • @trungduc sorry, my mistake. – Micgal Nov 15 '17 at 12:43
  • @hoangCap take a look at this link https://stackoverflow.com/questions/25826383/when-to-use-dequeuereusablecellwithidentifier-vs-dequeuereusablecellwithidentifi and you will know why you are wrong and why i said that you will got crash instead of not calling method ;) – trungduc Nov 15 '17 at 12:56