10

I'm hoping maybe this is just an issue with the simulator but of course it has me worried since I have already submitted my retina capable apps and there's no way to test it until the 16th.

I have implemented a CATiledLayer in my app to view very large maps. The tiles for the map are coming from the internet, however they also get cached, so, typically, they are actually being loaded directly from the device.

On iPad 1 and iPad2 it works beautifully. You can only barely notice the tiles being rendered on the iPad 2, even when they are coming from the internet.

On the iPad Simulator it works beautifully.

My problem is the iPad retina simulator. Visually, it looks okay. The map is sized properly and lines up with another layer I use to display a data overlay, however it loads INCREDIBLY slowly. Most of the time I try, it won't load any tiles at all until I begin scrolling, then when it is loading tiles it's doing maybe 1 per second and looks terrible.

I have no code that would run differently on the retina than the standard resolution screen, so I'm hoping this is just an issue with the simulator...but I'm still concerned.

Has anyone else seen this in their own apps?

Alexsander Akers
  • 15,967
  • 12
  • 58
  • 83
Brodie
  • 3,526
  • 8
  • 42
  • 61

4 Answers4

14

Bigger tile sizes were kind of working for me, however when I would adjust the levelsOfDetailBias property of the CATiledLayer, it would go back to making tiny tiles and it would take forever to load. Turning off detail biasing was unacceptable as zooming into the view needed to look sharp, so I looked at some of Apple's docs - https://web.archive.org/web/20120323033735/http://developer.apple.com/library/ios/samplecode/ZoomingPDFViewer/Listings/Classes_PDFScrollView_m.html - and one of their suggestions was to override the layoutSubviews method of your tiled view to always set the contentScaleFactor = 1. The only thing I had to do after that was call setNeedsLayout every time scrollViewDidEndZooming fired. This is assuming you are using a UIScrollView. I have tested this on my iPad(3rd Gen) and iPad2, both seem to work very well. Hope that helps.

Example Code - Assuming you are subclassing a UIView and overriding the view's backing layer with a 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;
    }

then assuming your View Controller is setup as a UIScrollViewDelegate -

    -(void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale{
        //do any other stuff you may need to do.
       [view setNeedsLayout];
    }
Michael Kohne
  • 11,888
  • 3
  • 47
  • 79
mzider
  • 156
  • 1
  • 5
  • Im trying this out but I'm not seeing any difference? Should this be having the same affect as doubling the tiles then effectively negating the retina display? – Brodie Mar 24 '12 at 15:56
  • It is telling iOS to handle tile sizes like it ordinarily would on a non-retina display instead of trying to scale them, although that may not be the case depending on your implementation. One thing you should double check is tilesize, you will still need to boost it to 1024X1024, & if it's a PDF you are displaying, the rendering time can vary based on the size and quality of the PDF. In my implementation, certain PDFs open faster and tile less than others, I am still digging into why that is. If you post some code I will be more than happy to take a look at it. – mzider Mar 26 '12 at 11:45
  • This doesn't work for us. Hope someone can share more solutions. – Manny Apr 19 '12 at 10:56
  • @mzider, can you give the link to Apple's docs where you saw this suggestion on? Thanks! – Altealice Apr 20 '12 at 03:21
  • 1
    @Altealice You can find their suggestion in the ZoomingPDFViewer Example - http://bit.ly/JwA1YD The exact quote is this - "// to handle the interaction between CATiledLayer and high resolution screens, we need to manually set the // tiling view's contentScaleFactor to 1.0. (If we omitted this, it would be 2.0 on high resolution screens, // which would cause the CATiledLayer to ask us for tiles of the wrong scales.) pdfView.contentScaleFactor = 1.0;" – mzider Apr 22 '12 at 02:21
  • @Manny, one of the things I found was that you can experiment w/contentScaleFactor. I ended up dropping it to .5 just to see if performance was better & I noticed an immediate improvement. However, you need to make sure the app is running on a 3rd gen iPad, as it will look blurry on iPad2. Again, this may depend on your implementation, & depending on what you are tiling, your LOD, as well as your LOB, your results will vary. Otherwise, the only other thing I do is to layout the subviews in the CGRect of the parent View's frame. I hope this helps. – mzider Apr 22 '12 at 02:43
  • Naturally, dropping the contentScaleFactor to 0.5 will improve performance: this causes it to render 1/4th of the pixels as a CSF of 1.0. If you actually look at the results, though, you'll notice blurry, choppy text and images, because you're rendering at non-retina (iPad 2) resolution. Faster, yes, but not nearly as nice to look at. – dkmp Jul 06 '12 at 17:49
4

The performance on iPad3 of all TiledLayers is worse than on iPad2 - that's also visible in the GoogleMaps app.

However, the best performance you get by adding the following changes to your UIView class that uses 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;
    }
}

There are other options to achieve the same result visually ie increasing tileSize but the performance will be much worse.

jfischer
  • 281
  • 2
  • 9
  • 1
    Note my comment above: setting contentScaleFactor to .5 causes the layer to render at iPad 2 (non retina) resolution, which may not be acceptable to many of us. – dkmp Jul 06 '12 at 17:50
3

CATiledLayer performance on the simulator seems to be nothing like that of that on an actual new iPad. Test on actual hardware.

CATiledLayer generates a lot more tiles on the new iPad than on older devices, even when using the same settings. At the moment I detect whether the code is running on a hires screen (via CALayer's contentScale property), and if so, set a bigger tile size.

I'll be doing more experimentation, and will post any significant findings here.

Kenshi
  • 728
  • 6
  • 8
  • 1
    Thanks - I've found the same thing and the problem with my app is that it's displaying 4x the tiles. Yes it looks sharp but when an average user holds my app on an iPad 3 next to an iPad 1 and displays the map - the iPad 1 beats the iPad 3 by a long shot at displaying the map. is there a way to change this behavior without modifying the tile images? (I have hundreds of thousands of tiles). – Brodie Mar 19 '12 at 20:06
  • I don't think you'd need to modify your tile images. You probably just need to explicitly set the tileSize property on the CATiledLayer to a larger size, when the code is running on a high res display. – Kenshi Mar 22 '12 at 23:35
0

Remember, it's just a simulator and it's most likely software accelerated. On the other hand, the device is hardware accelerated and Core Animation is highly optimized, since there are only few target GPUs to look for.

Until you check your performance on the new iPad itself I wouldn't be concerned with simulator results.

Bartosz Ciechanowski
  • 10,293
  • 5
  • 45
  • 60