Iphone 当我第一次旋转手机时,应用程序崩溃

Iphone 当我第一次旋转手机时,应用程序崩溃,iphone,objective-c,cocoa-touch,memory,uiview,Iphone,Objective C,Cocoa Touch,Memory,Uiview,应用程序仅在我第一次旋转手机时崩溃(EXC_BAD_ACCESS)。任何时候都可以。它也只会在设备上崩溃。一切都很好 #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)zoom

应用程序仅在我第一次旋转手机时崩溃(EXC_BAD_ACCESS)。任何时候都可以。它也只会在设备上崩溃。一切都很好

#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

viewdiload
中分配
imageView
并在最后取消分配,因此
imageView
的保留计数为0
imageView
已解除分配,这就是为什么您希望下次访问
imageView
时会收到
EXC\u BAD\u访问权限。您将
[imageView dealloc]
viewDidLoad
方法中删除,一切都会正常工作


我注意到的另一件事是:您忘了在
-(void)dealloc

中取消分配滚动视图,也忘了在初始化imageView和imageScrollViewfull代码的地方发布。崩溃记录在崩溃日志中,除了EXC_BAD_access之外没有可读的数据不是答案,而是
[imageView release]是一个bug,因为您还调用了
[imageView release]在dealloc中<代码>imageScrollView
也被泄露。您应该在viewDidUnload和dealloc中释放imageScrollView。前者是因为您在viewDidLoad中创建它,后者是因为viewDidUnload不会被调用,除非视图在ImageViewController的生命周期内卸载。重要提示:当您在viewDidUnload中释放它时,请将其设置为nil,否则dealloc中的释放可能会对无效引用调用release(如果调用了viewDidUnload)。因此,基本上不要在dealloc()中释放imageView,因为我已经在viewDidLoad中释放了它。您必须仅在dealloc()中释放imageView。