Using CATiledLayer's drawLayer:inContext:
I am trying to implement my own map engine by using CATiledLayer
+ UIScrollView
.
In drawLayer:inContext:
method of my implementation, if I have a certain tile image needed for the current bounding box, I immediately draw it in the context.
However, when I do not have one available in the local cache data structure, the tile image is asynchronously requested/downloaded from a tile server, and not draw anything in the context.
The problem is, when I don't draw anything 开发者_运维问答in the context, that part of the view is shown as a blank tile. And the expected behavior is to show the zoom-in scaled tile view from the previous zoom level.
If you guys have faced any similar problem and found any solution for this, please let me know.
You have to setNeedsDisplayInRect: for the tile as soon as you have the data. You have to live with it being blank until the tile is available because you have no way to affect which tiles CATiledLayer is creating.
I do the same, blocking the thread until the tile has been downloaded. The performance is good, it runs smoothly. I'm using a queue to store every tile request, so I can also cancel those tile requests that are not useful anymore.
To do so, use a lock to stop the thread just after you launch your async tile request, and unlock it as soon as you have your tile cached.
Sounds that good to you? It worked for me!
Your CATiledLayer
should be providing this tile from the previous zoom level as you expect. What are your levelsOfDetail
and levelsOfDetailBias
set to for the tiled layer?
You have to call setNeedsDisplay or setNeedsDisplayInRect: But the problem is if you call this then it will redraw every tile in the scrollView. So try using subclass of UIView instead of CATiledLayer subclass, and implement TiledView (subclass of UIView) like this,
+ (Class) layerClass { return [CATiledLayer class]; } -(void)drawRect:(CGRect)r { CGRect tile = r; int x = tile.origin.x/TILESIZE; int y = tile.origin.y/TILESIZE; NSString *tileName = [NSString stringWithFormat:@"Shed_1000_%i_%i", x, y]; NSString *path = [[NSBundle mainBundle] pathForResource:tileName ofType:@"png"]; UIImage *image = [UIImage imageWithContentsOfFile:path]; [image drawAtPoint:tile.origin]; // uncomment the following to see the tile boundaries /* UIBezierPath* bp = [UIBezierPath bezierPathWithRect: r]; [[UIColor whiteColor] setStroke]; [bp stroke]; */ }
and
for scrollView,
UIScrollView* sv = [[UIScrollView alloc] initWithFrame:
[[UIScreen mainScreen] applicationFrame]];
sv.backgroundColor = [UIColor whiteColor];
self.view = sv;
CGRect f = CGRectMake(0,0,3*TILESIZE,3*TILESIZE);
TiledView* content = [[TiledView alloc] initWithFrame:f];
float tsz = TILESIZE * content.layer.contentsScale;
[(CATiledLayer*)content.layer setTileSize: CGSizeMake(tsz, tsz)];
[self.view addSubview:content];
[sv setContentSize: f.size];
精彩评论