Search code examples
iosobjective-cdelegatesuicollectionviewsubclassing

Override delegate and datasource setters in UICollectionView subclass


I created a subclass of UICollectionView and in that subclass I want to override setters of dataSource and delegate properties.

It uses another segmentSelectionDelegate and segmentDataSource properties (which can be set by caller) to populate the data. I want to disallow setting original dataSource and delegate properties by the caller because subclass itself is the dataSource and delegate.

How can I do that?

Below is what I did but it's throwing an error : Data source is not set.

Interface file:

@class ZISegmentCollectionView;

@protocol ZISegmentCollectionViewDelegate <NSObject>

-(void)segmentCollectionView:(ZISegmentCollectionView *)collectionView didSelectSegmentWithName:(NSString *)segmentName;

@end

@protocol ZISegmentCollectionViewDataSource <NSObject>

-(NSUInteger)segmentCollectionView:(ZISegmentCollectionView *)collectionView badgeCountForSegment:(NSString *)segmentName;
-(NSString *)segmentCollectionView:(ZISegmentCollectionView *)collectionView nameForSegmentAtIndexPath:(NSIndexPath *)indexPath;
-(NSUInteger)numberOfSegmentsInSegmentCollectionView:(ZISegmentCollectionView *)collectionView;

@end

@interface ZISegmentCollectionView : UICollectionView

@property(nonatomic, readonly) NSString * selectedSegmentName;
@property(nonatomic, weak) id<ZISegmentCollectionViewDelegate> segmentSelectionDelegate;
@property(nonatomic, weak) id<ZISegmentCollectionViewDataSource> segmentDataSource;

@end

I synthesised delegate and dataSource properties in UICollectionView subclass:

@synthesize dataSource = _dataSource;
@synthesize delegate = _delegate;

Wrote setters like:

-(void)setDataSource:(id<UICollectionViewDataSource>)dataSource
{
    if (dataSource == self) {
        _dataSource = dataSource;
    }
}

-(void)setDelegate:(id<UICollectionViewDelegate>)delegate
{
    if (delegate == self) {
        _delegate = delegate;
    }
}

Solution

  • What you did by synthesizing the properties in your subclass is create new instance variables. When the superclass code checks if the data source is set, the answer is no, because its instance variable is still nil.

    Drop the synthesize statements, because you will be implementing the setter anyway (and you don't need to provide a getter).

    In your overriding setter, do nothing.

    To set the actual data source, invoke [super setDatasource:self].