CATiledLayer в iPad Retina Simulator дает низкую производительность

Я надеюсь, что, возможно, это просто проблема с симулятором, но, конечно, меня это беспокоит, так как я уже представил свои приложения, поддерживающие сетчатку, и до 16-го числа нет возможности протестировать его.

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

На iPad 1 и iPad2 все работает прекрасно. Вы можете едва заметить плитки, отображаемые на iPad 2, даже если они поступают из Интернета.

На симуляторе iPad работает прекрасно.

Моя проблема - симулятор сетчатки iPad. Визуально это выглядит хорошо. Карта имеет правильный размер и выровнена с другим слоем, который я использую для отображения наложения данных, однако она загружается НЕВЕРОЯТНО медленно. Большую часть времени я пытаюсь, он не будет загружать никакие плитки, пока я не начну прокручивать, тогда, когда он загружает плитки, он делает, возможно, 1 в секунду и выглядит ужасно.

У меня нет кода, который работал бы на сетчатке иначе, чем экран со стандартным разрешением, поэтому я надеюсь, что это просто проблема с симулятором... но я все еще обеспокоен.

Кто-нибудь еще видел это в своих приложениях?

4 ответа

Решение

Большие размеры плиток работали для меня, однако, когда я настраивал свойство levelsOfDetailBias в CATiledLayer, это возвращалось к созданию крошечных плиток, и загрузка длилась бы вечно. Отключение смещения деталей было недопустимо, поскольку для увеличения масштаба необходимо было увеличить изображение, поэтому я посмотрел некоторые документы Apple - https://web.archive.org/web/20120323033735/http://developer.apple.com/library/ios/samplecode/ZoomingPDFViewer/Listings/Classes_PDFScrollView_m.html - и одно из их предложений состояло в том, чтобы переопределить метод layoutSubviews вашего плиточного представления, чтобы всегда устанавливать contentScaleFactor = 1. Единственное, что мне нужно было делать после этого, это вызывать setNeedsLayout каждый раз scrollViewDidEndZooming сработал. Это предполагает, что вы используете UIScrollView. Я проверил это на своем iPad(3-е поколение) и iPad2, оба, кажется, работают очень хорошо. Надеюсь, это поможет.

Пример кода - Предполагая, что вы создаете подкласс UIView и переопределяете вспомогательный слой представления с помощью CATiledLayer -

     -(void)layoutSubviews{
        [super layoutSubviews];
        /* 
           EDIT: After some additional experimentation, 
           I Have found that you can modify this number to .5 but you need
           to check to make sure you are working on a 3rd gen iPad. This
           seems to improve performance even further.
        */

        // Check if app is running on iPad 3rd Gen otherwise set contentScaleFactor to 1
        self.contentScaleFactor = .5;
    }

затем предположим, что ваш View Controller настроен как UIScrollViewDelegate -

    -(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale{
        //do any other stuff you may need to do.
       [view setNeedsLayout];
    }

Производительность на iPad3 всех TiledLayers хуже, чем на iPad2 - это также видно в приложении GoogleMaps.

Тем не менее, лучшую производительность вы получите, добавив следующие изменения в свой класс UIView, который использует CATiledLayer

- (id)initWithFrame:(CGRect)frame tileSize:(CGSize)tileSize
{
    self = [super initWithFrame:frame];
    if(self)
    {
        CATiledLayer *animLayer = (CATiledLayer *) self.layer;
        animLayer.levelsOfDetail = 5;
        animLayer.levelsOfDetailBias = 3;
        animLayer.tileSize = tileSize;

        // adjustments for retina displays
        if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00)
        {
            animLayer.contentsScale = 1.0;
            self.contentScaleFactor = .5;
            animLayer.shouldRasterize = NO;
            animLayer.levelsOfDetailBias ++;
        }
    }
    return self;
}

- (void)layoutSubviews
{
    [super layoutSubviews];
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES && [[UIScreen mainScreen] scale] == 2.00)
    {
        self.contentScaleFactor = .5;
    }
}

Существуют и другие варианты достижения того же результата визуально, например, увеличение tileSize, но производительность будет намного хуже.

Производительность CATiledLayer на симуляторе не похожа на таковую на новом iPad. Тест на реальном оборудовании.

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

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

Помните, это всего лишь симулятор, и, скорее всего, он ускорен программно. С другой стороны, устройство имеет аппаратное ускорение, а Core Animation высоко оптимизирована, так как целевых графических процессоров мало для поиска.

Пока вы не проверите свою производительность на новом iPad, я не буду беспокоиться о результатах симулятора.

Другие вопросы по тегам