0

I have a custom UIViewcontroller and wanted to initialize and assign a custom UIView which I assigned to an IBOutlet before. I'm using a storyboard. Can anybody give me hints where to call the designated initializer of the custom UIView?

**MyCustomUIView.h**

@interface MyCustomUIView : UIView

@end

**MyCustomUIView.m**
@implementation MyCustomUIView 
- (id)initWithNumberOfHeaderRows:(NSUInteger)headerRowCount numberOfHeaderColumns:(NSUInteger)headerColumnCount frame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {

    }
    return self;
}
@end


**MyUIViewController.h**
@interface MyUIViewController : UIViewController
@property (weak, nonatomic) IBOutlet MyCustomUIView *myCustomUIView; // I wanna use this Outlet
@end

**MyUIViewController.m**
@implementation MyUIViewController 

@end

This was an abstract version of the used github source: https://github.com/mutualmobile/MMSpreadsheetView/blob/master/MMSpreadsheetView/MMSpreadsheetView.m

Moonstar
  • 247
  • 1
  • 4
  • 13

2 Answers2

1

You can call the constructor (initializer) of the custom view in viewDidLoad of the controller. Then, add it as a subview of the view of the controller.

Something like this:

- (void)viewDidLoad {
    ...
    MyCustomUIView *customView = [MyCustomUIView alloc] initWithNumberOfHeaderRows:0 numberOfHeaderColumns:0 frame:CGRectZero];
    [self.view addSubview:customView];
    ...    
}

UPDATED

I think you should create your custom view class something like this:

//MyCustomView.h
@interface MyCustomView : UIView

- (id)initWithNumberOfHeaderRows:(NSUInteger)numberOfHeaderRows numberOfHeaderColumns:(NSUInteger)numberOfHeaderColumns;

@property (readwrite, nonatomic) NSUInteger numberOfHeaderRows;
@property (readwrite, nonatomic) NSUInteger numberOfHeaderColumns;

@end

//MyCustomView.m
@implementation

- (void)setup {
    // Do custom stuffs here...
}

- (id)initWithNumberOfHeaderRows:(NSUInteger)numberOfHeaderRows numberOfHeaderColumns:(NSUInteger)numberOfHeaderColumns {
    self = [self initWithFrame:CGRectZero];
    if (self) {
        self.numberOfHeaderRows = numberOfHeaderRows;
        self.numberOfHeaderColumns = numberOfHeaderColumns;
    }
    return self;
}

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

- (id)init {
    self = [super init];
    if (self) {
        [self setup];
    }
    return self;
}

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

@end

Then in viewDidLoad:

- (void)viewDidLoad {
    ...
    // Assuming you have an IBOutlet property of MyCustomView class with a name 'customView'
    // That property must be hooked up from the xib/storyboard
    self.customView.numberOfHeaderRows = 1;
    self.customView.numberOfHeaderColumns = 1;
    self.customView.frame = self.view.bounds;
    ...
}

UPDATED 2

You may simply add a public method for setting number of header rows and columns in the custom view.

//MyCustomView.h
@interface MyCustomView : UIView

...
- (void)setNumberOfHeaderRows:(NSUInteger)rows numberOfHeaderColumns:(NSUInteger)columns; 
...

@end

//MyCustomView.m
@implementation MyCustomView

...
- (void)setNumberOfHeaderRows:(NSUInteger)rows numberOfHeaderColumns:(NSUInteger)columns {
    //Do the custom stuffs that you want...
}
...

@end

Then in viewDidLoad

- (void)viewDidLoad {
    ...
    [self.customView setNumberOfHeaderRows:10 numberOfHeaderColumns:4];
    ...
}

UPDATED 3

Based on the reference files that you've given, you can add methods in the DataSource:

    //MMSpreadsheetView.h
    @optional
    ...
    - (NSUInteger)spreadsheetViewNumberOfHeaderRows:(MMSpreadsheetView *)spreadsheetView;
    - (NSUInteger)spreadsheetViewNumberOfHeaderColumns:(MMSpreadsheetView *)spreadsheetView;
    ...

Then, in the implementation file:

//MMSpreadsheetView.m
...
- (void)setupWithNumberOfHeaderRows:(NSUInteger)rows numberOfHeaderColumns:(NSUInteger)columns {
    _scrollIndicatorInsets = UIEdgeInsetsZero;
    _showsVerticalScrollIndicator = YES;
    _showsHorizontalScrollIndicator = YES;
    _headerRowCount = headerRowCount;
    _headerColumnCount = headerColumnCount;

    if (headerColumnCount == 0 && headerRowCount == 0) {
        _spreadsheetHeaderConfiguration = MMSpreadsheetHeaderConfigurationNone;
    }
    else if (headerColumnCount > 0 && headerRowCount == 0) {
        _spreadsheetHeaderConfiguration = MMSpreadsheetHeaderConfigurationColumnOnly;
    }
    else if (headerColumnCount == 0 && headerRowCount > 0) {
        _spreadsheetHeaderConfiguration = MMSpreadsheetHeaderConfigurationRowOnly;
    }
    else if (headerColumnCount > 0 && headerRowCount > 0) {
        _spreadsheetHeaderConfiguration = MMSpreadsheetHeaderConfigurationBoth;
    }
    self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.backgroundColor = [UIColor grayColor];
    [self setupSubviews];
}

- (id)initWithNumberOfHeaderRows:(NSUInteger)headerRowCount numberOfHeaderColumns:(NSUInteger)headerColumnCount frame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        [self setupWithNumberOfHeaderRows:rows numberOfHeaderColumns:columns];
    }
    return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if (self) {
        NSUInteger rows = 0;
        NSUInteger columns = 0;
        if (self.dataSource && [self.dataSource respondsToSelector:@selector(spreadsheetViewNumberOfHeaderRows:)]) {
            rows = [self.dataSource spreadsheetViewNumberOfHeaderRows:self];
        }
        if (self.dataSource && [self.dataSource respondsToSelector:@selector(spreadsheetViewNumberOfHeaderColumns:)]) {
            columns = [self.dataSource spreadsheetViewNumberOfHeaderColumns:self];
        }
        [self setupWithNumberOfHeaderRows:rows numberOfHeaderColumns:columns];
    }
    return self;
}
...
mownier
  • 1,719
  • 2
  • 13
  • 27
  • Right. I did this before and it worked. Just wanted to know the other way around. After having assigned the custom class for my UIView of Type MyUIView over the interface builder. I want to initialize it with the designated initializer of MyUIView using the IBOutlet in the MyUIViewController. According to you I would have a MyUIView which has a subview which is a MyCustomView again... You got me? – Moonstar Apr 12 '14 at 14:33
  • I wanna this myCustomUIView = [MyCustomView alloc] initWithNumberOfHeaderRows: 1 numberOfHeaderColumns:1 frame:anyFrame.bounds.]; myCustomUIView is an IBOutlet of type MyUIView. – Moonstar Apr 12 '14 at 14:38
  • Thank you very much for the effort helping me. If I declared intance variables, I would have needed more because this initializer does more than simple stuff. Then I would need more for each setup :(. Therefore I wanted a solution combined with initWithCoder... But I kinda didn't. – Moonstar Apr 12 '14 at 15:18
  • I didn't noticed the 3rd one. I'll try it. Thank your very much again. – Moonstar Apr 12 '14 at 16:53
  • Ok the problem in this solution is that within initWithCoder the datasource is nil and therefore the datasource methods aren't invoked. – Moonstar Apr 13 '14 at 14:18
  • I think if you have a 'reload' public method where to reload your data source – mownier Apr 14 '14 at 07:49
1

Another option is to adopt the data source pattern for your view. For example, in MyCustomUIView.h:

@class MyCustomUIView;

@protocol MyCustomUIViewDataSource
- (NSInteger)numberOfHeadersInMyCustomUIView:(MyCustomUIView *)view;
- (NSInteger)numberOfHeaderColumnsInMyCustomUIView:(MyCustomUIView *)view;
@end

@interface MyCustomUIView : UIView

@property (nonatomic, strong) id<MyCustomUIViewDataSource> dataSource;

@end

In MyCustomUIView.m add:

- (void)setDataSource:(id<MyCustomUIViewDataSource>)dataSource {
    self.dataSource = dataSource;
    self.headerRowCount = [self.dataSource numberOfHeadersInMyCustomUIView:self];
    self.headerColumnsCount = [self.dataSource numberOfHeaderColumnsInMyCustomUIView:self];

    // Rearrange view with the new values
}

Then in your UIViewController:

- (void)viewDidLoad {
    [super viewDidLoad];
    self.myCustomUIView.dataSource = self;
}

- (NSInteger)numberOfHeadersInMyCustomUIView:(MyCustomUIView *)view {
    return 5;
}

- (NSInteger)numberOfHeaderColumnsInMyCustomUIView:(MyCustomUIView *)view {
    return 2;
}

You could even add a reload method in your custom view.

Matías R
  • 2,195
  • 1
  • 14
  • 12