2013-10-08 20 views
10

Sfondopoligono sovrapposizioni che interferiscono con l'altro quando si riempie un MKPolygon con un CGPattern (utilizzando Quartz 2D)

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): On iOS6 (as expected)

Su iOS7 (non come previsto): On iOS7 (not as expected)

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

+0

MapView: viewForOverlay: è deprecato in IOS 7 –

+0

Grazie, ma hai letto la mia domanda? 3 ° paragrafo, dico che so che è deprecato e che il problema è lo stesso con viewForRenderer. –

+0

Puoi facilmente sed/s/Visualizza/g 'nel mio codice e ottenere lo stesso risultato. –

risposta

0

problema è stato in realtà un bug e indirizzata da iOS 7.1