开发者

Large UIScrollView with page flipping sometimes crashes

I have a UIScroll view that is kind of odd in the first place because you scroll to the end, and then you flip the page, and you can go back as well, but this is how the client wanted it. For some reason it sometimes crashes (more often on the actual iPad) and it does this without a crash log. I have a feeling it has to be memory related. Is there anyway of preventing this from crashing? Thanks.

#import "viewBookVC.h"
#import "switchVC.h"
#import "switchExVC.h"
#import "mainMenuAppDelegate.h"
#import "exGlobal.h"

@implementation ViewBookVC

UIScrollView *scroll;

UIButton *prevPageButton;
UIButton *nextPageButton;

UIImage *scrollImage;

UIImageView *BGview2;

NSMutableArray *BGList;

NSMutableArray *pagingEnabledArr;

int currentPage = 0;

int maxPages = 0;

// used to put a delay on the previous page touch detection
int prevNextPageDetectDelay = 45;

int prevNextPageDetectDelayCounter = 0;

int nextContentOffsetX; 



- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {

        currentPage = 0;

        maxPages = 0;

        prevNextPageDetectDelayCounter = 0;

        mainMenuAppDelegate *del = (mainMenuAppDelegate *)[[UIApplication sharedApplication] delegate];

        // page list
        BGList = [[NSMutableArray alloc] init];

        for(int i = 0; i < 31; i++) {
            NSString *img = [NSString stringWithFormat:@"Viewbook_%d.png", i];
            [BGList addObject:img];
        }


        maxPages = [BGList count];


        // scrolling rules for paging being enabled

        pagingEnabledArr = [[NSMutableArray alloc] init];
        [pagingEnabledArr addObject:@"YES"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"YES"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"YES"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"YES"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"NO"];
        [pagingEnabledArr addObject:@"YES"];
        [pagingEnabledArr addObject:@"YES"];


        timer_checkScrollPos = [[NSTimer scheduledTimerWithTimeInterval:.005
                                                                 target:self
                                                               selector:@selector(onTimer_checkScrollPos:)
                                                               userInfo:nil
                                                                repeats:YES] retain];

        /////////////
        //         //
        // SCROLL  //
        //         //
        /////////////

        //scroll view
        CGRect scrollContainer = CGRectMake(0, 0, 1024, 768);
        scroll = [[UIScrollView alloc] initWithFrame:scrollContainer];
        [scroll setBackgroundColor:[UIColor blackColor]];
        scroll.contentSize = CGSizeMake(1024, 722);

        scroll.showsHorizontalScrollIndicator = YES;
        scroll.bounces = NO;

        scroll.pagingEnabled = YES;

        [self addSubview:scroll];

        // get scroll offset
        NSLog(@"cOffset(A): %f", scroll.contentOffset.x);


        //image to use in scroll
        scrollImage = [UIImage imageNamed:@"Viewbook_0.png"];
        BGview2 = [[UIImageView alloc] initWithImage:(UIImage *)scrollImage];
        BGview2.frame = CGRectMake(0, 23, 1024, 722);


        [scroll addSubview:BGview2];


        //back button [prev button height was compensated for this button to work]

        CGRect backBTNFrame = CGRectMake(10, 30, 140, 52); 
        UIButton * viewbook_backButton = [[UIButton alloc] init];
        viewbook_backButton.frame = backBTNFrame;
        UIImage *viewbook_backButtonIMG = [UIImage imageNamed:@"SHIP_button_back.png"];
        [viewbook_backButton setImage:viewbook_backButtonIMG forState:UIControlStateNormal];
        viewbook_backButton.backgroundColor = [UIColor clearColor];
        [self addSubview:viewbook_backButton];

        [viewbook_backButton addTarget:self 
                                action:@selector(kill_timers)
                      forControlEvents:UIControlEventTouchUpInside];    

        [viewbook_backButton addTarget:del.switchVC 
                                action:@selector(gotoMain)
                      forControlEvents:UIControlEventTouchUpInside];    


        [viewbook_backButton release];





        //prev button
        CGRect prevPageButtonFrame = CGRectMake(0, 70, 312, 698);
        prevPageButton = [[UIButton alloc] init];
        prevPageButton.frame = prevPageButtonFrame;
        prevPageButton.backgroundColor = [UIColor clearColor];
        [self addSubview:prevPageButton];

        [prevPageButton addTarget:self 
                           action:@selector(prevPage:)
                 forControlEvents:UIControlEventTouchUpInside]; 


        //next button
        CGRect nextPageButtonFrame = CGRectMake(712, 0, 312, 768);
        nextPageButton = [[UIButton alloc] init];
        nextPageButton.frame = nextPageButtonFrame;
        nextPageButton.backgroundColor = [UIColor clearColor];
        [self addSubview:nextPageButton];

        [nextPageButton addTarget:self 
                           action:@selector(nextPage:)
                 forControlEvents:UIControlEventTouchUpInside]; 



    }
    return self;
}   


-(void) onTimer_checkScrollPos:(NSTimer*)timer {

    if(currentPage!=0){
        nextContentOffsetX = 750;
    }else{
        nextContentOffsetX = 0;
    }

    //NSLog(@"cOffset(A): %f", scroll.contentOffset.x);
    if(scroll.contentOffset.x >= nextContentOffsetX){
        nextPageButton.hidden = NO;
    }else{
        nextPageButton.hidden = YES;
    }

    if(scroll.contentOffset.x <= 274){
        prevPageButton.hidden = NO;
    }else{
        prevPageButton.hidden = YES;
    }

    prevNex开发者_开发技巧tPageDetectDelayCounter += 1;
}


- (void)nextPage:(id)sender {

    if(currentPage!=0){
        nextContentOffsetX = 750;
    }else{
        nextContentOffsetX = 0;
    }

    if(scroll.contentOffset.x >= nextContentOffsetX & prevNextPageDetectDelayCounter>=prevNextPageDetectDelay){

        prevNextPageDetectDelayCounter = 0;

        currentPage+=1;

        if(currentPage >= maxPages){
            currentPage = 0;
        }

        if(currentPage!=0){
            scroll.contentSize = CGSizeMake(2048, 722);
            BGview2.frame = CGRectMake(0, 23, 2048, 722);
        }else{
            scroll.contentSize = CGSizeMake(1024, 722);
            BGview2.frame = CGRectMake(0, 23, 1024, 722);           
        }

        [UIView beginAnimations:@"flipping view" context:nil];
        [UIView setAnimationDuration:0.8];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp
                               forView:scroll
                                 cache:YES];
        [scroll setHidden:NO];
        [UIView commitAnimations];

        if([pagingEnabledArr objectAtIndex:currentPage]==@"YES"){
            scroll.pagingEnabled = YES;
        }else{
            scroll.pagingEnabled = NO;
        }


        BGview2.image = [UIImage imageNamed:[BGList objectAtIndex:currentPage]];

        // set scroll offset
        [scroll setContentOffset:CGPointMake(0,0) animated:NO];

    }
}

- (void)prevPage:(id)sender {
    if(scroll.contentOffset.x <= 274 & prevNextPageDetectDelayCounter>=prevNextPageDetectDelay){

        prevNextPageDetectDelayCounter = 0;

        currentPage-=1;

        if(currentPage < 0){
            currentPage = maxPages-1;
        }

        if(currentPage!=0){
            scroll.contentSize = CGSizeMake(2048, 722);
            BGview2.frame = CGRectMake(0, 23, 2048, 722);
        }else{
            scroll.contentSize = CGSizeMake(1024, 722);
            BGview2.frame = CGRectMake(0, 23, 1024, 722);           
        }

        [UIView beginAnimations:@"flipping view" context:nil];
        [UIView setAnimationDuration:0.8];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
        [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown
                               forView:scroll
                                 cache:YES];
        [scroll setHidden:NO];
        [UIView commitAnimations];

        if([pagingEnabledArr objectAtIndex:currentPage]==@"YES"){
            scroll.pagingEnabled = YES;
        }else{
            scroll.pagingEnabled = NO;
        }

        BGview2.image = [UIImage imageNamed:[BGList objectAtIndex:currentPage]];

        // set scroll offset
        [scroll setContentOffset:CGPointMake(0,0) animated:NO];

    }
}

-(void) kill_timers{
    NSLog(@"kill viewbook timer");

    [timer_checkScrollPos invalidate];
    timer_checkScrollPos = nil; 

}

- (void)dealloc {

    [scroll release];

    [BGview2 release];

    [BGList release];

    [pagingEnabledArr release];

    [prevPageButton release];
    [nextPageButton release];

    [timer_checkScrollPos invalidate];
    [timer_checkScrollPos release];

    [super dealloc];
}

@end


This does sound like a memory management issue. I suspect that you are loading all of the content into memory although you only display one or two pages at a single time. I suggest using Core Data or XML to load only the data you absolutely need at any given time.

As far as the device being less stable than the simulator, you should note that the simulator is not an emulator. The simulator uses the memory in your Mac and does not have the memory limitations of your iPad.

To debug this, you have a few options:

  • Try hooking up an iPad to your Mac and watch the console (Cmd+Shift+R). You will see a warning when your app gets a memory warning. A level 1 is often followed by a level 2 which is often followed by a crash. This could help substantiate the existence of an existing problem.

  • Run your app using the Allocations Instrument to track what could be causing the app to allocate so much memory. The Leaks instrument will help you find memory leaks.

  • Take advantage of a nifty feature in Xcode called "Build and Analyze". It's pretty good at finding memory leaks. (Build -> Build and Analyze)

Between leaking memory and allocating memory that the system doesn't have to give you, you have probably cause for your crashes.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜