title: Using CATiledLayer to display a large image that has been programmatically split into tiles
body: <p>I'm running into an issue with using CATiledLayer... I have a large image, a map, that is 4726 x 2701. Basically I'm needing to break this image into tiles and be able to zoom in to view a lot of detail, but also be able to zoom all the way out and see the entire map. Using my current implementation it works perfectly if the zoomlevel of the scrollview is set to 1.0 (the maximum zoomscale), but if you zoom out the tile are replaced incorrectly. </p>
  
  <p>Here the zoomlevel is set to 1.0. The map looks perfect.
  <img src="https://i.stack.imgur.com/akOq0.png" alt="enter image description here"></p>
  
  <p>But if the zoomlevel is all the way out (0.2 I believe) the map is all messed up. I should be seeing the entire map not just two tiles.</p>
  
  <p><img src="https://i.stack.imgur.com/3OXxa.png" alt="enter image description here"></p>
  
  <p>Here is how I'm getting the tiles from the large image:</p>
  
  <pre><code>- (UIImage *)tileForScale:(CGFloat)scale row:(int)row col:(int)col {
       float tileSize = 256.0f;
       CGRect subRect = CGRectMake(col*tileSize, row * tileSize, tileSize, tileSize);
       CGImageRef tiledImage = CGImageCreateWithImageInRect([mapImage CGImage], subRect);
       UIImage *tileImage = [UIImage imageWithCGImage: tiledImage];
       return tileImage;
  }
  </code></pre>
  
  <p>I'm displaying the tiles exactly like Apple does in the PhotoScroller application.</p>
  
  <pre><code>- (void)drawRect:(CGRect)rect {
      CGContextRef context = UIGraphicsGetCurrentContext();
      CGFloat scale = CGContextGetCTM(context).a;
  
      CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
      CGSize tileSize = tiledLayer.tileSize;
      tileSize.width /= scale;
      tileSize.height /= scale;
  
      int firstCol = floorf(CGRectGetMinX(rect) / tileSize.width);
      int lastCol = floorf((CGRectGetMaxX(rect)-1) / tileSize.width);
      int firstRow = floorf(CGRectGetMinY(rect) / tileSize.height);
      int lastRow = floorf((CGRectGetMaxY(rect)-1) / tileSize.height);
  
      for (int row = firstRow; row &lt;= lastRow; row++) {
          for (int col = firstCol; col &lt;= lastCol; col++) {
              UIImage *tile = [self tileForScale:scale row:row col:col];
              CGRect tileRect = CGRectMake(tileSize.width * col, tileSize.height * row,
                                       tileSize.width, tileSize.height);
              tileRect = CGRectIntersection(self.bounds, tileRect);
  
              [tile drawInRect:tileRect];
          }
      }
  }
  </code></pre>
  
  <p>Also, here is the code where I'm setting the levels of detail, which returns 4 for my image:</p>
  
  <pre><code>- (id)initWithImageName:(NSString *)name andImage:(UIImage*)image size:(CGSize)size {
      self = [super initWithFrame:CGRectMake(0, 0, size.width, size.height)];
      if (self) {
          _imageName = [name retain];
          mapImage = [image retain];
  
          CATiledLayer *tiledLayer = (CATiledLayer *)[self layer];
          tiledLayer.levelsOfDetail = [self zoomLevelsForSize:mapImage.size];
      }
      return self;
  }
  - (NSUInteger)zoomLevelsForSize:(CGSize)imageSize {
      int zLevels = 1;
      while(YES) {
          imageSize.width /= 2.0f;
          imageSize.height /= 2.0f;
          if(imageSize.height &lt; 256.0 || imageSize.width &lt; 256.0) break;
          ++zLevels;
      }
      return zLevels;
  }
  </code></pre>
  
  <p>I'm assuming it has something to do with the tile size and the zoom scale, but I really have no clue how to solve the problem. I can't seem to find any solutions to my issue on the Google. Any help would be great! :)</p>