Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why UIView calls both init and initWithFrame?

I noticed that when I override both init and initWithFrame: in UIView subclasses, both methods are called. Even though only one is call explicitly in my code:

TestViewController.m:

@implementation TestViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    View1 *view1 = [[View1 alloc] init];
    [self.view addSubview:view1];
}

@end

View1.m:

@implementation View1

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

- (id)init
{
    self = [super init];
    if (self)
    {
        NSLog(@"init");
    }
    return self;
}

@end

Console looks like this:

2013-10-17 12:33:46.209 test1[8422:60b] initWithFrame

2013-10-17 12:33:46.211 test1[8422:60b] init

Why is initWithFrame called before init?

like image 410
Sergey Avatar asked Oct 17 '13 09:10

Sergey


3 Answers

It's not an issue. In the case of UIView a [super init] calling will be automatically change to [super initWithFrame:CGRectZero] . So you have to maintain this code by keeping this in mind.

like image 184
manujmv Avatar answered Nov 15 '22 07:11

manujmv


The reason is that inside View1 initWithFrame: you call [super initWithFrame:]. UIView initWithFrame: calls [self init].

When you call a method inside a class, the method on the very subclass is called. So, when you call an instance method (e.g. init) on UIView it tries to call the init method on View1 (if it is implemented).

EDIT according to answer below: https://stackoverflow.com/a/19423494/956811

Let the view1 be an instance of View1.
The call hierarchy is:

   - [view1(View1) init] 

      - [view1(UIView) init] (called by [super init] inside View1)

        - [view1(View1) initWithFrame:CGRectZero] (called inside [view(UIView) init] )

           - [view1(UIView) initWithFrame:CGRectZero] (called by [super initWithFrame] inside View1) 
              - ...

           - NSLog(@"initWithFrame"); (prints "test1[8422:60b] initWithFrame")

      - NSLog(@"init"); (called inside [view1(View1) init] ; prints "test1[8422:60b] init")

Check inheritance in OOP.

http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming)

http://www.techotopia.com/index.php/Objective-C_Inheritance

like image 40
maros Avatar answered Nov 15 '22 08:11

maros


Below is the small description of both method which will clearly define why init will called after initWithFrame:-

What initWithFrame method do?

Initializes and returns a newly allocated NSView object with a specified 
frame rectangle. This method returns the initialize and allocated object. Once it 
returned the below init method will called automatically.

What init method do?

 Implemented by subclasses to initialize a new object (the receiver) immediately after 
 memory for it has been allocated.So this init method will called only when memory has 
 been allocated to the object by initwithFrame. 
like image 1
Hussain Shabbir Avatar answered Nov 15 '22 06:11

Hussain Shabbir