Update : 3/2018 AR enabled version with ARKit available here
Suprise, iOS 9 MapKit finally enables flyeover mode with WMS overlays ! I have used my github MapKit sample and only set in MapViewController mkMapView.mapType = MKMapTypeHybridFlyover;
Update : 3/2018 AR enabled version with ARKit available here
Suprise, iOS 9 MapKit finally enables flyeover mode with WMS overlays ! I have used my github MapKit sample and only set in MapViewController mkMapView.mapType = MKMapTypeHybridFlyover;
Simple & strightforward test of loading shape file and drawing it on MapKit on iOS8 using drawMapRect
GitHub:https://github.com/Sumbera/SHPonMapKit
Reading of shape file is performed by shapelib
//------------------------------------------------------------ NS_INLINE NSArray *getPolygonsFromShapeFile(NSString *shpFilePath){ const char *path = [shpFilePath cStringUsingEncoding:NSUTF8StringEncoding]; SHPHandle shp = SHPOpen(path, "rb"); int numEntities; int shapeType; SHPGetInfo(shp, &numEntities, &shapeType, NULL, NULL); NSMutableArray *allPolygons = [[NSMutableArray alloc]init]; for (int i=0; i<numEntities; i++){ SHPObject *shpObject = SHPReadObject(shp, i); if (shpObject->nSHPType == SHPT_POLYGON || shpObject->nSHPType == SHPT_POLYGONZ || shpObject->nSHPType == SHPT_POLYGONM){ int numParts = shpObject->nParts; int totalVertexCount = shpObject->nVertices; for (int n=0; n<numParts; n++) { int startVertex = shpObject->panPartStart[n]; int partVertexCount = (n == numParts - 1) ? totalVertexCount - startVertex : shpObject->panPartStart[n+1] - startVertex; int endIndex = startVertex + partVertexCount; CLLocationCoordinate2D coords[partVertexCount]; for (int pv = startVertex, i = 0; pv < endIndex; pv++,i++) { coords[i] =CLLocationCoordinate2DMake(shpObject->padfY[pv], shpObject->padfX[pv]); } // -- this actually converts lat lon to mkmappoints projection MKPolygon *singlePolygon = [MKPolygon polygonWithCoordinates:coords count:partVertexCount]; [allPolygons addObject:singlePolygon]; } } SHPDestroyObject(shpObject); } SHPClose(shp); return [allPolygons copy]; }
credits/inspiration:
drawing : http://stackoverflow.com/questions/17673410/mkmapview-with-multiple-overlays-memory-issue
parsing : http://www.al-tyus.com/blog/2013/10/14/mapkit-and-esri-shapefiles
shapelib: http://shapelib.maptools.org
dala: http://www.geoportalpraha.cz
Sample for using WMS sources in Google Maps SDK for iOS. available on github here: https://github.com/Sumbera/WMS_iOS_GoogleMapSDK
Provide your API key in the WMSController.h
There are two ways of overlaying WMS in the Google Maps for iOS SDK:
“Method B”: use GMSTileURLConstructor
// -- method B. WMS tile layer with GMSTileURLConstructor GMSTileURLConstructor urls = ^(NSUInteger x, NSUInteger y, NSUInteger z) { BBox bbox = bboxFromXYZ(x,y,z); NSString *urlKN = [NSString stringWithFormat:@"Your WMS url&BBOX=%f,%f,%f,%f", bbox.left, bbox.bottom, bbox.right, bbox.top]; return [NSURL URLWithString:urlKN]; };
“Method A”: use custom TileLayer derived from GMSTileLayer
-(void)requestTileForX:(NSUInteger)x y:(NSUInteger)y zoom:(NSUInteger)z receiver:(id<GMSTileReceiver>)receiver
[self drawTileAtX:x y:y zoom:z Url:urlStr Receiver:receiver] ;
[data writeToFile: filePath atomically:YES]; [self drawTileAtX:x y: y zoom: z Url:urlStr Receiver:receiver] ;
-(void) drawTileAtX: (NSUInteger) x y:(NSUInteger) y zoom:(NSUInteger)zoom Url:(NSString*) url Receiver: (id<GMSTileReceiver>) receiver { UIImage *image = TileLoad(url,NO); [receiver receiveTileWithX:x y:y zoom:zoom image:image]; }
}
both ways are used in this sample.
How avoided storyboard and overloading XIB with just right split between what is visually defined and what is programatically programmed:
[super awakeFromNib];
CALayer * layer = [self.locationThumb layer];
[layer setMasksToBounds:YES];
[layer setCornerRadius:10.0];
self.view = [[UINib nibWithNibName:@”AddNoteView” bundle:nil] instantiateWithOwner:nil options:nil][0];
}
describes how to combine UITableView with other view in single UIVIewController using NIB
Sept 26th 2012 update :for erasing iOS6 base maps look here: https://blog.sumbera.com/2012/09/26/how-to-erase-ios6-maps-in-mapkit/
I have searched this and couldn’t find any answer, so here is my own research so far on this subject. You can disable MapKit base layers using 3 approaches:
#1 remove subview from MKMapView (quite bad as you will loose all overlays too)
#2 use undocumented function (bad too as this will be rejected by Apple approval process):
// get MKMapTileView from view hierarchy UIView * mkMapTileView = [((UIView*) [ ((UIView*)[self.subviews objectAtIndex:0]). subviews objectAtIndex:0]).subviews objectAtIndex:0]; // call undocumented method if ( [mkMapTileView respondsToSelector:@selector(setDrawingEnabled:)]){ [mkMapTileView performSelector:@selector(setDrawingEnabled:) withObject:(id) NO];
#3 use method swizzle
inspired by http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html
http://atastypixel.com/blog/making-uitoolbar-and-uinavigationbars-background-totally-transparent/
this method is fine as it is official method and enables you to ‘subclass’ a class that you don’t have access in compile time.
#import <objc/runtime.h> // original method declaration static void (*_origDrawLayerInContext)(id, SEL, CALayer*, CGContextRef); // set up subclass in runtime..in some entering method UIView * mkMapTileView = [((UIView*) [ ((UIView*)[self.subviews objectAtIndex:0]). subviews objectAtIndex:0]).subviews objectAtIndex:0]; Method origMethod = class_getInstanceMethod([mkMapTileView class], @selector(drawLayer:inContext:)); _origDrawLayerInContext = (void *)method_getImplementation(origMethod); if(!class_addMethod([mkMapTileView class], @selector(drawLayer:inContext:), (IMP)OverrideDrawLayerInContext, method_getTypeEncoding(origMethod))) method_setImplementation(origMethod, (IMP)OverrideDrawLayerInContext); // implement our Override static void OverrideDrawLayerInContext(UIView *self, SEL _cmd, CALayer *layer, CGContextRef context) { // possibly call original method if you leave it empty base google maps will not be displayed. You can draw custom content here as well... // _origDrawLayerInContext(self, _cmd, layer, context);
}