2013-10-08 16 views
10

nềnlớp Polygon can thiệp với nhau khi điền một MKPolygon với một CGPattern (sử dụng Quartz 2D)

Trong iOS6, tôi sử dụng để thêm vài MKPolygon (lớp phủ) trên MKMapView và để cung cấp một MKOverlayView cụ thể để cuộc gọi lại mapView:viewForOverlay: (xem MKMapViewDelegate Class Reference). Công việc của chế độ xem cụ thể này là điền vào đa giác với mẫu tùy chỉnh bằng cách sử dụng Quartz 2D. Nó đã làm việc tốt.

Hiện tại, điều này dường như không hoạt động được trên iOS7 theo cách tôi đã sử dụng để thực hiện.

mapView:viewForOverlay: bị phản đối trong iOS SDK7 cũng như MKOverlayView và lớp con của nó, tôi đã cố gắng chuyển sang mapView:rendererForOverlay: và subclassing MKOverlayRenderer nhưng không thành công: Những vấn đề gặp phải đều giống nhau.

Các mã mẫu sau đây sẽ sử dụng MKOverlayView nhưng bạn có thể dễ dàng thay thế chế độ xem/xem bằng trình kết xuất/Renderer trong mã dưới đây và nhận được cùng một hiệu ứng.

Vấn đề gặp phải

Tôi đã giảm được vấn đề với mẫu mã nhỏ nhất có thể sao chép nó và kết quả là như sau:

On iOS6 (như dự kiến): On iOS6 (as expected)

Trên iOS7 (không như mong đợi): On iOS7 (not as expected)

Tôi hy vọng sẽ có đa giác của tôi s được lấp đầy, luôn luôn có cùng một mẫu và kích thước của mẫu vẫn giữ nguyên trên màn hình độc lập với mức thu phóng của bản đồ.

Than ôi, trên iOS7 và khi thêm nhiều lớp phủ trên bản đồ, kích thước của mẫu trên màn hình giảm khi thu nhỏ một số phần của đa giác. Mẫu chỉ có kích thước phù hợp khi phóng to ở mức thu phóng tối đa.

Vấn đề không xuất hiện:

  • Khi thêm chỉ có một lớp phủ
  • Khi lớp phủ được cũng cách nhau
  • Đối với lớp phủ với chỉ số thấp nhất (Khi thêm vài lớp phủ với mapView:insertOverlay:atIndex:)

Sự cố dường như xảy ra ngay cả khi chỉ có một lớp phủ được tạo mẫu cũng như các lớp phủ không có hoa văn khác.

mẫu Mã

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 

Câu hỏi

Tôi đang trên đường đến báo cáo này như là một lỗi trên theo dõi lỗi của Apple nhưng tôi muốn kiểm tra đầu tiên nếu người khác tìm thấy một lỗ hổng trong việc sử dụng MapKit và Quartz 2D của tôi.

Chỉnh sửa # 1: Tôi đã cố gắng để làm cho fillPath của mã đề an toàn bằng cách gói nó trong một cuộc gọi dispatch_sync trên một hàng đợi thông thường nhưng nó không giải quyết vấn đề.

Chỉnh sửa # 2: Không cố định trong iOS 7.0.3

+0

MapView: viewForOverlay: bị phản đối trong IOS 7 –

+0

Cảm ơn, nhưng có bạn đọc câu hỏi của tôi? Đoạn 3 Tôi nói tôi biết nó không được chấp nhận và vấn đề là như nhau với viewForRenderer. –

+0

Bạn có thể dễ dàng sed 's/View/Renderer/g' trong mã của tôi và nhận được kết quả tương tự. –

Trả lời

0

Issue là thực sự là một lỗi và giải quyết từ iOS 7.1

Các vấn đề liên quan