Управление памятью/ресурсами с помощью MonoTouch и MonoTouch.Dialog

У меня есть приложение MonoTouch с UITabBarController, причем каждая из вкладок является UINavigationController. Некоторые из них оборачивают UIViewController, который добавляет UITableView и UIToolbar, а другие оборачивают DialogViewController.

До сих пор я не уделял много внимания управлению памятью/представлением (в основном я работал в симуляторе), но когда я начал тестировать на реальном устройстве, я заметил некоторые сбои из-за низкой производительности. состояния памяти (например, приложение завершается, и я обнаруживаю из своего журнала, что DidReceiveMemoryWarning был вызван до этого).В других случаях я замечаю длительные паузы в отклике приложения, которые, как я предполагаю, связаны с циклом GC.

До сих пор я предполагал, что каждый DialogViewController, который я помещаю в стек навигации, очищает свои представления и другие вещи, которые он выделяет, когда я извлекаю его. Но я начинаю понимать, что это, вероятно, не так просто, и что мне нужно начать вызывать Dispose() для вещей.

Существуют ли передовые методы управления ресурсами и памятью с помощью MonoTouch и MT.D? В частности:

  • Требуется ли вызывать Dispose для DialogViewController после его извлечения? Если да, то где это лучше сделать? (ViewDidUnload? DidReceiveMemoryWarning? деструктор?)
  • DVC автоматически удаляет объекты, такие как RootElement, который передается ему, или мне нужно беспокоиться об этом? Как насчет UIImages, которые он загружает как часть рендеринга ячейки таблицы (например, StyledStringElement)?
  • Есть ли места, где я должен вызвать GC.Collect() для лучшего распределения коллекций, чтобы не получить немного потери в отзывчивости, когда GC действительно происходит?
  • Помогает ли сборщик мусора поколений решить проблемы с интерактивностью и достаточно ли он стабилен для использования в рабочем приложении? (Я полагаю, что в MonoDevelop 3.0.2 / MT 4.3.3 он по-прежнему указан как «экспериментальный»)
  • Что мне нужно сделать в DidReceiveMemoryWarning, чтобы уменьшить вероятность того, что iOS выстрелит в мое приложение? Поскольку каждый невидимый контроллер представления, похоже, получает этот вызов, я предполагаю, что мне следует очистить ресурсы этого контроллера представления...Должен ли я делать то же самое, что и в ViewDidUnload?
  • Кажется, мой ViewDidUnload не вызывается (даже после того, как я получил DidReceiveMemoryWarning). На самом деле я не помню, чтобы когда-либо видел это в своем журнале. Если бы iOS всегда вызывала мой ViewDidUnload после DidReceiveMemoryWarning, я мог бы просто выполнить всю очистку в ViewDidUnload... Как лучше всего разделить ответственность за очистку между ViewDidUnload и DidReceiveMemoryWarning?

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

Обновление: чтобы конкретизировать вопрос: после использования Instruments и профилировщик Xamarin Heapshot, мне ясно, что я пропускаю UIViewControllers, когда пользователь открывает стек навигации. Рольф подал ошибкудля этого, и у него есть два дубликата, так что это реальная проблема не только для меня. К сожалению, я не нашел хорошего обходного пути для просочившихся UIViewControllers — я не нашел подходящего места для вызова Dispose() на них. Естественным местом для освобождения ресурсов, выделенных ViewDidLoad, является сообщение ViewDidUnload, но оно никогда не вызывается в симуляторе, поэтому мой объем памяти продолжает расти. На устройстве я вижу DidReceiveMemoryWarning, но я не хочу использовать это как место для освобождения моего контроллера представления и его ресурсов, поскольку я не уверен, что iOS действительно выгрузит мое представление, и, следовательно, не гарантирует, что мой ViewDidLoad снова будет вызван либо (что привело к ViewDidAppear, который должен был бы защищаться от ситуаций, когда его основные ресурсы были удалены).Хотелось бы получить совет, как выбраться из этой заварухи...

19
задан Omri Gazitt 12 June 2012 в 20:48
поделиться