Почему массив, декодированный из plist или JSON, не отвечает на: class или: count, в то время как это делает программно созданный массив? - PullRequest
1 голос
/ 26 июня 2009

Я столкнулся с чрезвычайно неприятной проблемой. У меня есть UITableViewController, который в своем методе init декодирует словарь из файла JSON или plist (я пробовал оба), а затем получает массив из этого словаря. Позже в методе tableView: numberOfRowsInSection: я возвращаю счетчик этого массива.

Однако по не зависящим от меня причинам счетчик вызовов в массиве в этот момент приводит к сбою приложения, хотя счетчик вызовов непосредственно после назначения в init - нет. Кроме того, если я заменяю начальное назначение на программно созданный массив (через NSArray initWithObjects), оно работает нормально.

JSON-декодирование в init:

NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"Categories" ofType:@"json"];
SBJSON *jsonParser = [SBJSON new];
NSDictionary* dict = [jsonParser objectWithString:[NSString stringWithContentsOfFile:jsonPath encoding:NSUTF8StringEncoding error:nil]];
categories = [dict objectForKey:@"ContentCategories"];

// Outputs correct count
NSLog(@"Count: %@", [NSNumber numberWithInt:[categories count]]);

Программная инициализация:

 categories = [[NSArray alloc] initWithObjects: [[NSDictionary alloc] initWithObjectsAndKeys:@"Junk", @"Title"]];

 // Outputs correct count
NSLog(@"Count: %@", [NSNumber numberWithInt:[categories count]]);

Метод числа строк UITableViewController:

// Outputs correctly if programmatically created, crashes if decoded from JSON/plist
NSLog(@"Count: %@", [NSNumber numberWithInt:[categories count]]);

Я пробовал переменную «категории» в качестве ивара, свойства-ивара и переменной класса, но безуспешно.

Спасибо за вашу помощь!

Ответы [ 2 ]

2 голосов
/ 26 июня 2009

Я не знаком с этим синтаксическим анализатором JSON, но если он следует соглашениям Какао, objectWithString будет возвращать объект, выпущенный автоматически. Это означает, что он будет освобожден на следующей итерации через цикл запуска, если вы его не сохраните. Когда классы коллекции Какао освобождаются, они освобождают каждый содержащийся в них объект, поэтому категории также будут освобождены. Вот почему это работает сначала, но не позже в программе.

Причина, по которой он работает, делая его свойством, заключается в том, что созданный синтезированный сеттер сохраняет категории (при условии, что вы устанавливаете свое свойство с помощью параметра retain, что, я полагаю, вы сделали), поэтому оно не будет освобождено. Это правильное решение, хорошая работа. :) Вызов удержания по категориям также сработал бы.

Соглашение Какао состоит в том, что если имя метода содержит «alloc» или «copy» или начинается с «new», возвращаемый объект имеет счет сохранения 1, и вы несете ответственность за его освобождение. В противном случае возвращенный объект имеет нулевое количество сохранений (он был автоматически освобожден) и будет освобожден на следующей итерации в цикле выполнения, если только вы не сохраните его (в этом случае вы берете на себя ответственность за его последующее освобождение).

Я рекомендую прочитать это: Руководство по программированию управления памятью для какао

Edit: Причина, по которой он работал с использованием [[NSArray alloc] initWithObjects ...], заключается в том, что этот метод содержит «alloc», возвращенный массив не был автоматически выпущен, и поэтому он все еще появляется позже, когда вы обращаетесь к нему.

0 голосов
/ 26 июня 2009

Примечание: изменение «категорий» для свойства и добавление «себя». перед всеми методами установки / получения (например, self.categories = ...) сделал эту работу. По какой-то причине при вызове только «категорий» возвращался объект типа UIWindow в методе numberOfRows (!). Это кажется мне невероятно странным (я надеюсь, что у меня просто возникнут ошибки компилятора), но опять же, я относительно новичок в obj-c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...