2013-05-25 2 views
1

Так я разрабатываю приложение IOS, которая в основном выполняет следующие действия: На iPhone это UITabBarController с пять вкладок, на IPad у меня есть UISplitViewController с MKMapView на правой стороне и UITabBarController с четырьмя вкладки слева. Приложение использует ARC.уменьшить использование памяти

Предположим, что речь идет о достопримечательностях.
В зависимости от текущего города, в котором находится пользователь, мое приложение загружает все достопримечательности этого города на устройство. Как только определенный прицел был загружен, он хранится в моем локальном db, чтобы пользователь не загружал его снова. Если пользователь ищет другой город, будут загружены все достопримечательности этого города. И так далее. Все сохраненные достопримечательности будут перечислены внутри tableView или mapView, отсортированные по их городу.

Прицел состоит из:

  • 1-10 изображений
  • мета информация (название, подзаголовок, название, описание, адрес, город, страна, рейтинг, ID, широта, долгота ...)
  • принадлежит к 1-н категории/теги

приложение позволяет пользователю создавать новые достопримечательности, снимать его, заполнить его мета информацию и загрузить его на моем веб-сервере.

Все это работает нормально, пока загружено только небольшое количество достопримечательностей. Благодаря 40 + локациям, сохраненным в памяти, я получаю предупреждения о памяти и приложение закрывается. Проблема в том, что приложение предназначено для просмотра очень большого количества достопримечательностей, нескольких сотен.

Теперь я хотел бы знать некоторые методы для решения таких проблем с памятью.

Я думаю, моя проблема в том, что с началом моего приложения все локально сохраненные объекты загружаются в массив в качестве источника данных для tableView или mapView. Но так как я хочу их отображать, я не вижу другого выхода, кроме этого.

Как другие приложения имеют дело с огромным количеством пользовательских объектов, состоящих из нескольких изображений и нескольких метаинформаций или подобных? Существует ли какая-то передовая практика для решения этой проблемы?

спасибо, что заблаговременно!

ответ

3

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

Если вы используете представление таблицы или коллекции, iOS обрабатывает это очень изящно, вызывая cellForRowAtIndexPath источника данных и только в это время вы должны создать UIImage. И когда ячейка прокручивается, если вы выполняете типичную реализацию cellForRowAtIndexPath, эту ячейку мы повторно используем для другой строки в таблице, вы переназначите image ячейки новой UIImage и при условии, что старое изображение предположительно не имеет более сильных ссылок, он будет выпущен, и память, полученная с помощью изображения, будет освобождена.

Несколько дополнительных мыслей:

  1. Вы говорите, что информация загружается в локальную базу данных. Вы загружаете URL-адреса для изображений, или вы фактически помещаете изображения, сами, в базу данных. По моему опыту, если вы имеете дело с чем-то другим, кроме очень маленьких миниатюр, вы не хотите сохранять изображение в самой базе данных (поскольку база данных iOS довольно неэффективна с точки зрения экономии больших блоков), и вы увидите удар производительности. Если изображения, скажем, более 100 кб каждый, вы можете загрузить изображения в папку с документами и сохранить только URL-адрес файла/путь для изображения в своей базе данных.

  2. Если в приложении отображается много изображений за один раз (например, приложение для iPad, и у вас есть браузер эскизов фотографий, который может показывать, например, более 20 изображений за раз), вы можете захотеть убедиться, что изображение, которое вы загружаете свой пользовательский интерфейс, соответствующим образом. Например, в то время как iOS может изящно принимать изображения с высоким разрешением и показывать вам миниатюру с небольшим UIImageView с UIViewContentModeAspectFill, это может быть экстравагантное использование памяти. Я использую image resizing algorithm, в результате чего я изменил размер изображений на соответствующий размер для моего пользовательского интерфейса, сохранив память. Вам действительно нужно беспокоиться об этом, если ваши изображения огромны или если вы показываете много миниатюр одновременно.

  3. После того, как вы изменили свое приложение, чтобы загрузить изображения в объекты UIImage на лету, вы можете стать чувствительными к дополнительным соображениям производительности, которые вы, возможно, не испытали до сих пор. Типичным решением является использование кеширования, при котором вы сохраняете изображения, которые вы недавно загрузили в объект NSCache, но этот кеш будет автоматически опустошен, если устройство будет работать с низким объемом памяти. Так что это лучшее из обоих миров; производительность, которую вы привыкли испытывать при загрузке всех ваших изображений за один раз, но с большей чувствительностью к изящному обращению с низкой ситуацией с памятью. Кстати, сторонние классы вроде SDWebImage делают это кэширование для вас автоматически.

+0

Спасибо за подробный ответ! До сих пор я фактически сохранил изображения в базе данных. Я думаю, что это одна из главных причин, по которым производительность снижается, и я изменю это, чтобы хранить только их пути внутри db. Кроме того, я больше не буду загружать все объекты моего зрения, а только те, которые предназначены для одного города. Если пользователь ищет новый город, приложение может выгрузить предыдущие достопримечательности. Также я никогда не смотрел NSCache или SDWebImage, я предполагаю, что я собираюсь использовать это. – pmk

1

Вы должны загрузить только некоторую информацию о данных, которые вы хотите показать, например ID, заголовок, который вы будете использовать для заполнения начальной информации, а остальную информацию, например изображения, вам нужно будет загрузить на фон, и обновление, когда они будут готовы, вы посмотрите на это можете отвечает, например:

UICollectionView scrolling is slow

Также вы должны позаботиться о том, не будет оставаться со всеми Infos, когда ваши данные не показывая на экране.

+0

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

2

Путь я обращался с использованием тонны изображений было с помощью

https://github.com/rs/SDWebImage

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

+0

Спасибо за ваш ответ! Когда я ответил на другие ответы, я обязательно посмотрю на SDWebImage. – pmk

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