【发布时间】:2011-05-16 21:23:00
【问题描述】:
我正在开发一个使用 UIScrollView 滚动浏览一堆幻灯片的应用程序。当应用程序打开时,它会创建幻灯片并将它们传递给滚动视图。我的应用程序还有一个计时器,它会导致 UIScrollView 在幻灯片中滚动。
我还有一个设置按钮。当我按下该按钮时,它会打开设置面板。计时器无效并设置为nil。当设置面板打开时,用户可以更改应用程序主题、幻灯片和动画方向等内容。
当设置面板关闭时,将应用设置:从 UIScrollView 中删除幻灯片,并为 UIScrollView 提供一个新的 NSArray 幻灯片以供使用。 UIScrollView 然后以正确的顺序和方向布置新幻灯片。计时器已重置。
大约每 14-16 次,应用程序在运行 dismissAndRestart(“关闭”代码)时崩溃。我不确定为什么。我以为我在泄漏内存,显然我是,但我不知道在哪里。
这是我的代码:
这在启动时运行:
- (void)viewDidLoad {
[scrollView setPagingEnabled:YES];
}
- (void) viewWillAppear:(BOOL)animated{
[self prepareViews];
[self applyTheme];
}
- (void) viewDidAppear:(BOOL)animated{
[self createTimerWithInterval:kScrollInterval];
}
将视图加载到滚动条中的主力方法。 (它也会删除旧的):
- (void)loadViews:(NSArray *)views IntoScroller:(UIScrollView *)scroller withDirection:(NSString *)direction{
[scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
[scrollView setShowsHorizontalScrollIndicator: NO];
[scrollView setShowsVerticalScrollIndicator:NO];
scrollView.scrollsToTop = NO;
if([direction isEqualToString:@"horizontal"]){
scrollView.frame = CGRectMake(0, 0, 1024, 768);
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [[NSNumber numberWithUnsignedInt:[views count]] floatValue], scrollView.frame.size.height);
}else if([direction isEqualToString:@"vertical"]){
scrollView.frame = CGRectMake(0, 0, 1024, 768);
scrollView.contentSize = CGSizeMake(scrollView.frame.size.width, scrollView.frame.size.height * [[NSNumber numberWithUnsignedInt:[views count]] floatValue]);
}
for (int i=0; i<[[NSNumber numberWithUnsignedInt:[views count]] intValue]; i++) {
[[[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view] setFrame:scrollView.frame];
if([direction isEqualToString:@"horizontal"]){
[[[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view] setFrame:CGRectMake(i * [[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view].frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height)];//CGRectMake(i * announcementView.view.frame.size.width, -scrollView.frame.origin.x, scrollView.frame.size.width, scrollView.frame.size.height)];
}else if([direction isEqualToString:@"vertical"]){
[[[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view] setFrame:CGRectMake(0, i * [[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view].frame.size.height, scrollView.frame.size.width, scrollView.frame.size.height)];
}
[scrollView addSubview:[[views objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntValue]] view]];
}
}
为自动滚动创建计时器:
#pragma mark -
#pragma mark Create the Timer to automate scrolling
- (void) createTimerWithInterval:(float)interval{
self.timer = [NSTimer scheduledTimerWithTimeInterval:interval target:self selector:@selector(scrollWrapperForTimer) userInfo:nil repeats:YES];
}
定时器函数的包装函数。 (在方向是 NSUserDefault 之前这是必需的,现在我不应该需要它了。)
#pragma mark -
#pragma mark Scroll Automatically Every N seconds
- (void) scrollWrapperForTimer{
[self scrollToNewViewInDirection:kDirection];
}
- (void)scrollToNewViewInDirection:(NSString *)direction{
if([[NSUserDefaults standardUserDefaults] boolForKey:@"animated_scrolling"] == YES){
if([direction isEqualToString:@"horizontal"]){
if([[NSNumber numberWithFloat:scrollView.contentOffset.x] compare:[NSNumber numberWithFloat:scrollView.contentSize.width - scrollView.frame.size.width]] == (NSOrderedAscending)){
[scrollView scrollRectToVisible:CGRectMake(scrollView.contentOffset.x + scrollView.frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];
}else if([[NSNumber numberWithFloat:scrollView.contentOffset.x] compare:[NSNumber numberWithFloat:scrollView.contentSize.width - scrollView.frame.size.width]] == (NSOrderedSame)){
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];
}
}else if([direction isEqualToString:@"vertical"]){
if([[NSNumber numberWithFloat:scrollView.contentOffset.y] compare:[NSNumber numberWithFloat:scrollView.contentSize.height - scrollView.frame.size.height]] == (NSOrderedAscending)){
[scrollView scrollRectToVisible:CGRectMake(0, scrollView.contentOffset.y + scrollView.frame.size.height, scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];
}else if([[NSNumber numberWithFloat:scrollView.contentOffset.y] compare:[NSNumber numberWithFloat:scrollView.contentSize.height - scrollView.frame.size.height]] == (NSOrderedSame)){
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:YES];
}
}
}else {
if([direction isEqualToString:@"horizontal"]){
if([[NSNumber numberWithFloat:scrollView.contentOffset.x] compare:[NSNumber numberWithFloat:scrollView.contentSize.width - scrollView.frame.size.width]] == (NSOrderedAscending)){
[scrollView scrollRectToVisible:CGRectMake(scrollView.contentOffset.x + scrollView.frame.size.width, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
}else if([[NSNumber numberWithFloat:scrollView.contentOffset.x] compare:[NSNumber numberWithFloat:scrollView.contentSize.width - scrollView.frame.size.width]] == (NSOrderedSame)){
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
}
}else if([direction isEqualToString:@"vertical"]){
if([[NSNumber numberWithFloat:scrollView.contentOffset.y] compare:[NSNumber numberWithFloat:scrollView.contentSize.height - scrollView.frame.size.height]] == (NSOrderedAscending)){
[scrollView scrollRectToVisible:CGRectMake(0, scrollView.contentOffset.y + scrollView.frame.size.height, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
}else if([[NSNumber numberWithFloat:scrollView.contentOffset.y] compare:[NSNumber numberWithFloat:scrollView.contentSize.height - scrollView.frame.size.height]] == (NSOrderedSame)){
[scrollView scrollRectToVisible:CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height) animated:NO];
}
}
}
}
当在设置面板中按下完成按钮时调用此方法。
#pragma mark -
#pragma mark Restart the program
- (void) dismissAndRestart{
[self prepareViews];
[self applyTheme];
[self dismissModalViewControllerAnimated:YES];
[self createTimerWithInterval:kScrollInterval];
}
这会创建正确的图像文件并将它们加载到位:
#pragma mark -
#pragma mark Apply the theme to the main view
- (void) applyTheme{
//Front panel
UIImage *frontImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[[NSString stringWithFormat:@"%@_front", kTheme]description] ofType:@"png"]];
[self.overlayImage setImage:frontImage];
[frontImage release];
//Back Panel
if([kTheme isEqualToString:@"walnut"]){
[self.backgroundImage setHidden:NO];
UIImage *backImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[[NSString stringWithFormat:@"%@_back", kTheme]description] ofType:@"png"]];
[self.backgroundImage setImage:backImage];
[backImage release];
}else if([kTheme isEqualToString:@"metal"]){
[self.backgroundImage setHidden:YES];
[self.view setBackgroundColor: [UIColor scrollViewTexturedBackgroundColor]];
}
//Gabbai Button
UIImage *gabbaiImage = [[UIImage alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[[NSString stringWithFormat:@"%@_settings_button", kTheme]description] ofType:@"png"]];
[self.gabbaiButton setImage:gabbaiImage forState:UIControlStateNormal];
[gabbaiImage release];
}
另一个需要重构的包装函数:
#pragma mark -
#pragma mark Slide View related
- (void) prepareViews{
[self loadViews:[self createandReturnViews] IntoScroller:scrollView withDirection:kDirection];
}
创建幻灯片数组以传递给滚动条:
//recreation of the views causes a delay each time the admin panel is closed.
- (NSArray*) createandReturnViews{
NSMutableArray *announcements = [NSMutableArray array];
NSArray *announcementsArray = [NSArray arrayWithObjects: @"Welcome to\nGabbai HD!",
@"First slide",
@"Second Slide",
@"Third Slide",
@"etc.",
nil];
for (int i = 0; i<[[NSNumber numberWithUnsignedInteger:[announcementsArray count]] intValue]; i++) {
MBAnnouncementViewController *announcement = [[MBAnnouncementViewController alloc] initWithNibName:@"MBAnnouncementViewController" bundle:nil];
[announcement setAnnouncementText:[announcementsArray objectAtIndex:[[NSNumber numberWithInt:i] unsignedIntegerValue]]];
[announcements addObject:announcement];
[announcement release];
}
return announcements;
}
为什么我的设置面板会在关闭时使应用程序崩溃?
【问题讨论】:
标签: iphone ipad memory-management uiscrollview