【问题标题】:Obj-c: returning NSArray from method - objects out of scopeObj-c:从方法返回 NSArray - 对象超出范围
【发布时间】:2011-01-28 23:28:46
【问题描述】:

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

我有一个类以 NSString 的形式接收 XML int,解析出一些对象并以 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 作为一个不允许它保存这些对象的成员变量是什么?

【问题讨论】:

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


    【解决方案1】:

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

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

    【讨论】:

    • 从概念上讲,您的视图控制器应该“拥有”parseMessageFromXml 的结果。
    • 这正是我正在做的。您还会注意到消息使用了保留属性,因此它不会被释放。最重要的是,我已经仔细调试了这个问题,我知道它不会过早地被释放。看看他的第 4 个代码示例:在临时 NSArray 中,对象仍在范围内,同时它们在消息中超出范围。相同的对象,相同的时间,但其中一个可见,而另一个不可见。
    • @mtmurdock 您将数组分配给实例变量 (messages = [Parser parseMessageFromXml:xml];),而不是使用 ughoavgfhw (self.messages = [Parser parseMessageFromXml:xml];) 建议的属性。
    • 所以你的意思是self.messagesmessages 是不同的?如果我可以用两种不同的方式访问同一个变量并得到不同的结果,那这似乎是语言的一个缺陷。
    • self.messages 是 @property,messages 是 ivar。 self.messages = ...[self setMessages:...] 的语法糖。合成方法setMessages: 将保留传入的值,然后分配给messages(ivar)。这不是语言的缺陷...
    猜你喜欢
    • 1970-01-01
    • 2011-11-23
    • 1970-01-01
    • 2011-01-31
    • 1970-01-01
    • 2014-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多