我有一个viewcontroller,可以在uiscrollview中重复定位6个项目。然而,即使我将uiscrollview中的项目数量限制为6,我仍然在更新其位置和图像时泄漏内存。如果下面代表uiscrollview中的单位的代码被正确编码,有人可以告诉我吗? startLoad是我重新加载图像后调用的方法。
#import "ScrollUnit.h"
@implementation ScrollUnit
@synthesize index;
@synthesize ProductToDisplay;
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code.
}
return self;
}
-(void)startLoad
{
[imageview removeFromSuperview];
[imageview release];
NSOperationQueue *queue = [NSOperationQueue new];
NSInvocationOperation *operation = [[NSInvocationOperation alloc]
initWithTarget:self
selector:@selector(loadImage)
object:nil];
[queue addOperation:operation];
[operation release];
}
-(void)loadImage
{
NSString *myimageName = [self.ProductToDisplay valueForKey:IMAGEKEY];
NSString *myimageUrl = [NSString stringWithFormat:@"%@/%@",IMAGE_SERVICE,myimageName];
NSData* imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:myimageUrl]];
UIImage* image = [[[UIImage alloc] initWithData:imageData] autorelease];
[imageData release];
[self performSelectorOnMainThread:@selector(displayImage:) withObject:image waitUntilDone:NO];
}
- (void)displayImage:(UIImage *)image
{
imageview = [[[UIImageView alloc] initWithFrame:CGRectMake(9, 0, 320, 320)]retain];
imageview.contentMode = UIViewContentModeScaleAspectFit;
imageview.backgroundColor = [UIColor whiteColor];
imageview.image = image;
[self addSubview:imageview];
[imageview release];
//[image release];
}
- (void)dealloc {
[super dealloc];
}
@end
答案 0 :(得分:3)
删除此行上的retain
消息,您应该全部设置:
imageview = [[[UIImageView alloc] initWithFrame:CGRectMake(9, 0, 320, 320)]retain];
您需要执行此操作的原因是您已通过调用alloc
来拥有该对象,因此此时相对引用计数为2
。
一旦您调用addSubview:
,传递imageview
,引用计数就会变为3
,然后在您2
后向右追溯到release
它在下一行。
因此,一旦该对象在release
中发送-dealloc
,您仍然会被卡住,因为引用计数现在是1
,而不是您预期的0
。
答案 1 :(得分:1)
还有另一件可能有bug(或没有)的小东西。在displayImage方法中指定之前,不要发布 imageview 。只要只调用startLoad就可以了,但如果从外部调用displayImage,那么你仍然会泄漏。
您可能希望使用保留的属性,然后合成getter和setter方法。这样,iOS将在保留新分配的对象之前释放您之前的作业。那说你需要释放创建的图像视图,如果你创建它,你必须使用“self.imageview”,以确保你使用setter(setImageview)。