Question

I've constructed an UICollectionView in a storyboard and implemented all of its required data source and delegate methods in the view controller. In the storyboard, I checked the Section Header property on the collection view and set the header view's class to a subclass of UICollectionResusableView (in the storyboard).

From here, I dragged in two UI elements onto the header view via the storyboard--a label and a segmented control:

enter image description here

When the program is executed, the label appears in the header view of the collection view (with no actual code required), but the segmented control does not. However, when a segmented control is dragged onto a typical UIView, it displays and is manipulatable with no code required. Even when instantiated through code in an IBOutlet, the segmented control does not appear.

Why is the segmented control not visible on the collection view's header while it is in a typical UIView, and why does the label display without issue?

UPDATE

Here is the init method for the custom header view, in which I attempted adding the segmented control programmatically (as opposed to in the storyboard):

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        _segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"One", @"Two", nil]];
        [_segmentedControl setFrame:CGRectMake(0, 0, 100, 50)];
        [_segmentedControl addTarget:self action:@selector(segmentedControlChanged:) forControlEvents:UIControlEventValueChanged];
        [self addSubview:_segmentedControl];
    }
    return self;
}

As requested, here is the -[UICollectionReusableView viewForSupplementaryElementOfKind:] method in the main view controller:

- (UICollectionReusableView *)collectionView:(UICollectionView *)cv viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
    GalleryHeader *headerView = [cv dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];
    return headerView;
}
Was it helpful?

Solution

I'm not able to reproduce your storyboard problem, it works just fine for me when i add the segmented control by dragging it directly in the storyboard (with no code required). As for your alternative way of adding it programmatically, the problem here is that when a view is initialized from the storyboard (as it is in this case), the initWithCoder initializer method is used (not the initWithFrame initializer method). Hence, if you override that method, inserting the code in there, it should work:

-(id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if(self){
        _segmentedControl = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"One", @"Two", nil]];
        _segmentedControl.bounds = CGRectMake(0, 0, 100, 50);
        [_segmentedControl addTarget:self action:@selector(segmentedControlChanged:) forControlEvents:UIControlEventValueChanged];
        [self addSubview:_segmentedControl];
    }
    return self;
}

P.S. It doesnt affect this specific case, but you should just do:

GalleryHeader *headerView = [cv dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];

instead of:

GalleryHeader *headerView = [cv dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"HeaderView" forIndexPath:indexPath];

As it is the collection view that will ask for the right kind of view, you should worry about specifying it!

EDIT: The steps i followed to create the header from storyboard are:

  • Select the collection view and tick the box labelled Section Header

  • Select the newly created header and select the right class in the identity inspector

enter image description here

  • Give the header section a unique identifier

enter image description here

  • Drag the UI elements in the header in the storyboard (i also changed its background color)

enter image description here

  • Finally implement the collectionView:viewForSupplementaryElementOfKind:atIndexPath: method in your collection view's data source class
 -(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
          viewForSupplementaryElementOfKind:(NSString *)kind 
                                atIndexPath:(NSIndexPath *)indexPath
 {
     return [self.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"collectionViewHeader" forIndexPath:indexPath];
 }

Let me know if you can spot any difference between what you did and what I did!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top