Obj-c:从方法返回NSArray - 对象超出范围

时间:2011-01-28 23:28:46

标签: objective-c memory-management scope nsarray exc-bad-access

我的问题与this question非常相似,但有一些差异。

我有一个以NSString的形式接受XML的类,解析出一些对象,并在NSArray中返回它们,如下所示:

//Parser.m
+(NSArray *)parseMessagesFromXml:(NSString *)xml
{
   NSMutableArray *messages = [[NSMutableArray alloc] init];

   //do some work parsing the xml
   //for each <row>
   //   Message *m = makeMessageFromRow(row);

   return [messages autorelease];
}

然后在我的视图控制器类中,我声明了一个NSArray:

//MyViewController.h
NSArray *messages;
@property (nonatomic, retain) NSArray *messages;

并使用上述方法分配:

//MyViewController.m
messages = [Parser parseMessageFromXml:xml];
[[self tableView] reloadData];

所以这就出现了问题:当我将数组分配给messages时,它包含元素,但它们都“超出范围”。我已经调试了问题,我知道解析方法正确地创建了对象并在返回之前将它们添加到NSMutableArray。当我尝试访问messages我的应用程序崩溃中的对象时,调试器显示EXC_BAD_ACCESS。更奇怪的是:如果我将数组存储到局部变量中,它可以正常工作:

NSArray *temp = [Parser parseMessageFromXml:xml]; 
//temp has all the right objects and they are in scope

messages = temp;
//messages has the objects, but cannot access them (they are out of scope).

就好像我可以在本地范围内合法地查看它们,但我无法将它们分配给成员变量。我甚至尝试迭代返回的数组,将每一个单独添加到messages,但结果是相同的:它们超出了范围。我完全不知道这个。

messages作为不允许它保存这些对象的成员变量是什么意思?

1 个答案:

答案 0 :(得分:2)

问题是阵列正在发布。当你在parseMessagesFromXml:中调用autorelease时,你告诉数组它应该在将来的某个时候发布。这是在表重新加载其数据之前发生的。您需要再次保留阵列以防止它被释放。在这种情况下,它就像使用访问器方法设置属性一样简单,而不是直接设置实例变量。

//MyViewController.m
self.messages = [Parser parseMessageFromXml:xml];
[[self tableView] reloadData];