Стратегия памяти iPhone NSXMLParser для больших xml

Я строю алгоритм синтаксического анализа с помощью NSXMLParser. Я сомневаюсь, как лучше всего использовать память на минимальном уровне.

У меня есть valueObject (например, "Person"), этот объект имеет ≈ 30 свойств NSString, при синтаксическом анализе xml я постоянно выделяю и освобождаю временный объект Person по мере прохождения узлов. Я проверил это, и в любой момент создается только один из этих объектов Person. Когда узел пройден и Person "строит", я передаю Person в NSMutableArray и освобождаю это Person. Кажется, здесь нет проблем. (Мне понадобится массив для tableView). Когда я достигаю около 50+ объектов Person в массиве, мое приложение просто закрывается, didReceiveMemoryWarning не вызывается, никаких других предупреждений, никакого parseErrorOccurred, ничего?

Если я ограничу количество лиц в xml, приложение будет работать нормально, я не смогу найти утечки памяти с помощью инструментов. Я думаю, что просто не могу удерживать в массиве 50+ объектов Person… кажется немного жестким, но у меня не так много опыта работы с памятью на iPhone, так что это всего лишь предположение.

Xml - это результаты поиска, из которых пользователю, вероятно, понадобится всего несколько, поэтому сохранение их в моей базовой модели, чтобы держать их для отображения, кажется немного сумасшедшим.

Что было бы хорошей стратегией для хранения этих объектов Person? или мне не хватает огромной утечки памяти, так как iPhone должен справляться с гораздо большими возможностями?

Надеюсь, что некоторые опытные разработчики могут указать мне правильное направление :)

Спасибо!


person RickiG    schedule 03.11.2009    source источник
comment
Некоторые примеры кода были бы полезны   -  person ACBurk    schedule 04.11.2009


Ответы (4)


Какова длина этих струн? Как правило, на iPhone 3G и более старых моделях ваше приложение должно иметь как минимум около 20 МБ доступной памяти (намного больше для 3G). Это, конечно, не абсолютное правило, а хорошее практическое правило. Занять такой объем памяти 50 объектами означало бы ~ 400-500 КБ на объект Person. Это примерно так? Если это так, вам, вероятно, понадобится стратегия управления памятью, которая не хранит в памяти все объекты одновременно. Core Data, вероятно, может вам очень помочь в этом случае.

person Ole Begemann    schedule 04.11.2009
comment
Привет, Оле. Спасибо. Я искал кое-какие идеи по этому поводу :) Мои объекты Person имеют размер около 0,1 КБ за штуку. Я начинаю думать, что это веб-сервис, откуда я получаю данные, которые действуют. Я продолжал тестирование с разным количеством xml, залитым в мой скрипт, и он не вылетал постоянно в симуляторе. Мне кажется, что если я запустил его с инструментами, он не вылетит, а просто вырастет до ≈250 МБ. Я считаю, что Натан что-то понял, Instruments не может найти никаких утечек, и в момент завершения синтаксического анализа (и выпуска URLConnection и XMLParser) выделенные МБ увеличиваются с 250 до 1,5. Спасибо:) - person RickiG; 04.11.2009
comment
У меня есть основная модель данных, но я бы действительно подумал, что это безумие использовать ее для отображения 50 результатов поиска. Я думаю, что ошибка зарыта в другом месте, может мне стоит притормозить и лучше изучить инструменты инструментов. Спасибо - person RickiG; 04.11.2009

Несмотря на то, что NSXMLParser является синтаксическим анализатором на основе SAX, он не поддерживает синтаксический анализ входного потока, что означает, что вся строка XML, которую вы анализируете, хранится в памяти. Само по себе это большая проблема, но по мере анализа проблема усугубляется, когда вы начинаете дублировать строковые данные из XML в своих Person объектах.

Если ваши строки действительно большие, у вас есть вторая проблема - слишком много Person объектов в памяти одновременно.

Первую проблему можно решить, используя AQXMLParser из библиотеки Джима Дови AQToolkit, которая предоставляет NSXMLParser-подобный API но с поддержкой потоковой передачи данных с диска.

Вторая проблема может быть решена с использованием технологии сохранения на основе диска, такой как Core Data, SQLite Persistent Objects, или даже просто сохранения объектов Person на диске самостоятельно.

person Nathan de Vries    schedule 04.11.2009
comment
Спасибо, Натан. Это ошеломляет меня :) Я был уверен, что парсер SAX будет читать поток, а не просто кусок из памяти: / Я попытаюсь заблокировать ToolKit, который вы рекомендуете, спасибо за устранение этого недоразумения по поводу NSXMLParser для меня! - person RickiG; 04.11.2009
comment
Я также должен был упомянуть, что вам на самом деле не нужен весь AQToolkit ... просто добавьте в свой проект iPhoneNonatomic.h, AWXMLParser.h, AWXMLParser.m, AWXMLParserDelegate.h и AWXMLParserDelegate.m. Затем вы можете использовать initWithStream: API, а не initWithData: API NSXMLParser. - person Nathan de Vries; 05.11.2009

Если вы не получали предупреждения о памяти, вероятно, не по этой причине ваше приложение закрывается. В Xcode перейдите в органайзер и выберите устройство, затем щелкните вкладку консоли. Если это приложение было отключено по причинам, связанным с памятью, в журнале консоли появится системное сообщение о том, что приложение убивает приложение из-за нехватки памяти.

person Louis Gerbarg    schedule 04.11.2009
comment
Насколько я понимаю NSXMLParser, -parse - это синхронный метод, то есть он не возвращается в цикл выполнения, пока процесс синтаксического анализа не будет завершен. В таком случае вы бы не получили предупреждение о памяти, не так ли? - person Ole Begemann; 04.11.2009
comment
Это зависит ... Лично я никогда не выполняю синтаксический анализ XML в основном потоке (в первую очередь, чтобы избежать сбоев пользовательского интерфейса), поэтому основной цикл выполнения продолжает нормально обрабатывать события. - person Louis Gerbarg; 04.11.2009

Ответ - нарезать входящий поток, я недавно написал об этом: https://lukassen.wordpress.com/2010/01/15/feeding-nsxmlparser-a-stream-of-xml/

person CocoaChris    schedule 16.07.2013