2013-10-08 5 views
10

HintergrundPolygon-Overlays sich stören, wenn eine MKPolygon mit einem CGPattern (mit Quartz 2D) Füllung

In iOS6, habe ich mehr MKPolygon (Overlays) auf dem MKMapView hinzuzufügen und ein spezifisches MKOverlayView zur Verfügung zu stellen die mapView:viewForOverlay: Rückruf (siehe MKMapViewDelegate Class Reference). Die Aufgabe dieser bestimmten Ansicht bestand darin, das Polygon mit einem benutzerdefinierten Muster unter Verwendung von Quartz 2D zu füllen. Es hat gut funktioniert.

Nun, dies scheint nicht mehr auf iOS7 zu arbeiten, wie ich es zu tun pflegte.

Da mapView:viewForOverlay: in iOS SDK7 veraltet sowie MKOverlayView und ihre Unterklassen, ich habe Schalt versucht mapView:rendererForOverlay: und Subklassifizieren MKOverlayRenderer ohne Erfolg: Die aufgetretenen Probleme sind die gleichen.

Die folgenden Beispielcodes wird daher MKOverlayView verwenden, aber Sie können leicht Ansicht/View mit Renderer/Renderer in den Code unten und Sie erhalten die gleiche Wirkung ersetzen.

Problem aufgetreten

Ich habe das Problem auf den kleinsten Codebeispiel kann reduziert es und das Ergebnis reproduzieren ist die folgende:

Auf iOS6 (wie erwartet): On iOS6 (as expected)

Auf iOS7 (nicht wie erwartet): On iOS7 (not as expected)

Ich erwarte mein Polygon s gefüllt, immer mit dem gleichen Muster, und dass die Größe des Musters unabhängig vom Zoom-Level der Karte auf dem Bildschirm gleich bleibt.

Ach, auf iOS7 und beim Hinzufügen von mehr als einem Overlay auf der Karte, die Größe des Musters auf dem Bildschirm ab, während auf einem Teil des Polygons Auszoomen. Das Muster erhält nur dann die richtige Größe, wenn mit maximaler Zoomstufe herangezoomt wird.

Das Problem scheint nicht:

  • Beim Hinzufügen nur eine Overlay
  • Wenn Overlays gut
  • für die Überlagerung mit dem niedrigsten Index (Beim Hinzufügen mehr Overlays mit mapView:insertOverlay:atIndex:)
beabstandet sind,

Das Problem scheint zu passieren, auch wenn nur ein gemustertes Overlay sowie andere nicht gemusterte Overlays hinzugefügt wurden.

Codebeispiele

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 

Frage

Ich bin auf dem Weg dies als Fehler auf dem Apple-Bug-Tracker zu melden, aber ich wollte zuerst prüfen, ob jemand anderes finde einen Fehler in meinem Gebrauch der MapKit und Quartz 2D.

Edit # 1: Ich habe versucht, fillPath ‚s Code Thread-sicher, indem es in einem dispatch_sync Anruf auf einer gemeinsamen Warteschlange zu machen Einwickeln aber nicht das Problem zu beheben.

Edit # 2: Nicht 7.0.3

+0

mapView: viewForOverlay: in IOS 7 –

+0

Dank veraltet, aber haben Sie gelesen meine Frage? 3. Absatz Ich sage, ich weiß, es ist veraltet und das Problem ist das gleiche mit ViewForRenderer. –

+0

Sie können einfach sed '/ View/Renderer/g' in meinem Code und erhalten das gleiche Ergebnis. –

Antwort

0

Problem war eigentlich ein Bug in iOS fixiert und adressiert von iOS 7.1

Verwandte Themen