2010-12-03 4 views
5

Ey là, comme le dit le titre, j'ai du mal à ajouter un MKPolygon comme une superposition à un MKMapView. Voici le code correspondant:
ParkingMapViewContoller.hProblèmes Ajout de MKPolygon en superposition à un MKMapView

#import <UIKit/UIKit.h> 
#import <MapKit/MapKit.h> 


@interface ParkingMapViewController : UIViewController <MKMapViewDelegate> { 
    MKMapView *mapView; 
} 

@property (nonatomic, retain) IBOutlet MKMapView *mapView; 


-(void)loadAnnotations; 
-(void)showCurrentLocationButtonTapped:(id)sender; 


@end 

ParkingMapViewController.m

//... 
#import "ParkingRegionOverlay.h" 
//... 
- (void)viewDidLoad { 
    [super viewDidLoad]; 
    NSLog(@"%@",self.title); 

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:100 target:self action:@selector(showCurrentLocationButtonTapped:)]; 

    /*MKMapPoint points[3] = {{38.53607,-121.765793}, {38.537606,-121.768379}, {38.53487,-121.770578}}; 
    MKPolygon *polygon = [MKPolygon polygonWithPoints:points count:3];*/ 

    ParkingRegionOverlay *polygon = [[ParkingRegionOverlay alloc] initialize]; 
    [mapView addOverlay:polygon]; 

    [self loadAnnotations]; 

    CLLocationCoordinate2D centerCoord = { UCD_LATITUDE, UCD_LONGITUDE }; 
    [mapView setCenterCoordinate:centerCoord zoomLevel:13 animated:NO]; //from "MKMapView+ZoomLevel.h" 
} 
//... 

- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay 
{ 
    NSLog(@"in viewForOverlay!"); 

    if ([overlay isKindOfClass:[MKPolygon class]]) 

    { 

     MKPolygonView* aView = [[[MKPolygonView alloc] initWithPolygon:(MKPolygon*)overlay] autorelease]; 

     aView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2]; 

     aView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7]; 

     aView.lineWidth = 3; 

     return aView; 

    } 
    return nil; 
} 
//... 

ParkingRegionOverlay.h

#import <Foundation/Foundation.h> 
#import <MapKit/MapKit.h> 


@interface ParkingRegionOverlay : NSObject <MKOverlay> { 
    //CLLocationCoordinate2D origin; 
    MKPolygon *polygon; 

    //MKMapRect rect; 
} 

//@property (nonatomic) CLLocationCoordinate2D origin; 
@property (nonatomic, retain) MKPolygon *polygon; 

//@property (nonatomic) MKMapRect rect; 

-(ParkingRegionOverlay*)initialize; 
-(MKMapRect)boundingMapRect; 
-(CLLocationCoordinate2D)coordinate; 

@end 

ParkingRegionOverlay.m

#import "ParkingRegionOverlay.h" 


@implementation ParkingRegionOverlay 

//@synthesize origin; 
@synthesize polygon; 

//@synthesize rect; 


-(ParkingRegionOverlay*) initialize { 
    MKMapPoint points[3] = {{38.53607,-121.765793}, {38.537606,-121.768379}, {38.53487,-121.770578}}; 
    polygon = [MKPolygon polygonWithPoints:points count:3]; 
    polygon.title = @"Some Polygon"; 
    return self; 
} 

- (MKMapRect)boundingMapRect{ 
    MKMapRect bounds = MKMapRectMake(-121.770578,38.537606,-121.770578-(-121.765793),38.537606-38.53487); 
    return bounds; 
} 

- (CLLocationCoordinate2D)coordinate{ 
    return CLLocationCoordinate2DMake((38.537606-38.53487)/2, (-121.770578-(-121.765793))/2); 
} 

@end 

Vous voyez que je NSLog coincé dans la viewForOverlay: méthode? Eh bien, cela n'apparaît jamais dans la console, de sorte que cette fonction n'est jamais appelée. Une idée de ce qui ne va pas? Merci beaucoup!

Répondre

10

Le principal problème est que le code donne les coordonnées vue de la carte latitude/longitude où il attend MKMapPoints. Pour une explication de la différence, voir "Comprendre la géométrie de la carte" dans le Location Awareness Programming Guide. Utilisez la fonction MKMapPointForCoordinate pour convertir des coordonnées lat/long en un MKMapPoint.

Le deuxième problème est que dans viewForOverlay, il vérifie si overlay est de type MKPolygon. Votre classe Overlay ParkingRegionOverlay contient un objet MKPolygon à l'intérieur mais n'est pas lui-même de type MKPolygon.

Pour résoudre le problème principal, vous devez changer l'initialisation et les méthodes boundingMapRect:

-(id)init { 
    if (self = [super init]) { 
     MKMapPoint points[3]; 
     CLLocationCoordinate2D c1 = {38.53607,-121.765793}; 
     points[0] = MKMapPointForCoordinate(c1); 
     CLLocationCoordinate2D c2 = {38.537606,-121.768379}; 
     points[1] = MKMapPointForCoordinate(c2); 
     CLLocationCoordinate2D c3 = {38.53487,-121.770578}; 
     points[2] = MKMapPointForCoordinate(c3); 

     polygon = [MKPolygon polygonWithPoints:points count:3]; 
     polygon.title = @"Some Polygon"; 
    } 
    return self; 
} 

- (MKMapRect)boundingMapRect{ 
    CLLocationCoordinate2D corner1 = 
     CLLocationCoordinate2DMake(38.537606, -121.770578); 
    MKMapPoint mp1 = MKMapPointForCoordinate(corner1); 

    CLLocationCoordinate2D corner2 = 
     CLLocationCoordinate2DMake(38.53487, -121.765793); 
    MKMapPoint mp2 = MKMapPointForCoordinate(corner2); 

    MKMapRect bounds = 
     MKMapRectMake(mp1.x, mp1.y, (mp2.x-mp1.x), (mp2.y-mp1.y)); 

    return bounds; 
} 

S'il vous plaît avis par la façon dont je l'ai changé la méthode « initialiser » à « init ». Bien que cela n'empêche pas l'affichage du polygone, la façon dont vous surchargez l'initialisation de ParkingRegionOverlay en utilisant une méthode appelée "initialize" sans appeler [super init] ne suit pas la convention. (Supprimez également "initialize" du fichier .h.)

Pour fixer la deuxième question, la méthode viewForOverlay devrait ressembler à ceci:

- (MKOverlayView *)mapView:(MKMapView *)mapView 
    viewForOverlay:(id <MKOverlay>)overlay 
{ 
    NSLog(@"in viewForOverlay!"); 

    if ([overlay isKindOfClass:[ParkingRegionOverlay class]]) 
           //^^^^^^^^^^^^^^^^^^^^ 
    { 
     //get the MKPolygon inside the ParkingRegionOverlay... 
     MKPolygon *proPolygon = ((ParkingRegionOverlay*)overlay).polygon; 

     MKPolygonView *aView = [[[MKPolygonView alloc] 
      initWithPolygon:proPolygon] autorelease]; 
          //^^^^^^^^^^ 

     aView.fillColor = [[UIColor cyanColor] colorWithAlphaComponent:0.2]; 
     aView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7]; 
     aView.lineWidth = 3; 

     return aView; 
    } 
    return nil; 
} 

Enfin, modifiez le code dans viewDidLoad:

ParkingRegionOverlay *polygon = [[ParkingRegionOverlay alloc] init]; 
[mapView addOverlay:polygon]; 
[polygon release]; //don't forget this 
+0

J'ai oublié d'expliquer pourquoi viewDidOverlay n'a pas été appelée même si le délégué de la vue cartographique a été défini (ce qui doit être le cas) La méthode viewDidOverlay n'est appelée que lorsque le boundingMapRect de la superposition est visible dans la région actuelle. , il n'était pas considéré comme "visible" et viewDidOverlay ne recevait pas d'appel – Anna

+0

Dang mec, tu connais vraiment ton truc Incroyable ... Merci mec! Je n'ai aucune idée de combien de temps j'ai essayé de faire marcher ça. Oh et pendant que je suis sur le sujet, comment pourrais-je faire pour faire sortir une légende de la superposition quand elle est tapée? Pas besoin d'une longue explication, mais si vous pouviez me diriger vers une méthode ou un document qui serait génial. Merci beaucoup! – Stunner

+1

Malheureusement, une vue de superposition n'a pas de légende intégrée comme MKAnnotationView, donc plus de travail est nécessaire. Vous pouvez utiliser un UIGestureRecognizer pour détecter le toucher (voir [cette réponse] (http://stackoverflow.com/questions/4317810/how-to-capture-tap-gesture-on-mkmapview)). Utilisez un seul robinet, appuyez deux fois, appuyez longuement - tout ce qui fonctionne pour vous. Le double-tap serait en conflit avec le zoom si. Dans cette réponse, dans la méthode handleGesture, vous pouvez vérifier si le point de contact se trouve dans boundingMapRect de l'overlay en utilisant MKMapRectContainsPoint, puis afficher une vue en popup. – Anna

0

il me semble que vous oubliez de définir votre délégué somthing comme ça

_mapView.delegate = auto;

+0

pensée Nice, mais non, je l'ai mis en place via IB et mapView est connecté à ParkingMapViewController pour qu'il soit en effet le délégué de mapView. J'ai aussi des annotations sur la carte qui s'affichent et fonctionnent correctement, ce qui ne serait pas le cas si je n'avais pas spécifié ParkingMapViewController comme délégué de la vue cartographique. – Stunner

+0

Je suggérerais de définir le délégué par programme au lieu de IB. – justicepenny

+0

Réglez-le par programme, mais toujours pas de chance. :( – Stunner

0

Avez-vous mis cette ?:

yourMap.delegate=self; 

Et quel est votre objectif? 3.x ou 4.x ?? Je pense que MKPolygon est disponible à partir de 4.0. Vous pouvez essayer d'ajouter la clause d'importation dans votre fichier préfixe comme:

#ifdef __OBJC__ 
#import <Foundation/Foundation.h> 
#import <UIKit/UIKit.h> 
#import <MapKit/MapKit.h> 
#endif 
+0

Cible est 4.1 Et j'ai essayé de définir mon délégué comme vous l'avez spécifié dans la méthode viewDidLoad en vain.J'ai également essayé votre version de la clause d'importation, mais pas de chance.Autres idées? – Stunner

+0

essayer de définir votre variable MKMapView comme 'IBOutlet MKMapView mapView;' – Mat

+0

Je l'ai déjà comme ça dans la déclaration @property, et je suis sûr que ça ne va rien faire.Néanmoins, je l'ai essayé et ça n'a pas marché – Stunner

Questions connexes