Ограничения памяти iPad - PullRequest
       23

Ограничения памяти iPad

3 голосов
/ 07 февраля 2012

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

Приложение загружает из Интернета XML-файл, содержащий набор вопросов, а затем генерирует UIScrollView, который отображает список элементов управления вопросами. Каждый элемент управления вопросом имеет UITextView и UISegmentedControl, UIButton, UITableView, UITextField или четыре UITextFields с UIButton (пользовательский элемент управления датой). Вот скриншот:

http://i.imgur.com/vpa9Z.png

Эта установка прекрасно работает для небольших наборов вопросов, но приложение начинает выдавать предупреждения памяти с большими наборами более 120 вопросов. Вот типичный прогон с распределениями и инструментами VM Tracker на большем наборе:

http://i.imgur.com/gyWOX.png

Пик памяти Allocations при загрузке xml и загрузке модели, но предупреждения не выдаются до тех пор, пока память Allocations не загрузится. Хотя память VM Tracker все еще увеличивается, когда они выбрасываются, это заставляет меня думать, что элементы управления все еще загружаются в память, и что VM Tracker является лучшим индикатором роста памяти, вызывающего предупреждения. Обычно предупреждения появляются, когда размер резидента становится больше 125 МБ. Я нашел один способ значительно уменьшить размер резидента. Элементы управления вопросом имеют пользовательское представление, чтобы дать им закругленные края и тень. Если я закомментирую код drawRect (показанный ниже) из пользовательского представления, память Allocations останется прежней, но Resident Size уменьшится примерно на 30 МБ и не превысит 93 МБ. Я могу найти более светлый фон для вопросов, но я бы предпочел сохранить закругленные края и тень, если смогу уменьшить объем памяти.

- (void)drawRect:(CGRect)rect {
    // get the contect
    CGContextRef context = UIGraphicsGetCurrentContext();

    //for the shadow, save the state then draw the shadow
    CGContextSaveGState(context);
    CGContextSetShadow(context, CGSizeMake(4,-5), 10);

    //now draw the rounded rectangle
    CGContextSetStrokeColorWithColor(context, [[UIColor blackColor] CGColor]);  

    if(_HighlightColor==nil){
        _HighlightColor = [[UIColor whiteColor] retain];
    }
    CGContextSetFillColorWithColor(context, _HighlightColor.CGColor);

    //since I need room in my rect for the shadow, make the rounded rectangle a little smaller than frame
    CGRect rrect = CGRectMake(CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetWidth(rect)-30, CGRectGetHeight(rect)-30);
    CGFloat radius = 5;
    // the rest is pretty much copied from Apples example
    CGFloat minx = CGRectGetMinX(rrect), midx = CGRectGetMidX(rrect), maxx = CGRectGetMaxX(rrect);
    CGFloat miny = CGRectGetMinY(rrect), midy = CGRectGetMidY(rrect), maxy = CGRectGetMaxY(rrect);

    // Start at 1
    CGContextMoveToPoint(context, minx, midy);
    // Add an arc through 2 to 3
    CGContextAddArcToPoint(context, minx, miny, midx, miny, radius);
    // Add an arc through 4 to 5
    CGContextAddArcToPoint(context, maxx, miny, maxx, midy, radius);
    // Add an arc through 6 to 7
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    // Add an arc through 8 to 9
    CGContextAddArcToPoint(context, minx, maxy, minx, midy, radius);
    // Close the path
    CGContextClosePath(context);
    // Fill & stroke the path
    CGContextDrawPath(context, kCGPathFillStroke);

    //for the shadow
    CGContextRestoreGState(context);
}

Приборы и предупреждения памяти создают впечатление, что память исчерпана, но эти цифры кажутся мне высокими. Я бы не подумал, что 120 из этих элементов управления вопросами в виде прокрутки будут проблемой для iPad, но у меня нет ориентира относительно того, сколько памяти они должны использовать. Учитывая некоторые графически интенсивные игры, которые может запускать iPad, не похоже, что простой код drawRect, приведенный выше, потребляет более 30 МБ в элементах управления вопросом. Это потребление памяти кажется высоким или это то, что вы ожидаете от приложения с таким количеством простых элементов пользовательского интерфейса? Есть ли в drawRect что-то, что могло бы поглотить много памяти или какие-либо предложения по его оптимизации? Если кажется, что это должно максимально увеличить память iPad, я буду создавать вкладки или страницы и ограничивать количество вопросов, которые я задаю на вкладку / страницу, так что только часть элементов управления будет загружена в память одновременно. Однако я бы не стал разбивать их, если бы iPad мог обрабатывать их все в памяти. Любой вклад приветствуется.

Ответы [ 2 ]

4 голосов
/ 07 февраля 2012

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

Плохие новости: это кэширование и подкачка довольно сложно настроить.

Хорошие новости: UITableView сделает это за вас!

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

2 голосов
/ 07 февраля 2012

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

Также убедитесь, что в вашей программе нет утечек.

...