Hello,
I'm making a interactive book that consists of about 30 pages, each being represented by a separate UIViewController subclass with a XIB for user interface. There are animations, sounds and interactive elements on most of the pages. I'd like to know what is the best practise in making a interactive application like this.
My PageController class is responsible for all the initialization and handling page changes. It creates a UIScrollView that displays the pages. In order to use as less memory as needed, I decided to store in memory a maximum amount of 3 pages at a time. I'm using 3 UIViewControllers - pagePrevious, pageCurrent and pageNext. Here is my code for the UIScrollView's scrolling part:
Code:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
int newPage = scrollView.contentOffset.x / self.view.frame.size.height + 1;
if(newPage > currentPage) {
if(pagePrevious != nil) {
[pagePrevious.view removeFromSuperview];
[pagePrevious release];
}
pagePrevious = pageCurrent;
pageCurrent = pageNext;
if(newPage < PAGE_COUNT) {
NSString *pageClass;
if(newPage < 9) {
pageClass = [NSString stringWithFormat:@"Page0%d", (newPage + 1)];
} else {
pageClass = [NSString stringWithFormat:@"Page%d", (newPage + 1)];
}
pageNext = [[NSClassFromString(pageClass) alloc] init];
pageNext.view.frame = CGRectMake(self.view.frame.size.height * newPage, 0, self.view.frame.size.height, self.view.frame.size.width);
[scrollView addSubview:pageNext.view];
}
} else if(newPage < currentPage) {
if(pageNext != nil) {
[pageNext.view removeFromSuperview];
[pageNext release];
}
pageNext = pageCurrent;
pageCurrent = pagePrevious;
if(newPage > 1) {
NSString *pageClass;
if(newPage < 11) {
pageClass = [NSString stringWithFormat:@"Page0%d", (newPage - 1)];
} else {
pageClass = [NSString stringWithFormat:@"Page%d", (newPage - 1)];
}
pagePrevious = [[NSClassFromString(pageClass) alloc] init];
pagePrevious.view.frame = CGRectMake(self.view.frame.size.height * (newPage - 2), 0, self.view.frame.size.height, self.view.frame.size.width);
[scrollView addSubview:pagePrevious.view];
}
}
currentPage = newPage;
}
Unfortunately, this code gives me some bad access issues. For example, when I change pages like this: 1 -> 2 -> 1 -> 2 -> 1, I get a blank screen instead of page 1 and then, when I slide to page 2, the application crashes (EXC_BAD_ACCESS). Having "[pagePrevious release]" and "[pageNext release]" removed solves the problem with the crashes but not with the blank screens. Having removed removeFromSuperview lines solves it entirely, but I'm aware of the fact that those viewControllers still reside in memory which was clearly not my point.
I don't really know what exactly is wrong with this code. My initialization method of PageController looks like:
Code:
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self) {
pageScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.height, self.view.frame.size.width)];
pageScrollView.pagingEnabled = YES;
pageScrollView.scrollEnabled = YES;
pageScrollView.showsVerticalScrollIndicator = NO;
pageScrollView.showsHorizontalScrollIndicator = NO;
pageScrollView.bounces = NO;
pagePrevious = nil;
pageCurrent = [[Page01 alloc] init];
pageNext = [[Page02 alloc] init];
[pageCurrent.view setFrame:CGRectMake(0, 0, self.view.frame.size.height, self.view.frame.size.width)];
[pageNext.view setFrame:CGRectMake(self.view.frame.size.height, 0, self.view.frame.size.height, self.view.frame.size.width)];
[pageScrollView addSubview:pageCurrent.view];
[pageScrollView addSubview:pageNext.view];
pageScrollView.contentSize = CGSizeMake(self.view.frame.size.height * PAGE_COUNT, self.view.frame.size.width);
[pageScrollView setDelegate:self];
[self.view addSubview:pageScrollView];
currentPage = 1;
}
return self;
}
By the way: should I use a different UIScrollView delegate method for handling page changes? And should I store more pages (like 2 previous and 2 next) at a time?
I hope you can help me out
Regards,
Drwall