在我的iPhone应用中,我正在动态添加UIScrollView
并在滚动视图中添加n个UIImage
和UIButton
s。这里,图像从不同的URL加载,按钮标题来自SQlite数据库。一切都好。但是当我滚动滚动视图时,现在我得到内存警告级别= 1并且在一段时间之后它是Level = 2并且崩溃应用程序。我正在使用ARC。我该如何解决这个问题?
代码
- (void)setUpViewLayout{
int newContentSize = [appDelegate.itemArray count] * 125;
menuItemIdArray = [[NSMutableArray alloc]init];
mainView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 100, 480, 220)];
mainView.contentSize = CGSizeMake(newContentSize, 220);
mainView.tag = 100;
mainView.delegate = self;
mainView.userInteractionEnabled = YES;
mainView.backgroundColor = [UIColor clearColor];
int xPosition = 20;
for (tagVal = 0; tagVal < [appDelegate.itemArray count]; tagVal++) {
[self createImage:xPosition];
[self createButton];
xPosition = xPosition + 120;
}
[self.view addSubview:mainView];
}
- (void)createImage:(int)xPosition{
DataBaseClass *itemObj = [appDelegate.itemArray objectAtIndex:tagVal];
NSString *url = [NSString stringWithFormat:@"%@",itemObj.notAvialableIcon];
imgView = [[UIImageView alloc]initWithFrame:CGRectMake(xPosition+8, 48, 110, 123)];
imgView.userInteractionEnabled = YES;
imgView.tag = tagVal;
[imgView setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:@"item01.png"]];
[mainView addSubview:imgView];
}
- (void)createButton{
DataBaseClass *itemObj = [appDelegate.itemArray objectAtIndex:tagVal];
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(5, 90, 100, 26);
button.tag = tagVal;
button.userInteractionEnabled = YES;
button.tag = tagVal;
button.titleLabel.textColor = [UIColor blueColor];
button.titleLabel.font = [UIFont systemFontOfSize:9.0];
NSString *name = [NSString stringWithFormat:@"%@",itemObj.itemStatus];
itmName = [NSString stringWithFormat:@"%@",itemObj.itemName];
NSString *date = [self changeDateFormat:itemObj.itemReleaseDate];
[button setTitle:date forState:UIControlStateNormal];
button.userInteractionEnabled = NO;
button setBackgroundImage:[UIImage imageNamed:@"not_available_bttn_bck_img"] forState:UIControlStateNormal];
[imgView addSubview:button];
}
答案 0 :(得分:4)
不要一次将所有子视图添加到滚动视图中。那太贵了。
当滚动视图滚动时,获取滚动视图的可见矩形,并添加适合范围或超过该矩形的图像和按钮。
当可见的子视图不可见时,请从超级视图中删除。
答案 1 :(得分:2)
您需要确定代码的哪个部分导致泄漏。你可以通过以下几种方式做到这一点。
一种方法是在xcode中使用内置分析器。它分析您的代码并检测(某些)潜在的内存泄漏。
仪器工具也是找到这些泄漏的好工具。使用分配/泄漏组件启动它。转到滚动视图,滚动视图后进行示例。你的泄漏应该出现。现在,您可以追踪泄漏并让仪器直接在代码中找到正确的位置。
第三个选项是查看您的代码并尝试找出自己发生的事情。了解内存管理是ios设备编程的重要组成部分。
如何在滚动视图中发布您正在使用的代码,我们可以看一下吗?
答案 2 :(得分:2)
Abhishek绝对正确,所有子视图必须在添加到superview后发布。那会导致泄漏。具体来说,一旦滚动视图离开屏幕并被释放,其子视图将不会被释放。从分配时起,它们的保留计数仍为1。
但是,只要滚动视图仍然在屏幕上,就没有泄漏。超级视图保留其所有子视图(即将其保留计数增加1.)如果子视图已分配但尚未释放,则其保留计数为2.如果已分配并且已释放其子视图保留计数为1.无论哪种方式,只要滚动视图存在,其子视图仍然可以正确保留。
如果在滚动视图仍处于运行状态时收到内存警告,则问题可能不是泄漏,而是内存过度使用。如果您继续将图像添加到大型滚动视图中,您肯定会遇到内存过剩问题。
要使用图像填充大型滚动视图,但避免记忆过剩,您可以查看ScrollViewSuite演示的第三个示例,即平铺。这应该适合你,因为你的图像和按钮大小相同,可以充当瓷砖。
我们的想法是从滚动视图中创建一种表视图,现在可以回收图像切片而不是单元格。滚动视图是子类,一组可重用的磁贴保留为其实例变量之一。在layoutSubviews中,实现的关键是从superview中移除已移出可见区域的切片,然后为新可见内容回收切片并将其添加为子视图。这样,只有可见的图块被加载到内存中。而且,它就像桌子视图一样回收细胞回收瓷砖。
从滚动视图的大小来看,除了平铺和回收之外,您可能没有其他选择。尽管如此,这是一个不错的选择。
更新: Wubao Li基本上总结了需要做的事情。 ScrollViewSuite演示向您展示了如何。
答案 3 :(得分:2)
我正在为这个开启新的回复。这是我们都错过的简单解决方案。
从您发布的代码中,这只是一个表格视图。因此,您不必构建自己的平铺滚动视图。
这里有一些代码可以帮助您入门。设置表格视图时,将其旋转90度,设置行高并消除分隔线:
tableView.transform = CGAffineTransformMakeRotation(0.5 * M_PI);
tableView.rowHeight = 120.0;
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
您必须设置表格视图的框架,使其在旋转后处于正确的位置。基本上,它与您当前的滚动视图的框架相同,或者与其侧面的框架相同。
以下是一些表格视图的数据源方法:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [appDelegate.itemArray count];
}
表格单元格可以是非常简单的自定义表格单元格,只有一个图像视图和该图像视图上的按钮。您也可以旋转图像视图,以便正确显示图像,而不是侧面。或者,您可以在加载照片编辑器或图像编辑器之前旋转所有图像。
这就是它。表视图一如既往地负责回收您的单元并优化内存使用。
答案 4 :(得分:1)
//you had allocated the things but did not release it ... it was the reason of leak
- (void)setUpViewLayout{
int newContentSize = [appDelegate.itemArray count] * 125;
// menuItemIdArray = [[NSMutableArray alloc]init]; why you are allocating this array
UIScrollView *mainView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 100, 480, 220)];
mainView.contentSize = CGSizeMake(newContentSize, 220);
mainView.tag = 100;
mainView.delegate = self;
mainView.userInteractionEnabled = YES;
mainView.backgroundColor = [UIColor clearColor];
int xPosition = 20;
for (tagVal = 0; tagVal < [appDelegate.itemArray count]; tagVal++) {
[self createImage:xPosition];
[self createButton];
xPosition = xPosition + 120;
}
[self.view addSubview:mainView];
[mainView relese];//release scroll view here
}
- (void)createImage:(int)xPosition{
DataBaseClass *itemObj = [appDelegate.itemArray objectAtIndex:tagVal];
NSString *url = [NSString stringWithFormat:@"%@",itemObj.notAvialableIcon];
imgView = [[UIImageView alloc]initWithFrame:CGRectMake(xPosition+8, 48, 110, 123)];
imgView.userInteractionEnabled = YES;
imgView.tag = tagVal;
[imgView setImageWithURL:[NSURL URLWithString:url] placeholderImage:[UIImage imageNamed:@"item01.png"]];
[mainView addSubview:imgView];
[imgView release]; //release imageview here
}
- (void)createButton{
DataBaseClass *itemObj = [appDelegate.itemArray objectAtIndex:tagVal];
button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(5, 90, 100, 26);
button.tag = tagVal;
button.userInteractionEnabled = YES;
button.tag = tagVal;
button.titleLabel.textColor = [UIColor blueColor];
button.titleLabel.font = [UIFont systemFontOfSize:9.0];
NSString *name = [NSString stringWithFormat:@"%@",itemObj.itemStatus];
itmName = [NSString stringWithFormat:@"%@",itemObj.itemName];
NSString *date = [self changeDateFormat:itemObj.itemReleaseDate];
[button setTitle:date forState:UIControlStateNormal];
button.userInteractionEnabled = NO;
button setBackgroundImage:[UIImage imageNamed:@"not_available_bttn_bck_img"] forState:UIControlStateNormal];
[imgView addSubview:button];
}
可能对你有所帮助
答案 5 :(得分:1)
这里有3条建议:
leak
,instrument
找出您的应用程序泄漏的位置,然后管理该部分以获得最佳效果答案 6 :(得分:1)
这是Apple的错误。 UIScrollView甚至会泄漏这些代码:
UIScrollView *s = [[UIScrollView alloc] initWithFrame:self.view.bounds];
s.contentSize = CGSizeMake(320, 800);
[self.view addSubview:s];
[s release];