0

我正在开发的 iPad 应用程序是一本书。要跳转到特定页面,用户可以按下一个按钮,该按钮覆盖当前视图的视图顶部,显示书中每个页面的缩略图图像。

当用户按顺序浏览书籍并显示此缩略图菜单时,如果用户显示该菜单,则滚动动画是流畅而精细的。如果用户showBookmarkMenu在加载大约 15 页后调用,滚动视图动画非常非常慢,并且滚动视图不再捕获触摸,则会出现问题。

我注意到scrollViewDidEndDecelerating当滚动动画正常且流畅时(加载应用程序后不久)会调用它,但在用户浏览几页后不会调用它。所以一个假设是 CPU 正在努力处理滚动视图内容定位的动画。我使用 Instruments 的 Activity Monitor 运行应用程序,但有时应用程序使用 97% 甚至更多的 CPU 并且滚动视图滚动良好......

对这个问题有什么想法吗?我已经在下面发布了我的代码。

主类.m

//Called when user presses the open/close bookmark menu button
-(IBAction)toggleBookmarksMenu{
    if([bookMarkMenu isHidden]){
        [currentPage.view addSubview:bookMarkMenu];
        [bookMarkMenu showBookmarkMenu];

    }
    else{
        [bookMarkMenu hideBookmarksMenu];
    }
}

滚动视图类.h

@interface BookmarkManager : UIView<UIScrollViewDelegate>{
    UIScrollView *thumbnailScrollView;
}

@property (strong, nonatomic) UIScrollView *thumbnailScrollView;
@property (strong) id <BookmarkManagerDelegate> bookmarkManagerDelegate;


-(void)showBookmarkMenu;
-(void)hideBookmarksMenu;

@end

滚动视图类.m

-(void)showBookmarkMenu{
    [self setHidden:NO];
    [UIView animateWithDuration:0.5
                     animations:^{
                         self.center = CGPointMake(512, 384);
                     }
     ];
}


-(void)hideBookmarksMenu{
    [UIView animateWithDuration:1
                     animations:^{
                         self.center = CGPointMake(512, -120);
                     }
                     completion:^(BOOL finished){
                             [self setHidden:YES];
                             [self removeFromSuperview];
                     }
     ];
}

-(id)init{
    self = [super initWithFrame:CGRectMake(0, 0, 1024, 768)];
    if(self){
        [self setBackgroundColor:[UIColor clearColor]];
        self.center = CGPointMake(512, 0);

        thumbnailScrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 1024, 120)];
        [thumbnailScrollView setBackgroundColor:[UIColor clearColor]];
        thumbnailScrollView.showsHorizontalScrollIndicator = NO;

        //Add the UIButtons with images of the thumbnails
        for(int i = 0; i < totalPages; i++){

            UIButton *pageThumbnail = [UIButton buttonWithType:UIButtonTypeCustom];
            pageThumbnail.frame = CGRectMake(0, 0, 125, 95);

            [pageThumbnail setBackgroundImage:[UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/p%d_thumb.png", [[NSBundle mainBundle] resourcePath], i]] forState:UIControlStateNormal];

            [thumbnailScrollView addSubview:pageThumbnail];
            [pageThumbnail addTarget:self action:@selector(thumbnailTapped:) forControlEvents:UIControlEventTouchDown];

        }

        [self addSubview:thumbnailScrollView];
        [thumbnailScrollView setContentSize:CGSizeMake(totalPages * 125 + (20*(totalPages+1)), 120)];
        [thumbnailScrollView setDelegate:self];

        [self setHidden:YES];   
    }        
    return self;
}
4

3 回答 3

1

我必须解决可能的内存不足问题。

使用大量按钮的一种可能替代方法是使用 UITableView。您的代码当前的工作方式是加载所有带有图像的按钮。对于一本大书来说,这可能会很痛苦。

使用 UITableView 你只使用你看到的(关于)尽可能多的内存。而且,由于每个图像都是动态加载的,因此您的内存使用量仅与显示的一样多。那将是我将如何去做(实际上,我现在正在这样做,只是不是用一本书)。

于 2012-08-07T15:32:07.737 回答
1

根据您的观察,在加载 15 页左右后滚动变慢:可能您的设备正忙于处理内存不足的情况。在这种情况下,您可能知道,系统范围内的通知会发送到相当多的应用程序/对象,以便它们尽可能多地恢复内存。

您能否在滚动变慢时或多或少同时检查您的应用程序正在执行didReceiveMemoryWarning

如果您确认该问题可能与内存饱和/回收有关,那么我建议为您的图像实施延迟加载方案:

  1. 您仅在需要显示图像时才加载图像;

  2. 您总共只能在内存中保存 3-5 张图像,以确保平滑滚动。

基本步骤需要提供您的代表的 id

- (void)scrollViewDidScroll:(UIScrollView *)scrollView;

执行。在这里您将预加载图像:

  1. 知道您的位置,您就知道您当前的图像(例如,图像编号 N);

  2. 卸载图像 N-2, N+2;

  3. 加载图像 N-1, N+1。

如果您只想要一个“缓冲区”图像,我提供的要加载/卸载的图像很好。

无论如何,如果你用谷歌搜索“iso 滚动视图延迟加载”,你会发现很多信息。

于 2012-08-07T15:23:09.687 回答
0

原来这不是内存不足的问题,而是 CPU 过于繁忙的问题。

CPU 执行滚动视图的滚动动画所需的计算,当滚动变得如此缓慢时,我想我首先要弄清楚为什么我首先使用了 97% 的 CPU。原来,在第 15 页之后,我的 CPU 密集型递归函数(为应用程序的另一部分计算 UIBezierPaths)陷入了无限循环。该应用程序每秒计算数百个 UIBezierPaths,并且达到了 CPU 无法跟上滚动视图动画计算的地步。

一旦我确定递归函数在不需要它们时停止调用它们自己,整个应用程序的 CPU 使用率保持在 20% 以下,并且滚动视图表现得非常好。

于 2012-08-08T14:41:57.857 回答