Krueger
Krueger

Reputation: 484

EXC_BAD_ACCESS when dismissing modalViewController iOS5

I've been scratching my head for a long time now, trying to solve this problem. I've searched StackOverflow, and have found people asking for something that resembles my problem like this question and this question, but none of the answers given have helped me.

To explain the problem in detail:

  1. I've used Apple's Paging example to enable paging between view controllers

  2. The View hierachy is as follows: UIWindow -> UIScrollView (MainController) -> UIViewControllers.

    I use this code to create a delegate to the Viewcontroller containing the UISCrollview:

    if(page == 0)
    {
        ContractsViewController *controller = [viewControllers objectAtIndex:page];
    
        if ((NSNull *) controller == [NSNull null])
        {
            controller = [[ContractsViewController alloc] initWithNibName:@"ContractsView" bundle:nil];
            controller.delegate = self;
            [viewControllers replaceObjectAtIndex:page withObject:controller];
            [controller release];
        }
    
        // add the controller's view to the scroll view
        if (controller.view.superview == nil)
        {
            CGRect frame = scrollView.frame;
            frame.origin.x = frame.size.width * page;
            frame.origin.y = 0;
            controller.view.frame = frame;
            controller.view.tag = 0;
            [scrollView addSubview:controller.view];
    
        }
    }
    

The problem then occurs, when I try to present a modalviewcontroller from my ViewController inside the scrollview using the delegate. It works a few times, but then gives me a EXC_BAD_ACCESS. I've also tried posting a notification, and creating a listener in the MainController, to present it that way, but still the same problem.

When testing in iOS 4.3 everything works like a charm, but in iOS5 I get the issue.

I hope someone can help me get rid of this issue.

Thank you in advance.

Upvotes: 2

Views: 1318

Answers (4)

Krueger
Krueger

Reputation: 484

As a start thank you for all your answers! I've finally found the solution to the problem.

As mentioned in my question, I used Apple's Pagecontrol sample as a template for my project. This template has a rootViewController which has an XIB with a window containing an UIScrollview and a Pagecontrol.

The problem happened, when I was trying to present the ModalView from a UIViewController inside the scrollview. I wanted to use the delegate, to present it through the rootViewController, but found out that it was using the UIScrollview to present it.

The UIScrollView object was apperently not retained, so after a couple of dismisses I hit the EXC_BAD_ACCESS.

I then figured, that i needed an UIView in the rootViewController, and placed it in the bottom viewhierachy in the XIB, and connected it with the view of the rootViewController. After I did that, I could use [delegate present..] and [delegate dismiss..] in the UIViewController without the EXC_BAD_ACCESS.

Yay! :)

Upvotes: 1

JeremyP
JeremyP

Reputation: 86651

Try running the code with NSZombiesEnabled.

My guess is that the viewControllers object is either never initialised or is being released prematurely.

Also, there's this if (page == 0) wierdness:

if(page == 0) // <== only the first page ever gets the init code calling
{
    ContractsViewController *controller = [viewControllers objectAtIndex:page];

    if ((NSNull *) controller == [NSNull null])
    {
        // ** SNIP **

        [viewControllers replaceObjectAtIndex:page   // <<=== always 0
                                   withObject:controller];
        [controller release];
    }

    // ** SNIP **

}

Upvotes: 0

Ankit Srivastava
Ankit Srivastava

Reputation: 12405

I think I see your problem.. in the first if you release controller object and then you try to use it in the second if loop because of which you recieve this. release the controller object after both the if loops have passed.

EDIT:

try this code instead..

if(page == 0)
{
    ContractsViewController *controller = [viewControllers objectAtIndex:page];

    if ((NSNull *) controller == [NSNull null])
    {
        controller = [[[ContractsViewController alloc] initWithNibName:@"ContractsView" bundle:nil]autorelease];
        controller.delegate = self;
        [viewControllers replaceObjectAtIndex:page withObject:controller];
    }

    // add the controller's view to the scroll view
    if (controller.view.superview == nil)
    {
        CGRect frame = scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
        controller.view.frame = frame;
        controller.view.tag = 0;
        [scrollView addSubview:controller.view];

    }
}

Upvotes: 0

Sveinung Kval Bakken
Sveinung Kval Bakken

Reputation: 3824

I suggest removing your [controller release]; and adding an autorelease: controller = [[[ContractsViewController alloc] initWithNibName:@"ContractsView" bundle:nil] autorelease]; You don't own controller when it's returned from objectAtIndex:, so that way you could have the same behavior for both controllers, no releases.

Upvotes: 0

Related Questions