嵌套 NSAutoreleasePool
在我的 iPad 应用程序之一中,我使用 json 字符串远程构建数据库,然后转换为 NSArray 以插入核心数据,然后在 ipad 上下载大约 600Mb 的图像。所有这些都是在后台线程中创建的,从一开始就导致一些内存问题。 我解决了在操作中嵌套 3 个不同的 NSAutoreleasePool 并在方便的时候释放它们中的每一个的问题。我没有收到任何错误,也没有泄漏,也没有警告。我只是想知道这是否是一种好方法,或者我只是错过了一些东西。
这是一个示意性示例(实际代码很长):
- (void)main{
@try {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // first pool
[managedOC lock];
NSArray *results = [self loadEntitiesWithGroupName:@"Project" andName:@"projects"];
NSAutoreleasePool *prjPool; // second pool
for (NSDictionary *thisResult in results) {
prjPool = [[NSAutoreleasePool alloc] init];
Project *prj = [[Project alloc] initWithEntity:[NSEntityDescription entityForName:@"Project" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext:self.managedOC];
prj.name = [thisResult objectForKey:@"name"];
[prj saveThumbnail:[thisResult objectForKey:@"thumbnail"]];
//Slides. Those are the images that take so mutch space.
NSArray *slides = [thisResult objectForKey:@"slides"];
NSAutoreleasePool *slidePool; // third pool
if(slides != kCFNull){
slidePool = [[NSAutoreleasePool alloc] init];
for(NSDictionary *slide in slides){
Slide *thisSlide = [[Slide alloc] initWithEntity:[NSEntityDescription entityForName:@"Slide" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext: self.managedOC];
thisSlide.path = prj.path;
[thisSlide saveFile:[slide objectForKey:@"file"]];
[prj addSlidesObject:thisSlide];
[thisSlide release];
[slidePool drain];
}
}
[prj release];
[result release];
[prjPool drain];
}
[self.managedOC unlock];
[totResult release];
[pool drain];
}
@catch (NSException * e) {
}
In one of my applications for iPad I am building up the db remotely using a json string then converted to NSArray to be insert in core data and then I donwload around 600Mb of images on the ipad. All this is created in a background thread causing from the beginning some memory issue.
I get hold of the problem nesting 3 different NSAutoreleasePool in the operation and releasing each of them at a convenient point. I got no error, nor leak, nor warning. I was just wondering if it is a good way of doing it or I just miss something.
Here a schematic example (the real code is quite long):
- (void)main{
@try {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // first pool
[managedOC lock];
NSArray *results = [self loadEntitiesWithGroupName:@"Project" andName:@"projects"];
NSAutoreleasePool *prjPool; // second pool
for (NSDictionary *thisResult in results) {
prjPool = [[NSAutoreleasePool alloc] init];
Project *prj = [[Project alloc] initWithEntity:[NSEntityDescription entityForName:@"Project" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext:self.managedOC];
prj.name = [thisResult objectForKey:@"name"];
[prj saveThumbnail:[thisResult objectForKey:@"thumbnail"]];
//Slides. Those are the images that take so mutch space.
NSArray *slides = [thisResult objectForKey:@"slides"];
NSAutoreleasePool *slidePool; // third pool
if(slides != kCFNull){
slidePool = [[NSAutoreleasePool alloc] init];
for(NSDictionary *slide in slides){
Slide *thisSlide = [[Slide alloc] initWithEntity:[NSEntityDescription entityForName:@"Slide" inManagedObjectContext:self.managedOC] insertIntoManagedObjectContext: self.managedOC];
thisSlide.path = prj.path;
[thisSlide saveFile:[slide objectForKey:@"file"]];
[prj addSlidesObject:thisSlide];
[thisSlide release];
[slidePool drain];
}
}
[prj release];
[result release];
[prjPool drain];
}
[self.managedOC unlock];
[totResult release];
[pool drain];
}
@catch (NSException * e) {
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我很惊讶你的代码没有崩溃。
-drain
在引用计数环境中的行为与-release
相同,因此下面的 over 释放池除非
slides
中只有一个对象> 收藏。你需要这个:除此之外,你还有正确的总体想法。
您应该在异常处理程序的finally块中耗尽最外层的池,以便在引发异常时不会跳过它,即您应该这样做:
I'm surprised your code doesn't crash.
-drain
behaves the same as-release
in the reference counted environment, so the following over releases the poolUnless there is only one object in the
slides
collection. You need this:Other than that, you have the right general idea.
You should drain your outermost pool in the finally block of your exception handler so that it is not skipped if an exception is raised i.e. you should do this: