Objective-C超出范围问题

时间:2010-05-07 08:18:31

标签: objective-c memory retain

我在使用一些Objective-C时遇到了一些问题,并且会很感激。

所以我有一个类MapFileGroup,它有以下简单的接口(还有其他成员变量,但它们并不重要):

@interface MapFileGroup : NSObject {
 NSMutableArray *mapArray;

}

@property (nonatomic, retain) NSMutableArray *mapArray;

mapArray在.m文件中为@synthesize

它有一个init方法:

-(MapFileGroup*) init
  {
    self = [super init];
    if (self)
    {
       mapArray = [NSMutableArray arrayWithCapacity: 10];
    }

    return self;
  }

它还有一个向数组添加自定义对象的方法:

-(BOOL) addMapFile:(MapFile*) mapfile
{
if (mapfile == nil) return NO;

mapArray addObject:mapfile];
return YES;
}

当我想使用这个类时,我得到的问题显而易见 - 显然是由于我对内存管理的误解。

在我的视图控制器中,我声明如下:

(在@interface中):

MapFileGroup *fullGroupOfMaps;

使用@property @property (nonatomic, retain) MapFileGroup *fullGroupOfMaps;

然后在.m文件中,我有一个名为loadMapData的函数,它执行以下操作:

MapFileGroup *mapContainer = [[MapFileGroup alloc] init];
// create a predicate that we can use to filter an array

//表示以.png结尾的所有字符串(不区分大小写)     NSPredicate * caseInsensitivePNGFiles =     [NSPredicate predicateWithFormat:@“SELF endwith [c]'。png'”];

mapNames = [unfilteredArray filteredArrayUsingPredicate:caseInsensitivePNGFiles];
[mapNames retain];

NSEnumerator * enumerator = [mapNames objectEnumerator];
NSString * currentFileName;
NSString *nameOfMap;
MapFile *mapfile;


while(currentFileName = [enumerator nextObject]) {
  nameOfMap = [currentFileName substringToIndex:[currentFileName length]-4]; //strip the extension

mapfile = [[MapFile alloc] initWithName:nameOfMap];
[mapfile retain];
// add to array
[fullGroupOfMaps addMapFile:mapfile];

}

这似乎工作正常(虽然我可以告诉我没有让内存管理正常工作,我仍然在学习Objective-C);但是,我有(IBAction)以后与fullGroupOfMaps进行交互。它在fullGroupOfMaps内调用一个方法,但如果我在调试时从该行进入该类,则所有fullGroupOfMaps的对象现在都超出了范围,我就崩溃了。

为长期问题和大量代码道歉,但我想我的主要问题是:

我应该如何处理一个NSMutableArray作为实例变量的类?创建要添加到类中的对象的正确方法是什么,以便在我完成它们之前不会释放它们?

非常感谢

1 个答案:

答案 0 :(得分:2)

当您致电[NSMutableArray arrayWithCapacity:]时,这实际上会创建一个“自动释放”数组。这意味着它将在未来的某个时间自动发布。通常,它将在当前运行循环结束时释放。

您要做的是创建一个未自动释放的数组,因为您希望在完成后显式释放它。为此,请使用:

mapArray = [[NSMutableArray alloc] initWithCapacity: 10];

不要忘记,你需要在完成后释放它。通常,如果在类的初始化器中初始化了一个实例变量,那么它应该在类的dealloc方法中释放,如下所示:

- (void) dealloc
{
    [mapArray release];
    [super dealloc]; // so that NSObject can clean up itself
}

某些方法会返回自动释放的对象,以方便您使用,因此您无需自行管理内存(它将自动清理)。在实例变量的情况下,您几乎不希望它们被自动清理。

您还可以通过再次保留自动释放的对象来阻止自动释放。

mapArray = [[NSMutableArray arrayWithCapacity:10] retain];

Cocoa Memory Management Programming Guide有一些简单的规则可供您明确释放,以及何时应明确保留。保持链接书签,直到规则成为第二天性,你可以没有Cocoa内存管理的麻烦。它比最初看起来要简单得多(或者至少,对我来说就是这种情况)。