スクロールビューで画像を遅延読み込みしています。ただし、スクロールするとコンテンツのメモリ割り当てが増加し、かなり遅くなります。これが私のコードです。
- (void)scrollViewSetUp
{
self.scrollview.delegate = self;
self.automaticallyAdjustsScrollViewInsets = NO;
NSInteger pageCount = self.saleImages.count;
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(0.0,0.0,self.view.frame.size.width,40.0)];
[self.pageControl setNumberOfPages:pageCount];
[self.pageControl setCurrentPage:0];
self.pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
self.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
[self.pageControl setBackgroundColor:[UIColor clearColor]];
//Next, you set up the array that holds the UIImageView instances. At first, no pages have been lazily loaded and so you just fill it with the right amount of NSNull objects that are needed – one for each page.
//You’re using [NSNull null] because it’s a lightweight singleton object that can be added to an array to signify a placeholder.
//Later on, you’ll use the fact that there is an NSNull in there to know if that page is loaded or not.
self.pageViews = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < pageCount; i++) {
[self.pageViews addObject:[NSNull null]];
}
}
これが私のloadPage:
方法です。
-(void)loadPage:(NSInteger)page{
if (page < 0 || (page >= self.saleImages.count)) {
//if its outside the range of what you have to display, then do nothing
return;
}
//First, you check if you've already loaded the view. If you haven't, then the object in the pageViews array will be an NSNull ( remember, [NSNull null] is a special singleton which is why == works).
UIView * pageView = [self.pageViews objectAtIndex:page];
if ((NSNull*) pageView == [NSNull null]) {
CGRect frame = self.view.bounds;//set to views bounds instead of scrollviews bounds because it doesnt work very well with autolayout
frame.origin.x = (frame.size.width+kScrollViewPadding) * page;
frame.origin.y = 0.0f;
UIImageView * newPageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:[self.saleImages objectAtIndex:page]]];
newPageView.contentMode = UIViewContentModeScaleToFill;
newPageView.frame = CGRectMake(frame.origin.x,frame.origin.y,frame.size.width, frame.size.height);
[self.scrollview addSubview:newPageView];
//Finally, you replace the NSNull in pageViews array with the view you've kust created, so that if this page was asked to load again you would now not go into the if statement and instead do nothing since the view for the page has already been created.
[self.pageViews replaceObjectAtIndex:page withObject:newPageView];
}
}
これが私のpurgePage
とloadVisiblePages
です。
-(void)purgePage:(NSInteger)page{
if (page <0 || page >= self.saleImages.count) {
//if it's outside the range of what you have to display, then do nothing
return;
}
//Remove a page from the scroll view and reset the container array
UIView * pageView = [self.pageViews objectAtIndex:page];
if ((NSNull *)pageView != [NSNull null]) {
[pageView removeFromSuperview];
pageView = nil;
[self.pageViews replaceObjectAtIndex:page withObject:[NSNull null]];
}
}
-(void)loadVisiblePages{
//first determine which page is currently visible
CGFloat pageWidth = self.scrollview.frame.size.width;
NSInteger page = (NSInteger)floor((self.scrollview.contentOffset.x * 2.0f + pageWidth)/(pageWidth * 2.0f));
//update the page control
self.pageControl.currentPage = page;
//Work out which pages you want to load
NSInteger firstPage = page -1;
NSInteger lastPage = page+1;
//purge anything before the first page
for (NSInteger i = 0; i<firstPage; i++) {
[self purgePage:i];
}
//load pages in our range
for (NSInteger i = firstPage; i<=lastPage; i++) {
[self loadPage:i];
}
//purge anything after the last page
for (NSInteger i = lastPage +1; i<self.saleImages.count; i++) {
[self purgePage:i];
}
}
purgePage
個人的には、自分の方法に何か問題があると感じています。ここでは、スーパービューから pageView を削除し、nil に設定します。私は髪を引き裂いているので、誰かが助けてくれることを願っています。
Generation Analysis
インストゥルメントでa を実行した後、編集 1UIImage
が増加しているようです。犯人クラスは、loadPage と loadVisiblePages です。
編集2 @Wainは、キャッシュを行うと指摘しましたimageNamed:
。