简体   繁体   中英

iPhone App crashing in loadView method when creating a UIButton

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!

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.

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.

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 (ie 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.

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.

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?

-(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

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM