views:

298

answers:

3

Hello.

I'm developing an iPhone application that show the camera's view with this code:

-(void) displayAR {
    [rootViewController presentModalViewController:[self cameraController] animated:NO];
    [displayView setFrame:[[[self cameraController] view] bounds]];
}

And hide the camera's view with this code:

- (void) hideAR {
    [[self locationManager] stopUpdatingHeading];
    [[self locationManager] stopUpdatingLocation];

    [[self accelerometerManager] release];

    [rootViewController dismissModalViewControllerAnimated:YES];
}

When I call hideAR, I get an EXC_BAD_ACCESS with the following debugger screenshot:

alt text

Any advice?

UPDATE:

I've changed hideAR code with this and I'm getting the same error:

- (void) hideAR {

    [rootViewController dismissModalViewControllerAnimated:YES];
}

I've checked rootViewController and it isn't nil.

As you can see on debugger's screenshot, the last method called (the first on the stack) is: [UIWindowController transitionViewDidComplete:fromView:toView].

Maybe, there is something accessing camera´s view after it was dismissed.

SECOND UPDATE

The class containing these methods is:

@implementation AugmentedRealityController

@synthesize locationManager;
@synthesize accelerometerManager;
@synthesize displayView;
@synthesize centerCoordinate;
@synthesize scaleViewsBasedOnDistance;
@synthesize rotateViewsBasedOnPerspective;
@synthesize maximumScaleDistance;
@synthesize minimumScaleFactor;
@synthesize maximumRotationAngle;
@synthesize centerLocation;
@synthesize coordinates = coordinates;
@synthesize debugMode;
@synthesize currentOrientation;
@synthesize degreeRange;
@synthesize rootViewController;

@synthesize cameraController;

- (id)initWithViewController:(UIViewController *)vc {

    coordinates     = [[NSMutableArray alloc] init];
    coordinateViews = [[NSMutableArray alloc] init];
    latestHeading   = -1.0f;
    debugView       = nil;

    [self setRootViewController: vc];

    [self setDebugMode:NO];
    [self setMaximumScaleDistance: 0.0];
    [self setMinimumScaleFactor: 1.0];
    [self setScaleViewsBasedOnDistance: NO];
    [self setRotateViewsBasedOnPerspective: NO];
    [self setMaximumRotationAngle: M_PI / 6.0];

    CGRect screenRect = [[UIScreen mainScreen] bounds];

    [self setDisplayView: [[UIView alloc] initWithFrame: screenRect]];

    [self setCurrentOrientation:UIDeviceOrientationPortrait];
    [self setDegreeRange:[[self displayView] bounds].size.width / 12];

    [vc setView:displayView];

    [self setCameraController: [[[UIImagePickerController alloc] init] autorelease]];
    [[self cameraController] setSourceType: UIImagePickerControllerSourceTypeCamera];
    [[self cameraController] setCameraViewTransform: CGAffineTransformScale([[self cameraController] cameraViewTransform], 1.13f,  1.13f)];
    [[self cameraController] setShowsCameraControls:NO];
    [[self cameraController] setNavigationBarHidden:YES];
    [[self cameraController] setCameraOverlayView:displayView];

    CLLocation *newCenter = [[CLLocation alloc] initWithLatitude:37.41711 longitude:-122.02528];

    [self setCenterLocation: newCenter];
    [newCenter release];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(deviceOrientationDidChange:)
                                                 name: UIDeviceOrientationDidChangeNotification
                                               object:nil];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];   

    // Inicializa el gestor del GPS y el del acelerómetro.
    [self startListening];

    return self;
}

THIRD UPDATE

I've put some NSLog trace, and I see that displayAR is called after hideAR call. I also see that viewDidAppear method on rootViewController is also called after hideAR. Actually, viewDidAppear is calling displayAR.

Why is called viewDidAppear?

FOURTH UPDATE

I've found the line that is failing. This is the first line on displayAR:

[rootViewController presentModalViewController:[self cameraController] animated:NO];

Any ideas? rootViewController and cameraController aren't nil.

FITH UPDATE

If you want to reproduce my error:

I'm using nielswh's iPhone-AR-Toolkit (you can download it here).

You can modify the ARKitDemo example include it with the library and try to dismissModalView.

+1  A: 

Almost 100% of the time EXC_BAD_ACCESS is from a mistakenly released resource. Without seeing all your code there is no way to know for sure but my best guess is that accelerometerManager is nil

EDIT:

viewDidAppear is being called on the root view controller because it is now being presented again after the other view you had displayed was hidden.

EDIT 2:

From the look of your stack trace, something somewhere at one time registered for an animation callback. It's entirely possible that whatever that thing is, it's invalid now after showing/hiding different views and could have been released without you knowing it. Try to sniff out what it is that is listening for an animationDidStop callback, sorry I can't help more but without having all the code we are left with this shotgun debugging.

slf
No, see my question update.
VansFannel
how about rootViewController?
slf
its probably hte camereController...how to you initialize it?
Daniel
Neither. As you can see on debugger's screenshot, the last method called (the first on the stack) is: [UIWindowController transitionViewDidComplete:fromView:toView].Maybe, there is something accessing camera´s view after it was dismissed.
VansFannel
@Daniel: I 've added cameraController initialization.
VansFannel
are you performing any logic on "will hide" or "did hide", lots of times people forget those are firing
slf
I believe not. I've put some NSLog traces, and after calling hideAR, someone call displayAR again. When I find something, I'll tell you.
VansFannel
Is camera controller synthesized with a retain attribute?
Daniel
@Daniel: camera controller's property is defined as follows: `@property (nonatomic, retain) UIImagePickerController *cameraController`;
VansFannel
Probably I've found the error. After `hideAR`, `viewDidAppear` is called on `roorViewController`. I've updated my question.
VansFannel
viewDidAppear is called whenever the view reappears which is what is happening...the error is probably caused cuz of this...just to see if it is try establishing some control so the code inside the viewDidAppear method is only executed once and see if that stops crashing
Daniel
@Daniel: yes, viewDidAppear is my problem.
VansFannel
I've found the line that is throwing the exception, but I don't know why. I have updated my question with more details.
VansFannel
@slf: I have updated my question adding information about how to reproduce the error. I've modified the example, adding a UIButton, draw programatically, to dismiss the camera view. Maybe you can reproduce the error.
VansFannel
@VansFannel do you experience different results with this? http://github.com/zac/iphonearkit That is the original framework
slf
@slf: No, I have changed the entire solution. And now it works. Instead using a `presentModalViewController` to show the camera, now I'm using a ViewController that inherits from `UIImagePickerController`.
VansFannel
A: 

The crash is occurring deep in the API code. It really has to be an issue with either the modal view or the self.view (assuming self is a view controller.)

Are you doing anything to the controller's main view e.g myController.view? If you accidentally kill the non-modal view, when you return to it from the modal view you will get a Exec_Bad_Access.

I think this is likely because this:

[[self accelerometerManager] release];

... indicates you may not understand how manage properties. You never, ever release a retained property anywhere except the class' dealloc method. The synthesized accessors for properties are supposed to manage retention and if you release anywhere else you can easily make the instance think it has a property object it does not.

Check your controller code outside the dealloc for anything that looks like:

[self.view release];

If you find it, that is most likely your problem. Of course, any property that view refers to or needs that has been improperly released might cause the problem as well.

TechZen
No, I haven't found anything like this. I've updated my question, and I think the problem is that `viewDidAppear` on `rootViewController` is called after `hideAR` call.
VansFannel
I've found the line that is throwing the exception, but I don't know why. I have updated my question with more details.
VansFannel
A: 

Hi,

if you havent already solved this you could try using the instruments tool and enabling zombie detection. This has saved me a couple of times as it will highlight the exact line of code which is giving you the error (most of the time hehe)

Good luck

Jules

Jules
Thanks. I'm using NSZombieEnabled as environment variable (set to YES), but it doesn't work.
VansFannel
What do you mean when you say its not working?? Are you doing the following xcode>run>run with performance tool>object allocations??Then stop the execution (with the big red button) and click on the info button by object allocation and check enable zombie detection and record reference counts. Then click record and go through the sequence which crashes your app. When the bad access occurs it should highlight the line of code where the error is.Good luck again
Jules
Julian, thanks. I'm going to it.
VansFannel
I've found the line that is throwing the exception, but I don't know why. I have updated my question with more details.
VansFannel