У меня есть приложение MonoTouch, у которого есть UITabBarController, причем каждая из вкладок является UINavigationController. Некоторые из них завершают UIViewController, который добавляет UITableView и UIToolbar, а другие переносят DialogViewController.
Я пока не уделял много внимания управлению памятью/представлением (я в основном работал в симуляторе), но по мере того как я начал тестировать на реальном устройстве, я заметил некоторые сбои из-за низкого (например, приложение прекращается, и я обнаруживаю из своего журнала, что DidReceiveMemoryWarning получил вызов до этого). В других случаях я замечаю, что длительные паузы в реакции приложения, которые я предполагаю, связаны с циклом GC.
До сих пор я предполагал, что каждый DialogViewController, который я нажимаю на стек nav, очищает свои представления и другие вещи, которые он выделяет, когда я его всплываю. Но я начинаю понимать, что это, вероятно, не так просто, и что мне нужно начать вызов Dispose() на вещи.
Существуют ли лучшие методы для управления ресурсами и памятью с помощью MonoTouch и MT.D? В частности:
- Требуется ли вызывать Dispose на DialogViewController после его всплытия? Если да, то где это лучше всего сделать? (ViewDidUnload? DidReceiveMemoryWarning? Destructor?)
- 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?
Извиняюсь за общий характер этого вопроса - это кажется хорошей темой для технического документа, но я не мог найти...
Обновить: чтобы сделать вопрос более конкретным: после использования инструментов и профайлера Xamarin Heapshot мне ясно, что я утечка UIViewControllers, когда пользователь всплывает стек навигации. Рольф подал bug для этого, и у него есть два дубликата, так что это реальная проблема не только для меня. К сожалению, я не нашел хорошего обходного пути для утечки UIViewControllers - я не нашел подходящего места для вызова Dispose(). Естественное место для свободных ресурсов, выделенных ViewDidLoad, находится в сообщении ViewDidUnload, но оно никогда не вызывается на симуляторе, поэтому объем памяти продолжает расти. На устройстве я вижу DidReceiveMemoryWarning, но я не хочу использовать это как место для свободного доступа к моему контроллеру и его ресурсам, поскольку мне не гарантировано, что iOS фактически выгрузит мое представление и, следовательно, не гарантирует, что мой ViewDidLoad снова будет вызван либо (приводя к ViewDidAppear, который должен был бы защищать код от ситуаций, когда были расположены его основные ресурсы). Я хотел бы получить совет о том, как выйти из этого беспорядка...