0

Мой вопрос очень похож на this question, но с несколькими отличиями.Obj-c: возврат NSArray из метода - объекты вне рамок

У меня есть класс, который принимает в XML ИНТ виде NSString, разбирает некоторые объекты и возвращает их в 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 как переменная-член, которая не позволяет удерживать эти объекты?

ответ

2

Проблема в том, что массив освобождается. Когда вы вызываете autorelease в parseMessagesFromXml :, вы указываете массиву, что он должен быть выпущен в будущем. Это происходит до того, как таблица перезагрузит свои данные. Вам нужно снова сохранить массив, чтобы он не был выпущен. В этом случае это так же просто, как использование методов accessor для установки вашего свойства, а не для непосредственного задания переменной экземпляра.

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

Концептуально говоря, ваш контроллер представления должен «взять на себя ответственность» за результаты 'parseMessageFromXml'. – vicvicvic

+0

Это именно то, что я делаю. Также вы заметите, что сообщения используют свойство сохранения, поэтому оно не освобождается. И вдобавок ко всему, я тщательно отладил проблему, и я знаю, что она не освобождается преждевременно. Посмотрите, что он 4-й пример кода: в temp NSArray объекты все еще находятся в области видимости, и в то же время они недоступны в сообщениях. Те же объекты, в то же время, но для одного они видны, а другие - нет. – mtmurdock

+0

@mtmurdock Вы назначаете массив переменной экземпляра ('messages = [Parser parseMessageFromXml: xml];') вместо использования свойства, как было предложено ughoavgfhw ('self.messages = [Parser parseMessageFromXml: xml];') , –

Смежные вопросы