I am looking to find out how to correctly subclass UIView
with a custom init method passing in parameters.
I have read the UIView
class reference documentation here: https://developer.apple.com/library/ios/documentation/uikit/reference/uiview_class/uiview/uiview.html
At present the UIView is being created in the UIViewController
and can be moved/refactored into its own subclass. Also at present the view is created completely in code and the frame is calculated by the constraints added to the view itself.
The documentation says the following
initWithFrame: - It is recommended that you implement this method. You can also implement custom initialization methods in addition to, or instead of, this method.
Question
As I do not create a frame as a starting point for the view / neither is it loaded from a XIB what is the correct process to subclass this?
Would this be correct:
-(id)init {
NSLog(@"%s",__PRETTY_FUNCTION__);
self = [super init];
if (self) {
// Init code
[self spmCustomInit];
}
return self;
}
-(void)spmCustomInit {
NSLog(@"%s",__PRETTY_FUNCTION__);
}
If this is is correct I need to further change this. When the view is being created it creates some subviews based on information. Also the layout is different based on a difficulty level.
Further question
How do I create a further custom init method which I pass in parameters?
For example if I created a method called
spmInitWithWord:(NSString *)word difficulty:(GameTurnDifficulty)difficulty
How is the standard init method then called. Would I then call this custom init when creating the view initially too? [[UICustomViewExample alloc] spmInitWithWord:testWord difficulty:turnDifficulty]
??
No, I would suggest a different approach. Write your init method to call super initWithFrame. That's the designated initializer for UIView. By calling it yourself, you assure that any OS setup that needs to take place gets invoked.
You can pass in CGRectZero as the frame if you need to, and then set the frame later.
Note that you should also plan to support initialization using initWithCoder. That's the method that gets called if you put your view into an XIB file or Storyboard.
What I do is to create a method doInitSetup, and put my custom initialization there. I then call that method from both initWithFrame and initWithCoder.
In your case, you could add properties for your custom settings, and if you put one of your views in an XIB/Storyboard, you could set those properties using user runtime attributes.
Using IB to design your forms is a good idea. I would counsel you to learn to use them. They make like easier and give you access to features that are all but impossible to use from code.
Your code might look like this:
- (id) initWithWord: (NSString *) theWord
{
self = [super initWithFrame: CGRectZero];
if (!self)
return nil;
[self doInitSetupWithWord: theWord];
return self;
}
- (void) doInitSetupWithWord: (NSString *) theWord
{
//Do whatever you need to do to set up your view.
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder: aDecoder];
if (!self) {
return nil;
}
[self doInitSetupWithWord: nil];
return self;
}
- (void) setWord: (NSString *) theWord
{
_theWord = theWord;
//If possible, set things up for the new word
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With