views:

60

answers:

1

App only crashes the first time i rotate my phone (EXC_BAD_ACCESS). Anytime after its all gravy. It only crashes on device too. Simulator everything is good.

#import "ImageViewController.h"
#define degreesToRadian(x) (M_PI * (x) / 180.0)
#define ZOOM_VIEW_TAG 100
#define ZOOM_STEP 1.5

@interface ImageViewController (UtilityMethods)
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
@end

@implementation ImageViewController
@synthesize imageView,url, enableLandscapeOrientation;

/*
 // The designated initializer.  Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        // Custom initialization
    }
    return self;
}
*/


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];

    // set up main scroll view
    imageScrollView = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
    [imageScrollView setBackgroundColor:[UIColor blackColor]];
    [imageScrollView setDelegate:self];
    [imageScrollView setBouncesZoom:YES];
    [[self view] addSubview:imageScrollView];

    // add touch-sensitive image view to the scroll view
    imageView = [[AsyncImageView alloc]initWithFrame:[self.view bounds]];
    if (enableLandscapeOrientation) {
        imageView.showGhost = YES;
    }
    [imageView loadImageFromURL:self.url];
    [imageView setTag:ZOOM_VIEW_TAG];
    [imageView setUserInteractionEnabled:YES];
    [imageScrollView setContentSize:[imageView frame].size];
    [imageScrollView addSubview:imageView];
    [imageView release];

    UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
    UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)];

    [doubleTap setNumberOfTapsRequired:2];
    [twoFingerTap setNumberOfTouchesRequired:2];

    [imageView addGestureRecognizer:singleTap];
    [imageView addGestureRecognizer:doubleTap];
    [imageView addGestureRecognizer:twoFingerTap];

    [singleTap release];
    [doubleTap release];
    [twoFingerTap release];

    // calculate minimum scale to perfectly fit image width, and begin at that scale
    float minimumScale = [imageScrollView frame].size.width  / [imageView frame].size.width;
    [imageScrollView setMinimumZoomScale:minimumScale];
    [imageScrollView setMaximumZoomScale:4.0f];
    //[imageScrollView setZoomScale:minimumScale];

    //[imageScrollView setMinimumZoomScale:0.5f];
    //[imageScrollView setMaximumZoomScale:2.0f];



    //[self.imageView loadImageFromURL:self.url];
}



// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

    if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||interfaceOrientation == UIInterfaceOrientationLandscapeRight) {

        imageScrollView.frame = CGRectMake(0,0,480,300); //self.view.bounds;
        imageView.frame = CGRectMake(0,0,480,300); //self.view.bounds;
    }
    else {
        imageScrollView.frame = CGRectMake(0,0,320,460); 
        imageView.frame = CGRectMake(0,0,320,460); 
    }


    //return (interfaceOrientation == UIInterfaceOrientationPortrait);
    if (enableLandscapeOrientation) {
        [[self navigationController] setNavigationBarHidden:UIInterfaceOrientationIsLandscape(interfaceOrientation) animated:YES];
        return YES;
    }
    else {
        return NO;
    }
}


- (void)dealloc {
    [imageView release];imageView=nil;
    [url release];url=nil;
    [super dealloc];
}

#pragma mark UIScrollViewDelegate methods

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    return [imageScrollView viewWithTag:ZOOM_VIEW_TAG];
}

/************************************** NOTE **************************************/
/* The following delegate method works around a known bug in zoomToRect:animated: */
/* In the next release after 3.0 this workaround will no longer be necessary      */
/**********************************************************************************/
- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
    [scrollView setZoomScale:scale+0.01 animated:NO];
    [scrollView setZoomScale:scale animated:NO];
}

#pragma mark Utility methods

- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center {

    CGRect zoomRect;

    // the zoom rect is in the content view's coordinates. 
    //    At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
    //    As the zoom scale decreases, so more content is visible, the size of the rect grows.
    zoomRect.size.height = [imageScrollView frame].size.height / scale;
    zoomRect.size.width  = [imageScrollView frame].size.width  / scale;

    // choose an origin so as to get the right center.
    zoomRect.origin.x    = center.x - (zoomRect.size.width  / 2.0);
    zoomRect.origin.y    = center.y - (zoomRect.size.height / 2.0);

    return zoomRect;
}

- (void)handleSingleTap:(UIGestureRecognizer *)gestureRecognizer {
    // single tap does nothing for now
}

- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer {
    // double tap zooms in
    float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
    [imageScrollView zoomToRect:zoomRect animated:YES];
}

- (void)handleTwoFingerTap:(UIGestureRecognizer *)gestureRecognizer {
    // two-finger tap zooms out
    float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
    [imageScrollView zoomToRect:zoomRect animated:YES];
}




@end
+1  A: 

In viewDidLoad you allocate the imageView and at the end you deallocate it, so the retain count of imageView is 0. imageView has been deallocated, and that's why you receive a EXC_BAD_ACCESS as soon as you want to access imageView the next time. You put the [imageView dealloc] out of your viewDidLoad method and everything should work fine.

And just another thing I noticed: You forgot to deallocate the scroll view in -(void)dealloc.

burki
so basically don't release imageView in dealloc() because im already releasing it in viewDidLoad?
Sheehan Alam
You have to release imageView ONLY in dealloc().
burki