-1

I want to use UIExpandableTableView - https://github.com/OliverLetterer/UIExpandableTableView#readme.

I've run into a problem because it's only initializer is initWithFrame:

#pragma mark - Initialization

- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style {
    if ((self = [super initWithFrame:frame style:style])) {
        self.maximumRowCountToStillUseAnimationWhileExpanding = NSIntegerMax;
        self.expandableSectionsDictionary = [NSMutableDictionary dictionary];
        self.showingSectionsDictionary = [NSMutableDictionary dictionary];
        self.downloadingSectionsDictionary = [NSMutableDictionary dictionary];
        self.animatingSectionsDictionary = [NSMutableDictionary dictionary];
    }
    return self;
}

I've been trying to initialize the tableView from Storyboard and realized the errors I'm seeing are because this initWithFrame is never being called and the NSMutableDictionaries aren't being initialized. How to solve this?

If not easily solvable I can just instantiate programmatically and go with initWithFrame, but besides wanting to use Storyboard, I'm also curious what a solution would be.


EDIT Here is how these properties and their ivars are declared in UIExpandableTableView. This is in the .h file:

@interface UIExpandableTableView : UITableView <UITableViewDelegate, UITableViewDataSource, NSCoding> {

@private id __UIExpandableTableView_weak _myDelegate; id __UIExpandableTableView_weak _myDataSource;

NSMutableDictionary *_expandableSectionsDictionary;     // will store BOOLs for each section that is expandable
NSMutableDictionary *_showingSectionsDictionary;        // will store BOOLs for the sections state (nil: not expanded, 1: expanded)
NSMutableDictionary *_downloadingSectionsDictionary;    // will store BOOLs for the sections state (nil: not downloading, YES: downloading)
NSMutableDictionary *_animatingSectionsDictionary;

NSInteger _maximumRowCountToStillUseAnimationWhileExpanding;

BOOL _onlyDisplayHeaderAndFooterViewIfTableViewIsNotEmpty;
UIView *_storedTableHeaderView;
UIView *_storedTableFooterView;

}

Here's the top of the .m file of UIExpandableTableView. T

@interface UIExpandableTableView ()

@property (nonatomic, retain) NSMutableDictionary *expandableSectionsDictionary;
@property (nonatomic, retain) NSMutableDictionary *showingSectionsDictionary;
@property (nonatomic, retain) NSMutableDictionary *downloadingSectionsDictionary;
@property (nonatomic, retain) NSMutableDictionary *animatingSectionsDictionary;

@property (nonatomic, retain) UIView *storedTableHeaderView;
@property (nonatomic, retain) UIView *storedTableFooterView;

- (void)downloadDataInSection:(NSInteger)section;

- (void)_resetExpansionStates;

@end
OdieO
  • 6,836
  • 7
  • 56
  • 88

4 Answers4

1

All you have to do is remove initWithFrame: and override initWithCoder: instead. This method will be called when an interface builder element reaches init to allow you to setup your dictionaries. And don't worry about eliminating the style and frame arguments because both of those cases will be handled from within interface builder.

- (id)initWithCoder:(NSCoder *)aDecoder
{
    if (self = [super initWithCoder:aDecoder]) {
        NSLog(@"%s",__PRETTY_FUNCTION__); // Proof of call
        self.maximumRowCountToStillUseAnimationWhileExpanding = NSIntegerMax;
        self.expandableSectionsDictionary = [NSMutableDictionary dictionary];
        self.showingSectionsDictionary = [NSMutableDictionary dictionary];
        self.downloadingSectionsDictionary = [NSMutableDictionary dictionary];
        self.animatingSectionsDictionary = [NSMutableDictionary dictionary];
    }
    return self;
}
Mick MacCallum
  • 129,200
  • 40
  • 280
  • 281
  • So this seems like an easy solution, but isn't it good practice in general to subclass third-party code instead of copying it and altering it? Am I wrong in thinking that? – OdieO May 31 '13 at 00:02
  • @SmoothAlmonds I was just demonstrating how to make the change, but you are correct, it would be better practice to make a subclass. – Mick MacCallum May 31 '13 at 00:13
1

you could subclass from UIExpandableTableView, and do

- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style {
    if (self = [super initWithFrame:frame style:style]) {
        [self configure];
    }
    return self;
}


-(id)initWithCoder:(NSCoder *)aCoder {
    if(self = [super initWithCoder:aCoder]){ 
        [self configure];
    }
   return self;
}


-(void) configure {
    self.maximumRowCountToStillUseAnimationWhileExpanding = NSIntegerMax;
    self.expandableSectionsDictionary = [NSMutableDictionary dictionary];
    self.showingSectionsDictionary = [NSMutableDictionary dictionary];
    self.downloadingSectionsDictionary = [NSMutableDictionary dictionary];
    self.animatingSectionsDictionary = [NSMutableDictionary dictionary];
}

Nibs and Storybord instantiation is don via initWithCoder:

Subcalssing allows you to use third-party code unpatched in this case.

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
  • So I was thinking of this as a solution, and tried it, however, I was getting errors with my properties. So UIExpandableTableView has those properties listed in the interface of the implementation file, as shown in the edit above. I get `property ... not found on object of type..` in the subclass. Is there a way to access those properties in my subclass? – OdieO May 30 '13 at 23:59
  • So there are private ivars declared in the .h file as well, which I've included in the edit. – OdieO May 31 '13 at 00:08
0

I'd do the following:

- (id)initWithFrame:(CGRect)frame style:(UITableViewStyle)style {
    if ((self = [super initWithFrame:frame style:style])) {
        [self setup];
    }
    return self;
}

- (void)awakeFromNib {
    [super awakeFromNib];
    [self setup];
}

- (void)setup {
    self.maximumRowCountToStillUseAnimationWhileExpanding = NSIntegerMax;
    self.expandableSectionsDictionary = [NSMutableDictionary dictionary];
    self.showingSectionsDictionary = [NSMutableDictionary dictionary];
    self.downloadingSectionsDictionary = [NSMutableDictionary dictionary];
    self.animatingSectionsDictionary = [NSMutableDictionary dictionary];
}
Bruno Koga
  • 3,864
  • 2
  • 34
  • 45
0

I think this is simplest solution...you don't have to worry about how the view controller is being initialized.

-(void)viewDidLoad
{
    [super viewDidLoad];
    self.maximumRowCountToStillUseAnimationWhileExpanding = NSIntegerMax;
    self.expandableSectionsDictionary = [NSMutableDictionary dictionary];
    self.showingSectionsDictionary = [NSMutableDictionary dictionary];
    self.downloadingSectionsDictionary = [NSMutableDictionary dictionary];
    self.animatingSectionsDictionary = [NSMutableDictionary dictionary];
}
JonahGabriel
  • 3,066
  • 2
  • 18
  • 28