我想在滚动视图中显示多个图像,当图像超过70时,应用程序将崩溃并显示收到的内存错误。我从文档目录中获取图像
我试过了 -
UIScrollView *MyScroll=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
int x=5,y=15;
for (int i = 0; i < imgarr.count; i++)
{
if(x<=211)
{
UIImage* imagePath = [UIImage imageWithContentsOfFile:[path_array objectAtIndex:i]];
imgView=[[UIImageView alloc]initWithFrame:CGRectMake(x, y, 77, 75)];
imgView.image=imagePath;
imgeBtn=[UIButton buttonWithType:UIButtonTypeCustom];
imgeBtn.frame=CGRectMake(x, y, 93, 110);
[imgeBtn addTarget:self action:@selector(btnclick:) forControlEvents:UIControlEventTouchUpInside];
imgeBtn.tag=i;
x+=103;
}
else
{
x=5;
y+=130;
UIImage* imagePath = [UIImage imageWithContentsOfFile:[path_array objectAtIndex:i]];
imgView=[[UIImageView alloc]initWithFrame:CGRectMake(x, y, 77, 75)];
imgView.image=imagePath;
imgeBtn=[UIButton buttonWithType:UIButtonTypeCustom];
imgeBtn.frame=CGRectMake(x, y, 93, 110);
[imgeBtn addTarget:self action:@selector(btnclick:) forControlEvents:UIControlEventTouchUpInside];
imgeBtn.tag=i;
x+=103;
}
[MyScroll addSubview:imgeBtn];
[MyScroll addSubview:imgView];
MyScroll.contentSize=CGSizeMake(320, y+120);
如何在scrollview中显示多个图像?
答案 0 :(得分:10)
其他人提出的切换到UICollectionView
的建议很好,但它已经错过了代码中的真正缺陷:imageNamed:
的{{1}}方法保留了所有70个永远记忆中的图像。根据文档:
如果您的图像文件只显示一次并希望显示 确保它不会被添加到系统的缓存中,你应该这样做 而是使用imageWithContentsOfFile创建您的图像:这将 可能会将您的一次性图像保留在系统图像缓存之外 改善应用的内存使用特性。
如果您只将所需的图像加载到内存中,切换到此方法可以防止崩溃。 UICollectionView使这一点变得微不足道,因为只有在集合视图要求您在其数据源的UIImage
方法中填写单元格对象时才能加载图像。
答案 1 :(得分:5)
Create custom class of collection view cell
and You can pass image name in array.
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UICollectionViewDataSource,UICollectionViewDelegate>
@property (weak, nonatomic) IBOutlet UICollectionView *Collection;
@end
#import "ViewController.h"
#import "CustomCell.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self.Collection registerClass:[CustomCell class] forCellWithReuseIdentifier:@"cell"];
[self.Collection registerNib:[UINib nibWithNibName:@"CustomCell" bundle:nil] forCellWithReuseIdentifier:@"cell"];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 5;
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 4;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell * cell=[collectionView dequeueReusableCellWithReuseIdentifier:@"cell" forIndexPath:indexPath];
cell.imgview.image=[UIImage imageNamed:@"XYZ.png"];
return cell;
}
答案 2 :(得分:2)
您正在分配并继续添加导致内存崩溃的图像,因为所有图像都占用了设备内存。有许多解决方案可用于显示图像,最好是使用UICollectionView,它只加载显示图像的图像屏幕。你可以找到任何可以告诉你如何操作的好教程,这里是reference
答案 3 :(得分:2)
也许NSCache可以帮助你。
1 当您在索引10处显示图像时。您可以将图像5-9和11-16缓存到NSCache /
2 当scrollView开始滚动时,从您需要的NSCache获取图像,并删除您不需要显示的对象。
3 我认为这可能是有效的。 Apple提供了一个演示如何使用缓存和UICollectionView处理大量资产的演示。您可以查看它。
https://developer.apple.com/library/ios/samplecode/UsingPhotosFramework/Introduction/Intro.html
答案 4 :(得分:1)
我也面临同样的问题,我已经使用下面的简单线解决了这个问题。
instead of using this:
[UIImage imagedNamed:@"yourImage"];
try using this:
[yourCell.imageview setImage:[UIImage imageWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"yourImage" ofType:@"png"]]];
我希望通过使用imageWithContentsOfFile
释放内存来解决您的问题。所以你不会得到Memory Warning
<强>更新强>
您还可以使用UIImage Class
告诉它是否有帮助
答案 5 :(得分:0)
您可以尝试使用UITableView。假设您有n个图像 -
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// 3 is numbers of images per row
if (n/3 *3 == n)
return n/3;
return n/3 +1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
}
int x=5,y=15;
UIImageView* imgView1=[[UIImageView alloc]initWithFrame:CGRectMake(x, y, 93, 110)];
imgView1.image=[UIImage imageNamed:[imgarr objectAtIndex:indexPath.row + 0]];
x+=103;
UIImageView* imgView2=[[UIImageView alloc]initWithFrame:CGRectMake(x, y, 93, 110)];
imgView2.image=[UIImage imageNamed:[imgarr objectAtIndex:indexPath.row + 1]];
x+=103;
UIImageView* imgView2=[[UIImageView alloc]initWithFrame:CGRectMake(x, y, 93, 110)];
imgView2.image=[UIImage imageNamed:[imgarr objectAtIndex:indexPath.row + 2]];
[cell.contentView addSubview:imgView1];
[cell.contentView addSubview:imgView2];
[cell.contentView addSubview:imgView3];
return cell;
}
答案 6 :(得分:0)
使用@autoreleasepool。以下是有关@autoreleaspool
的详细信息@autoreleasepool语句正在执行与以前相同的工作,而不是使用NSAutoreleasePool类。 NSAutoreleasePool的工作方式有点奇怪,因为创建它会在整个应用程序中产生影响; @autoreleasepool创建一个范围区域,使其更清楚地知道池中的内容以及它何时消失(当它超出范围时)。根据Apple的说法,它的效率也更高。
自动释放池的概念很简单,只要对象实例被标记为自动释放(例如NSString * str = [[[NSString alloc] initWithString:@&#34; hello&#34;] autorelease];),它将在该时刻保留+1,但在运行循环结束时,池被耗尽,任何标记为自动释放的对象都会使其保留计数减少。它是一种保持物体的方式,同时准备任何可以保留物体的物体。
使用ARC,虽然开发人员不使用autorelease关键字,但管理ARC的基础系统会为您插入。 (请记住:所有ARC正在做的是在适当的时间为您插入保留,释放和自动释放呼叫)。因此,现有的AutoreleasePool概念需要保持不变。
如果删除自动释放池,则对象将开始泄漏 有关详细信息check here