UIScrollView滚动太慢,从不调用scrollViewDidEndDecelerating

时间:2012-08-07 15:15:28

标签: ios uiscrollview

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

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

我注意到当滚动动画正常且平滑(加载应用程序后不久)时会调用scrollViewDidEndDecelerating,但在用户经过多个页面后不会调用它。因此,一个假设是CPU正在努力研究scrollview内容定位的动画。我使用Instruments的Activity Monitor运行应用程序,但有时候应用程序使用97%以上的CPU并且滚动视图滚动得很好......

关于这个问题的任何想法?我在下面发布了我的代码。

MainClass.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];
    }
}

ScrollViewClass.h

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

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


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

@end

ScrollViewClass.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;
}

3 个答案:

答案 0 :(得分:1)

在黑暗中拍摄,基于您观察到在加载15页左右后滚动变慢:可能您的设备正在忙于处理低内存条件。在这种情况下,您可能知道,系统范围的通知会发送到相当数量的应用程序/对象,以便他们尽可能多地恢复内存。

您是否可以在滚动速度变慢的同时检查您的应用正在执行didReceiveMemoryWarning

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

  1. 您只需在需要显示图片时加载图片;

  2. 您只需保存3-5张图片,以确保滚动顺畅。

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

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

    实现。在这里,您将预加载图像:

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

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

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

    4. 如果您只想要一个“缓冲”图像,我提供的加载/卸载图像就可以了。

      无论如何,如果你google“iso scroll view lazy loading”你会发现很多信息。

答案 1 :(得分:1)

我必须考虑可能的低内存问题。

使用大量按钮的另一种可能方法是使用UITableView。代码当前的工作方式,它会将所有按钮加载到图像中。对于一本大书,这可能很痛苦。

使用UITableView只能使用你所看到的内存(约)。并且,由于每个图像都是动态加载的,因此您的内存使用量仅与显示的一样多。这就是我要去做的事情(实际上,我现在正在这样做,而不是一本书)。

答案 2 :(得分:0)

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

CPU执行滚动视图滚动动画所需的计算,当滚动变慢时,我想我会试着找出为什么我首先使用97%的CPU。事实证明,在过去的第15页,我有无限循环捕获的CPU密集型递归函数(为应用程序的另一部分计算UIBezierPaths)。该应用程序每秒计算数百个UIBezierPaths,并且达到了CPU无法跟上scrollview动画的计算的程度。

一旦我确定递归函数在不需要时停止调用自身,整个应用程序的CPU使用率仍然低于20%,并且滚动视图表现非常好。