延迟图像加载&卸载内存分配问题....aaaargghhh
我正在构建一个滚动视图,可滑动浏览 100 张房屋图像。 有用。但是......对于查看的每张图像,分配的内存都会增加 2.5 MB。最终应用程序因内存不足而崩溃。
即使我使用下面代码中指定的相同图像,由于内存分配,我也会用完内存。
我认为 NSMutableArray 在替换为另一个对象时会释放我的图像(因为保留计数为零)。
是什么导致我的图像无法卸载?如何卸载图像?
代码片段:
/*!
@method
@abstract Loads & places an house image.
@discussion Loads & places an house image and places it on the page at the proper location.
*/
- (void)loadScrollViewWithPage:(int)page {
if (page < 0) return;
if (page >= [fetchedObjects count]) return;
// replace the placeholder if necessary
[self setSelectedMiniature:[fetchedObjects objectAtIndex:page]];
NSString *imageLocation = [selectedMiniature image];
houseImageView = [imageViewArray objectAtIndex:page];
if ((NSNull *)houseImageView == [NSNull null]) {
// Use imageWithContentsOfFile: bacause imageNamed: is cached.
UIImage *houseImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"miniature91.jpg", imageLocation] ofType:nil]];
houseImageView = [[UIImageView alloc] initWithImage:houseImage];
[imageViewArray replaceObjectAtIndex:page withObject:houseImageView];
[houseImageView release];
}
// add the controller's view to the scroll view
if (nil == houseImageView.superview) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
houseImageView.frame = frame;
[scrollView addSubview:houseImageView];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self clearPage:page - 2];
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
[self clearPage:page + 2];
// A possible optimization would be to unload the views+controllers which are no longer visible
// for (int i = 0; i < [imageArray count]; i++) {
// if (i < (page - 1) || i > (page + 1)) {
// [imageArray replaceObjectAtIndex:i withObject:[NSNull null]];
// }
// }
}
- (void)clearPage:(int)page {
if (page < 0) return;
if (page >= [fetchedObjects count]) return;
[imageViewArray replaceObjectAtIndex:page withObject:[NSNull null]];
}
// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self swapSliderForRatingView];
//[self showInfo:YES];
}
// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self swapSliderForRatingView];
[self updateMiniatureInfo];
//[self showInfo:NO];
}
I am building a scrollview which swipes through 100 images of houses.
It works. But.... For every image viewed the allocated memory inscreases by 2.5 MB. In the end the app crashed because it ran out of memory.
Even if I use the same image as specified in the code below, I run out of memory because of the memory allocations.
I thought that NSMutableArray would release my image (since the retain count gets to zero) when replaced with another object.
What is keeping my images from unloading? How do I unload images?
CodeFragment:
/*!
@method
@abstract Loads & places an house image.
@discussion Loads & places an house image and places it on the page at the proper location.
*/
- (void)loadScrollViewWithPage:(int)page {
if (page < 0) return;
if (page >= [fetchedObjects count]) return;
// replace the placeholder if necessary
[self setSelectedMiniature:[fetchedObjects objectAtIndex:page]];
NSString *imageLocation = [selectedMiniature image];
houseImageView = [imageViewArray objectAtIndex:page];
if ((NSNull *)houseImageView == [NSNull null]) {
// Use imageWithContentsOfFile: bacause imageNamed: is cached.
UIImage *houseImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:[NSString stringWithFormat:@"miniature91.jpg", imageLocation] ofType:nil]];
houseImageView = [[UIImageView alloc] initWithImage:houseImage];
[imageViewArray replaceObjectAtIndex:page withObject:houseImageView];
[houseImageView release];
}
// add the controller's view to the scroll view
if (nil == houseImageView.superview) {
CGRect frame = scrollView.frame;
frame.origin.x = frame.size.width * page;
frame.origin.y = 0;
houseImageView.frame = frame;
[scrollView addSubview:houseImageView];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)sender {
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = scrollView.frame.size.width;
int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
// load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
[self clearPage:page - 2];
[self loadScrollViewWithPage:page - 1];
[self loadScrollViewWithPage:page];
[self loadScrollViewWithPage:page + 1];
[self clearPage:page + 2];
// A possible optimization would be to unload the views+controllers which are no longer visible
// for (int i = 0; i < [imageArray count]; i++) {
// if (i < (page - 1) || i > (page + 1)) {
// [imageArray replaceObjectAtIndex:i withObject:[NSNull null]];
// }
// }
}
- (void)clearPage:(int)page {
if (page < 0) return;
if (page >= [fetchedObjects count]) return;
[imageViewArray replaceObjectAtIndex:page withObject:[NSNull null]];
}
// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
[self swapSliderForRatingView];
//[self showInfo:YES];
}
// At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self swapSliderForRatingView];
[self updateMiniatureInfo];
//[self showInfo:NO];
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
快速查看您的代码后,我可以看到您正在管理图像视图数组,并可能在适当的时间删除它们,但我还没有发现您从滚动视图中删除图像视图的位置,它们被填充进入。
只要这些视图是子视图列表的一部分,它们就不会被释放。这可能就是您遇到内存问题的原因。
After quickly looking at your code, I can see that you're managing an array of image views and presumably removing them at appropriate times, but I haven't spotted where you are removing the image views from the scroll view they're getting stuffed into.
So long as those views are part of a subview list, they're not going to be released. This may be why you're running into memory troubles.