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.
Vì 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):
Trên iOS7 (không như mong đợi):
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
MapView: viewForOverlay: bị phản đối trong IOS 7 –
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. –
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ự. –