MkMapView cancel loading google tiles

2020-02-14 06:10发布

I have a case where I need to import an overlay map in top of MkMapView. The overlay totally covers the google tiles below so there is no need loading, plus it adds overhead to the app.

Is there a way to tell mkMapView to stop loading tiles?

标签: ios mkmapview
3条回答
疯言疯语
2楼-- · 2020-02-14 06:21

I encountered a related problem but in my case my overlay didn't cover all the google tiles. If anyone has this problem, and is trying to stop loading the google tiles, I managed to superimpose one gray tile(256x256) overlay over the google map tiles. To do this, the top level tile must be /FakeTiles/1/1/0.png and add this directory to resources to project. (N.B. don't drag this into project > Add files > Folders > Create folder references for any folders)

//hack to overlay grey tiles
NSString *fakeTileDirectory = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"FakeTiles"];
TileOverlay *greyOverlay = [[TileOverlay alloc] initWithTileDirectory:fakeTileDirectory];
[mapView addOverlay:greyOverlay];
[greyOverlay release];

then add your custom tile overlay.

Then you need this code to scale the grey tile Calculating tiles to display in a MapRect when "over-zoomed" beyond the overlay tile set

查看更多
Summer. ? 凉城
3楼-- · 2020-02-14 06:25

As far as I know you can't prevent MKMapView from loading Google Maps tiles, and there's a chance your app will be rejected if it covers up the Google logo while displaying an MKMapView – you may want to consider writing a custom UIScrollView to display your map instead.

查看更多
够拽才男人
4楼-- · 2020-02-14 06:44

Actually there are 2 ways to implement the real "Hide Google tiles" method (johndope solution only puts an overlay on top of it but doesn't prevent the tiles from loading).

Beware that option one described below might get your application rejected while option 2 will not but is a bit more complex.

Common Part: Retrieve the MKMapTileView object

Inside each MKMapView lies an undocumented class of type: MKMapTileView. Retrieving it is NOT a reason for rejection. In this code the MKMapView instance will be called mapView

UIView* scrollview = [[[[mapView subviews] objectAtIndex:0] subviews] objectAtIndex:0];
UIView* mkTiles = [[scrollview subviews] objectAtIndex:0]; // <- MKMapTileView instance

Option 1: Undocumented Method (!! can be a reason for rejection !! )

if ( [mkTiles respondsToSelector:@selector(setDrawingEnabled:)])
    [mkTiles performSelector:@selector(setDrawingEnabled:) withObject:(id)NO];

This will prevent the undocumented method setDrawingEnabled to be called on the MKMapTileView instance.

Option 2: Method Swizzling

Outside of your controller implementation you will write someting like:

// Import runtime.h to unleash the power of objective C 
#import <objc/runtime.h>

// this will hold the old drawLayer:inContext: implementation
static void (*_origDrawLayerInContext)(id, SEL, CALayer*, CGContextRef);

// this will override the drawLayer:inContext: method
static void OverrideDrawLayerInContext(UIView *self, SEL _cmd, CALayer *layer, CGContextRef context)
{
    // uncommenting this next line will still perform the old behavior
    //_origDrawLayerInContext(self, _cmd, layer, context);

    // change colors if needed so that you don't have a black background
    layer.backgroundColor = RGB(35, 160, 211).CGColor;

    CGContextSetRGBFillColor(context, 35/255.0f, 160/255.0f, 211/255.0f, 1.0f);
    CGContextFillRect(context, layer.bounds);
}

And somewhere in your code (once your map view is loaded!) :

// Retrieve original method object
Method  origMethod = class_getInstanceMethod([mkTiles class], 
                                             @selector(drawLayer:inContext:));

// from this method, retrieve its implementation (actual work done)
_origDrawLayerInContext = (void *)method_getImplementation(origMethod);

// override this method with the one you created    
if(!class_addMethod([mkTiles class],
                    @selector(drawLayer:inContext:), 
                    (IMP)OverrideDrawLayerInContext,
                    method_getTypeEncoding(origMethod)))
{
    method_setImplementation(origMethod, (IMP)OverrideDrawLayerInContext);
}

Hope this helps anyone, this code was originally described in this blog post.

查看更多
登录 后发表回答