0

Why does the following crash my app whenever this view is loaded?

-(void)loadView {
    UIButton *chooseSubjectButton = [[UIButton buttonWithType:UIButtonTypeDetailDisclosure] retain];
    [chooseSubjectButton addTarget:self action:@selector(chooseSubject) forControlEvents:UIControlEventTouchUpInside ];
    chooseSubjectButton.frame = CGRectMake(15.0f, 205.0f, 296.0f, 51.0f);
    [self.view addSubview:chooseSubjectButton];
}

Any help would be greatly appreciated.

Thanks!

EmptyStack
  • 51,274
  • 23
  • 147
  • 178
joshim5
  • 2,292
  • 4
  • 28
  • 40

7 Answers7

6

My guess is, your app is not crashing actually. It just keeps calling the loadView method repeatedly because you've missed to load the view. Call [super loadView] or create a view and assign it as self.view before you add anything to self.view. The convenient way would be to use [super loadView].

- (void)loadView {

    [super loadView];
    // Your Code Here
}

EDIT: This answer looks to be wrong. Please consider visiting Is it ok to call [super loadView]? as @Denis Vert pointed out in the comments.

EmptyStack
  • 51,274
  • 23
  • 147
  • 178
  • 2
    @joshim5 - I'm curious as to why did you consider this answer to be correct? The `-loadView` [documentation](http://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006926-CH3-SW1) clearly states that "You should never call this method directly". It also states that you should never invoke `super` in the implementation of `-loadView`. – octy May 27 '11 at 15:06
  • It seems I misclicked and chose this as the correct answer - I meant to choose yours ;). Sorry Simon :) EDIT: Nevermind - I did mean to choose Simon's - He pointed out that loadView was being called again and again - that's what fixed my problem and that's what I needed to know. – joshim5 May 30 '11 at 18:39
  • @EmptyStack "Your custom implementation of this method should not call super..." from Doc. I believe octy's version is correct ? correct me if i am wrong. – Tatvamasi May 28 '12 at 19:12
  • Wow, it's old but google lead me here:) If someone bumped into this answer, you should know it's not correct. Consider this one https://stackoverflow.com/questions/9569749/is-it-ok-to-call-super-loadview – Denis Vert Feb 11 '19 at 21:07
2

Your lack of [super loadView] as noted by @Simon prompts another question.

Are you loading this viewController with an associated .xib file? If so, you probably mean to be doing this in -viewDidLoad rather than -viewLoad.

Just a thought, because I've confused myself about that in the past.

Dan Ray
  • 21,623
  • 6
  • 63
  • 87
1

Ok, there is quite a bit of confusion in the answers already given here...

First, you're correct to not call [super loadView];, see - (void)loadView:

If you override this method in order to create your views manually, you should do so and assign the root view of your hierarchy to the view property. (The views you create should be unique instances and should not be shared with any other view controller object.) Your custom implementation of this method should not call super.

If you really mean to use loadView (i.e. creating your view programmatically, and not from a NIB), then in your implementation you must assign the view property of your controller.

Also, you do not need to retain your button the way you're using it, because you're adding it as a subview of your main view (your main view will own it after that).

Based on these considerations, your method would look like this:

    -(void)loadView {
        CGRect frame = [[UIScreen mainScreen] applicationFrame]; // adjust to your needs
        UIView *rootView = [[UIView alloc] initWithFrame:frame];

        UIButton *chooseSubjectButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
        chooseSubjectButton.frame = CGRectMake(15.0f, 205.0f, 296.0f, 51.0f);
        [chooseSubjectButton addTarget:self action:@selector(chooseSubject) forControlEvents:UIControlEventTouchUpInside];

        [rootView addSubview:chooseSubjectButton];

        self.view = rootView;
        [rootView release];
    }

Of course, if you use a NIB to define your root view, you need to override -viewDidLoad: for additional configuration.

Hope this helps.

octy
  • 6,525
  • 1
  • 28
  • 38
  • your suggestion about `[super loadView]` seems wrong. Please read the doc clearly. – EmptyStack May 28 '11 at 04:18
  • i think you did not get what the apples documentation has to offer please go through it again for clearing your concepts. you dont call the super loadview method it is called automatically by the view controller class; i think this is what you meant to say, because if you dont write the super loadView then in that case if you add the views like label, buttons etc then their will be no view present in which these controls can be added and ultimately you will see your application being crashed. – Radix May 28 '11 at 04:57
  • Thank you octy. Your explanation finally makes sense to me. I'm now going to join the "your custom implementation of this method should not call super" camp. – coco Nov 14 '11 at 17:31
0

You are getting an infinite loop because you are referencing self.view in loadView. When you call self.view, and self.view is nil, it'll cause loadView to be called again. Creating the loop.

If you call [super loadView] it will initialize self.view so you dont see the problem.

So, instantiate self.view yourself and you'll be fine.

Hope this helps.

Nate Lyman
  • 94
  • 5
0

Try placing that code in viewDidLoad. Init-codes can create an infinite stack trace. Though I'm not sure if creating that button might trigger the crash.

Anyone correct me if I'm wrong

See this: iPhone SDK: what is the difference between loadView and viewDidLoad?

Community
  • 1
  • 1
Joetjah
  • 6,292
  • 8
  • 55
  • 90
0
-(void)loadView 
{
[super loadView];
UIButton *chooseSubjectButton = [[UIButton buttonWithType:UIButtonTypeDetailDisclosure] retain];
[chooseSubjectButton addTarget:self action:@selector(chooseSubject) forControlEvents:UIControlEventTouchUpInside ];
chooseSubjectButton.frame = CGRectMake(15.0f, 205.0f, 296.0f, 51.0f);
[self.view addSubview:chooseSubjectButton];
}

Hope this helps

Radix
  • 3,639
  • 3
  • 31
  • 47
  • You shouldn't use [super loadView] – joshim5 May 27 '11 at 14:58
  • @joshim5, Why shouldn't `[super loadView]` be called? @Radix is correct. – EmptyStack May 28 '11 at 04:13
  • @jsohim5: more interested in looking for a comment or answer from you on why [super loadView] should not be called – Radix May 28 '11 at 04:45
  • Read what Octy wrote: Ok, there is quite a bit of confusion in the answers already given here... First, you're correct to not call [super loadView];, see - (void)loadView: If you override this method in order to create your views manually, you should do so and assign the root view of your hierarchy to the view property. (The views you create should be unique instances and should not be shared with any other view controller object.) Your custom implementation of this method should not call super. – joshim5 May 30 '11 at 18:37
  • 1
    @joshim5, Have you read the doc? Octy's answer about calling [super loadView] is wrong. Its completely alright to call [super loadView]. I`m confused about what confuses you guys. – EmptyStack May 31 '11 at 05:13
  • @joshim5: see i am a simple guy who understands simple terms so can you please demonstrate this that would be kind of you. Because i f you create the view programatically and don't call the super loadView in the loadView method then in that case you application crashes because their is no view present in which you can add your subviews like label, button, table etc, if you forget to add the super loadView method then the app crashes this is all i know. If you can provide some more data in simpler term then i would be pleased to know that – Radix May 31 '11 at 12:24
  • @joshim5:and rather than proving that octy is right why dont you do your part of the homework try to add a label via code and in the loadView don't add the [super loadView] and then see the magic for yourself i hope this should help you in clearing your concepts regarding the comments and answers from other developers. Do let me know if this works for you brother. – Radix May 31 '11 at 12:31
  • @Radix and @Simon: I am not the only one that understands the documentation that way, see: http://stackoverflow.com/questions/5288749/app-freeze-when-i-remove-super-loadview ; Also, do a search for "super loadView" on SO and check other answers. You're both right in that you *can* call `[super loadView]`. However, the documentation states you *shouldn't*. If you understand how a `UIViewController` initializes it's root view, you will understand that there is actually no point in calling `[super loadView]` at all in your own implementation. – octy May 31 '11 at 20:46
  • If you don't call `[super loadView]` your app will not crash – joshim5 May 31 '11 at 22:03
0

Just for anyone else reading this thread, Octy is correct in saying you should never call [super loadView]. I've read some debate on this page about it. Read the documentation posted in Octy's answer, on page 28 its clearly stated that you should not call this method. It's even explained why. Doing so will look for a nib using the default name (same as the classname). Even if this nib doesn't exist, it's a waste of processing power. Simply create a new UIView and set it as self.view. (see examples on this page)

Just wanted to make sure future readers knew this. Took me a while to figure it out.

paradigmatic
  • 40,153
  • 18
  • 88
  • 147
MGA
  • 3,711
  • 1
  • 21
  • 22