In iOS6, sono usati per aggiungere vari MKPolygon
(overlay) sulla MKMapView e per fornire una specifica MKOverlayView
a la richiamata mapView:viewForOverlay:
(vedere MKMapViewDelegate Class Reference). Il compito di questa specifica vista era di riempire il poligono con un motivo personalizzato usando Quartz 2D. Ha funzionato bene.
Ora, questo non sembra funzionare più su iOS7 come in passato.
Poiché mapView:viewForOverlay:
è obsoleto in IOS SDK7 nonché MKOverlayView
e le sue sottoclassi, ho cercato di passare a mapView:rendererForOverlay:
e sottoclassi MKOverlayRenderer
senza successo: I problemi riscontrati sono gli stessi.
I seguenti codici di esempio utilizzeranno pertanto MKOverlayView ma è possibile sostituire facilmente view/View con renderer/Renderer nel codice seguente e ottenere lo stesso effetto.
problema riscontrato
ho ridotto il problema al campione più piccolo codice in grado di riprodurre e il risultato è il seguente:
On iOS6 (come previsto):
Su iOS7 (non come previsto):
Mi aspetto di avere il mio poligono s riempito, sempre con lo stesso modello, e che le dimensioni del modello rimangono le stesse sullo schermo indipendentemente dal livello di zoom della mappa.
Purtroppo, su iOS7 e aggiungendo più di una sovrapposizione sulla mappa, le dimensioni del modello sullo schermo diminuiscono mentre si riduce lo zoom su una parte del poligono. Il modello ha le giuste dimensioni solo quando si ingrandisce al massimo livello di zoom.
Il problema non sembra:
- Quando si aggiunge un solo overlay
- Quando le sovrapposizioni sono ben distanziati
- Per la sovrapposizione con l'indice più basso (Quando si aggiungono diverse sovrapposizioni con
mapView:insertOverlay:atIndex:
)
Il problema sembra verificarsi anche quando è stata aggiunta solo una sovrapposizione con motivi e altre sovrapposizioni non modellate.
Esempi di codice
MTViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface MTViewController : UIViewController<MKMapViewDelegate>
@property (strong, nonatomic) IBOutlet MKMapView *mapView;
@end
MTViewController.m
#import "MTViewController.h"
#import <MapKit/MapKit.h>
#import "MTPolygonWithPatternOverlayView.h"
@implementation MTViewController
- (void)dealloc {
self.mapView.delegate = nil;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = @"MapTest - CGPattern";
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.mapView.delegate = self;
// Add a 4 polygon overlays on the map
int count = 0;
float delta = 0.012;
for (int i = 0; i < 4; i++) {
CLLocationCoordinate2D coords[4];
coords[0] = CLLocationCoordinate2DMake(58.395,15.555 + (i*delta));
coords[1] = CLLocationCoordinate2DMake(58.390,15.560 + (i*delta));
coords[2] = CLLocationCoordinate2DMake(58.385,15.555 + (i*delta));
coords[3] = CLLocationCoordinate2DMake(58.390,15.550 + (i*delta));
MKPolygon *overlay = [MKPolygon polygonWithCoordinates:coords count:4];
[self.mapView insertOverlay:overlay atIndex:count++];
}
// Zoom to region containing polygons
MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake(58.390,15.561), MKCoordinateSpanMake(0.015, 0.015));
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:NO];
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id<MKOverlay>)overlay {
MKOverlayView *overlayView = nil;
if ([overlay isKindOfClass:[MKPolygon class]]) {
MTPolygonWithPatternOverlayView *polygonOverlayView = [[MTPolygonWithPatternOverlayView alloc] initWithPolygon:overlay];
polygonOverlayView.alpha = 1.0f;
polygonOverlayView.strokeColor = [UIColor blueColor];
polygonOverlayView.lineWidth = 3.0f * [[UIScreen mainScreen] scale];
overlayView = polygonOverlayView;
}
return overlayView;
}
@end
MTPolygonWithPatternOverlayView.h
#import <MapKit/MapKit.h>
@interface MTPolygonWithPatternOverlayView : MKPolygonView
@end
MTPolygonWithPatternOverlayView.m
#import "MTPolygonWithPatternOverlayView.h"
@implementation MTPolygonWithPatternOverlayView
void patternReleaseInfoCallback(void *info) {
}
void drawPatternCell(void *info, CGContextRef context) {
float cellWidth = CGContextGetClipBoundingBox(context).size.width;
float cellHeight = CGContextGetClipBoundingBox(context).size.height;
// Make line width look constant on screen independently of map zoom level
CGFloat lineWidth = [[UIScreen mainScreen] scale] * cellWidth/64.0f;
CGContextSetLineWidth(context, lineWidth);
// Draw following pattern in cell:
// \ /
// \ /
// \ _/
// |_|
// / \
/// \
/// \
// Draw diagonal
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGPoint points [] = {{0.0,0.0}, {cellWidth,cellHeight }, {cellWidth,0.0}, {0.0,cellHeight}};
CGContextStrokeLineSegments(context, points, 4);
// Draw middle square
CGContextSetFillColorWithColor(context, [UIColor blackColor].CGColor);
float partWidth = cellWidth/8;
CGRect middleSpot = CGRectMake(partWidth * 3, partWidth*3, 2* partWidth, 2*partWidth);
CGContextFillRect(context, middleSpot);
}
- (void)fillPath:(CGPathRef)path inContext:(CGContextRef)context {
CGPatternCallbacks callBack;
callBack.drawPattern = &drawPatternCell;
callBack.releaseInfo = &patternReleaseInfoCallback;
callBack.version = 0;
float cellWidth = CGContextGetClipBoundingBox(context).size.width/4;
CGPatternRef pattern = CGPatternCreate(NULL, CGRectMake(0.0f, 0.0f, cellWidth, cellWidth), CGAffineTransformIdentity, cellWidth, cellWidth, kCGPatternTilingConstantSpacing, true, &callBack);
CGContextSaveGState(context);
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern (NULL);
CGContextSetFillColorSpace (context, patternSpace);
CGContextAddPath(context, path);
float alpha = 1;
CGContextSetFillPattern(context, pattern, &alpha);
CGContextDrawPath(context, kCGPathFill);
CGContextRestoreGState(context);
CGColorSpaceRelease (patternSpace);
CGPatternRelease(pattern);
}
@end
Domanda
sto sul mio modo di segnalare questo come un bug sul bug tracker di Apple, ma ho voluto verificare prima se qualcun altro trova un difetto nel mio utilizzo MapKit e Quartz 2D.
Modifica # 1: Ho cercato di rendere filo codice fillPath
's sicuro avvolgendolo in un dispatch_sync
chiamata su una coda comune, ma non risolvere il problema.
Edit # 2: Non fissato in iOS 7.0.3
MapView: viewForOverlay: è deprecato in IOS 7 –
Grazie, ma hai letto la mia domanda? 3 ° paragrafo, dico che so che è deprecato e che il problema è lo stesso con viewForRenderer. –
Puoi facilmente sed/s/Visualizza/g 'nel mio codice e ottenere lo stesso risultato. –