Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.3k views
in Technique[技术] by (71.8m points)

ios - MkMapView cancel loading google tiles

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...