Тот же делегат MKOverlayView вызывается в одном UIView, но не в другом. Чего не хватает?
Мое приложение отслеживает движение GPS как маршрут маршрута MKPolyline на MKMapView в качестве MKOverlayRenderer в HomeVC, сохраняет данные и отображает их позже, как сохраненный маршрут на несколько глубже, на DisplayVC. Я могу подтвердить, что данные идентичны исходным данным на втором виртуальном канале, и при отображении карты используются правильные routeBounds, но OverlayRenderer никогда не вызывается на втором виртуальном канале. Почему бы и нет? Я думаю, делегировать проблемы, но я не могу найти ничего плохого.
Оба homeVC.h
@interface homeVC : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate> {
и displayVC.h одинаковы, кроме имени:
@interface displayVC : UIViewController <CLLocationManagerDelegate, MKMapViewDelegate> {
CLLocationManager *locationManager;
// the data representing the route points
MKPolyline* _routePath;
// the view we create for the line on the map
MKPolylineView* _routePathVw;
// the rect that bounds the loaded points
MKMapRect _routeBounds;
}
@property (nonatomic, weak) IBOutlet MKMapView *mapView;
@end
И homeVC.m, и displayVC.m настроены одинаково:
- (void)viewDidLoad {
[super viewDidLoad];
// Add the Map
[_mapView setDelegate:self];
_mapView.mapType = MKMapTypeStandard;
}
Здесь много хорошо работающего кода. Затем,
-(void) buildRoute {
CLLocationCoordinate2D thisCoord;
int i = [arrayLa count] - 1; // keep growing the array size
MKMapPoint *tmpArr = realloc(pointArr, sizeof(CLLocationCoordinate2D)*(arrayLa.count));
pointArr = tmpArr;
thisCoord.latitude = [[arrayLa objectAtIndex:i] floatValue];
thisCoord.longitude = [[arrayLo objectAtIndex:i] floatValue];
MKMapPoint point = MKMapPointForCoordinate(thisCoord);
pointArr[i] = point;
// Reset Map View Boundaries
if( point.x > ne_Pt.x - 500 ) ne_Pt.x = point.x + 1000;
if( point.y > ne_Pt.y - 500 ) ne_Pt.y = point.y + 1000;
if( point.x < sw_Pt.x + 500 ) sw_Pt.x = point.x - 1000;
if( point.y < sw_Pt.y + 500 ) sw_Pt.y = point.y - 1000;
// create the polyline based on the C-array of map Points
_routePath = [MKPolyline polylineWithPoints:pointArr count:arrayLa.count];
_routeBounds = MKMapRectMake(sw_Pt.x, sw_Pt.y, ne_Pt.x-sw_Pt.x, ne_Pt.y-sw_Pt.y);
// add the routePath overlay to the map, if it isn't empty
if (recState == REC && _routePath != nil) {
// zoom in on the route with the fresh bounding box, routeBounds
[self zoomInOnRoute];
[_mapView addOverlay:_routePath];
}
}
-(void) zoomInOnRoute {
[_mapView setVisibleMapRect:_routeBounds];
}
#pragma mark MKMapViewDelegate
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolyline *route = overlay;
MKPolylineRenderer *routeRenderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
routeRenderer.lineWidth = 3;
routeRenderer.strokeColor = [UIColor redColor];
return routeRenderer;
}
else return nil;
}
Кто-нибудь может помочь решить мою проблему? Спасибо!
1 ответ
Это похоже на проблему делегата. Вы пытались поставить точку останова на вызове addOverLay на случай, если "если" пропустит его?
Я делаю что-то подобное, и все отлично работает, используя MKOverlay и MKOverlayRender (на основе примера приложения Apple Breadcrumbs, но обновлен). Приложение отображает маршрут, который пользователь может сохранить в CoreData. Они могут выбрать из таблицы сохраненных маршрутов, и маршрут отображается с помощью MKOverlayRenderer.
Установить делегата
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.mapView setDelegate:self];
}
Создайте MKOverlay и добавьте в mapView
- (void)createRoute2
{
// Some CoreData stuff. Iterate through map points and create an overlay.
// Order by date ascending so we draw in sequential order
NSSortDescriptor *timeStampDescriptor = [[NSSortDescriptor alloc] initWithKey:@"pointDate" ascending:YES];
NSArray *sortDescriptors = @[timeStampDescriptor];
NSArray *routePts = [[self.selectedRoute mapDetail] sortedArrayUsingDescriptors:sortDescriptors];
// A long is a bit excessive just use an int is fine ( BUT might be a huge number of route points)
long nbrPts = routePts.count;
if (nbrPts < 2){
return;
}
CLLocationCoordinate2D mapPointLoc;
MKMapRect updateRect; // The map area
// Init the route
// FtfmapDetail is a managed object holding lat long (and other stuff)
FtfMapDetail *currentPt = (FtfMapDetail *)[routePts objectAtIndex:0];
mapPointLoc = CLLocationCoordinate2DMake([currentPt.latitude floatValue], [currentPt.longitude floatValue]);
// self.route is a subclassed MapOverlay
if (!self.route)
{
// BGSMapOverlay is a subclassed MapOverlay
self.route = [[BGSMapOverlay alloc] initWithCenterCoordinate:mapPointLoc];
[self.mapView addOverlay:self.route];
}
// Add subsequent points. Kick off the for loop at int position 1 not 0
for (int i=1; i <nbrPts; i++){
currentPt = (FtfMapDetail *)[routePts objectAtIndex:i];
mapPointLoc = CLLocationCoordinate2DMake([currentPt.latitude floatValue], [currentPt.longitude floatValue]);
// AddCoordinate is a method in MKOverlay subclass that returns a bounding MKMaprect for all points in MkOverlay
updateRect = [self.route addCoordinate:mapPointLoc];
}
MKCoordinateRegion region = MKCoordinateRegionForMapRect(self.route.boundingMapRectCompleteRoute);
[self.mapView setRegion:region animated:YES];
}
И убедитесь, что вы добавили метод делегата
#pragma mark - MKMapView delegate
// self.routeViewRenderer is a sub-classed MKOverlayRendered (based on the Breadcrumbs app from apple CrumbPathView subclassed MKOverlayView)
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
if (!self.routeViewRenderer)
{
_routeViewRenderer = [[BGSMKOverlayRender alloc] initWithOverlay:overlay];
}
return self.routeViewRenderer;
}
Или, возможно, вы не отправляете какие-либо координаты в MkPolyLine. В следующем фрагменте, если я раскомментирую "NSArray *routeCoordinates = [[NSArray alloc]init];" чтобы отправить массив Nil в MKPolyLine, тогда код будет запущен, но делегат не будет вызван. Если routeCoordinates содержит точки, вызывается делегат и отображается маршрут.
-(void)buildRouteOverlays
{
for (int i=0; i< _routeHeaders.count;i++)
{
_selectedRoute = (FtfMaps*) [_routeHeaders objectAtIndex:i];
NSLog(@"DEBUG route date : %@", _selectedRoute.dateMap);
NSArray *routeCoordinates = [self arrayRoutePointCoordinates];
// if a nil array is produce then MapOverlayRenerder is not called - nothing to render
// Test this by uncommenting:
// NSArray *routeCoordinates = [[NSArray alloc]init];
NSLog(@"DEBUG number of point in Route : %lu",(unsigned long)routeCoordinates.count);
// Just a quick test only process the first route
if (i==0){
MKPolyline *routePolyLine = [self polyLineFromArray:routeCoordinates];
[self.mapView addOverlay:routePolyLine];
}
}
}
-(MKPolyline*)polyLineFromArray:(NSArray*)routePoints
{
NSInteger pointsCount = routePoints.count;
CLLocationCoordinate2D pointsToUse[pointsCount];
for(int i = 0; i < pointsCount; i++) {
FtfMapDetail *mapPt = (FtfMapDetail *) [routePoints objectAtIndex:i];
pointsToUse[i] = CLLocationCoordinate2DMake([mapPt.latitude doubleValue], [mapPt.longitude doubleValue]);
}
MKPolyline *myPolyline = [MKPolyline polylineWithCoordinates:pointsToUse count:pointsCount];
return myPolyline;
}
#pragma mark MKMapViewDelegate
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolyline *route = overlay;
MKPolylineRenderer *routeRenderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
routeRenderer.lineWidth = 3;
routeRenderer.strokeColor = [UIColor redColor];
return routeRenderer;
}
else return nil;
}