2013-02-05 11 views
5

Nella mia app, l'utente disegna una forma sulla mappa e usando UIBeizerPath sto disegnando quel percorso. Quindi in base alle coordinate del percorso sto visualizzando i risultati che sono solo in quella zona. Tutto funziona alla grande eccetto che ora, quando le annotazioni cadono sulla mappa, i perni sembrano essere dietro il percorso, il che significa che il percorso appare nella parte anteriore.Come portare UIBezierPath sul retro di un oggetto MKAnnotation?

Sto usando questo codice per visualizzare l'annotazione e il percorso:

-(void)clearAnnotationAndPath:(id)sender { 
    [_mapView removeAnnotations:_mapView.annotations]; 
    path = [UIBezierPath bezierPath]; 
    [shapeLayer removeFromSuperlayer]; 
} 

- (void)handleGesture:(UIPanGestureRecognizer *)gesture 
{ 

    CGPoint location = [gesture locationInView:_pathOverlay]; 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     shapeLayer = [[CAShapeLayer alloc] init]; 
     shapeLayer.fillColor = [[UIColor clearColor] CGColor]; 
     shapeLayer.strokeColor = [[UIColor greenColor] CGColor]; 
     shapeLayer.lineWidth = 5.0; 
     //[_mapView.layer addSublayer:shapeLayer]; 
     [pathOverlay.layer addSublayer:shapeLayer]; 
     path = [UIBezierPath bezierPath]; 
     [path moveToPoint:location]; 
    } 

    else if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
     [path addLineToPoint:location]; 
     shapeLayer.path = [path CGPath]; 
    } 

    else if (gesture.state == UIGestureRecognizerStateEnded) 
    { 
     // MKMapView *mapView = (MKMapView *)gesture.view; 

     [path addLineToPoint:location]; 
     [path closePath]; 
     allStations = [RoadmapData sharedInstance].data; 
     for (int i=0; i<[allStations count]; i++) { 
      NSDictionary * itemNo = [allStations objectAtIndex:i]; 

      NSString * fullAddress = [NSString stringWithFormat:@"%@,%@,%@,%@",[itemNo objectForKey:@"address"],[itemNo objectForKey:@"city"],[itemNo objectForKey:@"state"],[itemNo objectForKey:@"zip"]]; 
      CLGeocoder * geoCoder = [[CLGeocoder alloc]init]; 
      [geoCoder geocodeAddressString:fullAddress completionHandler:^(NSArray *placemarks, NSError *error) { 

       if (error) { 
        NSLog(@"Geocode failed with error: %@", error); 
        return; 
       } 

       if(placemarks && placemarks.count > 0) 
       { 
        CLPlacemark *placemark = placemarks[0]; 
        CLLocation *location = placemark.location; 
        CLLocationCoordinate2D coords = location.coordinate; 
        CGPoint loc = [_mapView convertCoordinate:coords toPointToView:_pathOverlay]; 
        if ([path containsPoint:loc]) 
        { 
         NSString * name = [itemNo objectForKey:@"name"]; 
         stationAnn = [[LocationAnnotation alloc]initWithCoordinate:coords Title:name subTitle:@"Wells Fargo Offer" annIndex:i]; 
         stationAnn.tag = i; 
         [_mapView addAnnotation:stationAnn]; 
        } 
        else{ 
         NSLog(@"Out of boundary"); 
        } 
       } 
      }]; 
      [self turnOffGesture:gesture]; 
     } 
    } 
} 

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views{ 
    if (views.count > 0) { 
     UIView* firstAnnotation = [views objectAtIndex:0]; 
     UIView* parentView = [firstAnnotation superview]; 
     if (_pathOverlay == nil){ 
      // create a transparent view to add bezier paths to 
      pathOverlay = [[UIView alloc] initWithFrame: parentView.frame]; 
      pathOverlay.opaque = NO; 
      pathOverlay.backgroundColor = [UIColor clearColor]; 
      [parentView addSubview:pathOverlay]; 
     } 

     // make sure annotations stay above pathOverlay 
     for (UIView* view in views) { 
      [parentView bringSubviewToFront:view]; 
     } 
    } 
} 

Anche una volta che torno da questo e di visualizzare e vengo di nuovo la sua non è nemmeno disegnare il percorso.

Per favore aiuto.

Grazie,

risposta

3

quanto pare, quando si aggiunge il tracciato Bezier alla mappa tramite:

 [_mapView.layer addSublayer:shapeLayer]; 

si sta facendo aggiunto sopra qualche strato interno che MKMapView usa per disegnare le annotazioni. Se you take a look at this somewhat related question, vedrete che è possibile implementare il protocollo MKMapViewDelegate e richiamare quando vengono aggiunte nuove annotazioni di stazione. Quando ciò accade, si controlla sostanzialmente la gerarchia delle viste delle annotazioni appena aggiunte e si inserisce un nuovo strato trasparente UIViewal di sotto di. Fai attenzione a portare tutte le annotazioni davanti a questo trasparente UIView.

// always remember to assign the delegate to get callbacks! 
    _mapView.delegate = self; 

...

#pragma mark - MKMapViewDelegate 

- (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views{ 
    if (views.count > 0) { 
     UIView* firstAnnotation = [views objectAtIndex:0]; 
     UIView* parentView = [firstAnnotation superview]; 
     // NOTE: could perform this initialization in viewDidLoad, too 
     if (self.pathOverlay == nil){ 
      // create a transparent view to add bezier paths to 
      pathOverlay = [[UIView alloc] initWithFrame: parentView.frame]; 
      pathOverlay.opaque = NO; 
      pathOverlay.backgroundColor = [UIColor clearColor]; 
      [parentView addSubview:pathOverlay]; 
     } 

     // make sure annotations stay above pathOverlay 
     for (UIView* view in views) { 
      [parentView bringSubviewToFront:view]; 
     } 
    } 
} 

Poi, invece di aggiungere il vostro livello di forma per _mapView.layer, lo si aggiunge al tuo livello visione trasparente, anche attraverso questo nuovo livello nella conversione di coordinate:

- (void)handleGesture:(UIPanGestureRecognizer*)gesture 
{ 
    CGPoint location = [gesture locationInView: self.pathOverlay]; 

    if (gesture.state == UIGestureRecognizerStateBegan) 
    { 
     if (!shapeLayer) 
     { 
      shapeLayer = [[CAShapeLayer alloc] init]; 
      shapeLayer.fillColor = [[UIColor clearColor] CGColor]; 
      shapeLayer.strokeColor = [[UIColor greenColor] CGColor]; 
      shapeLayer.lineWidth = 5.0; 
      [pathOverlay.layer addSublayer:shapeLayer]; // <- change here !!! 
     } 
     self.path = [[UIBezierPath alloc] init]; 
     [path moveToPoint:location]; 
    } 
    else if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
     [path addLineToPoint:location]; 
     shapeLayer.path = [path CGPath]; 
    } 
    else if (gesture.state == UIGestureRecognizerStateEnded) 
    { 
     /* 
     * This code is the same as what you already have ... 
     */ 

      // But replace this next line with the following line ... 
      //CGPoint loc = [_mapView convertCoordinate:coords toPointToView:self]; 
      CGPoint loc = [_mapView convertCoordinate:coords toPointToView: self.pathOverlay]; 

     /* 
     * And again use the rest of your original code 
     */    
    } 
} 

dove anche aggiunto un ivar (e proprietà) per il nuovo strato trasparente:

UIView* pathOverlay; 

Ho provato questo con una griglia fasullo di stazioni e ha ottenuto i seguenti risultati:

enter image description here

P.S. Ti consiglio anche di eliminare le tue variabili static. Basta renderli ivar/proprietà della tua classe.

+0

Ho fatto questo e ora non riesco nemmeno a vedere il livello disegnato sulla mappa. Sebbene controlli l'annotazione corretta e li visualizzi. – Ashutosh

+0

@Ashutosh, Queste informazioni non sono sufficienti per aiutarti. C'è un sacco di codice sopra, e ci sono alcune cose che posso immaginare che tu stia cambiando. Ti sei ricordato di rendere 'pathOverlay' una proprietà? In "handleGesture:", hai letto il codice, prendendo atto che ho ritagliato parti del tuo codice originale, per chiarezza? O hai semplicemente incollato l'intero metodo? Hai cambiato quelle statiche come ti ho suggerito? A questa riga: '[parentView addSubview: pathOverlay];', puoi fermarti nel debugger e assicurarti che 'parentView' non sia nullo? – Nate

+0

@Ashutosh, inoltre, potrebbe essere necessario aggiornare la domanda di cui sopra, incollando il codice che stai utilizzando ** ora **, così posso aiutarti a eseguire il debug. Oppure inizia una nuova domanda se pensi che si stia accumulando troppo. La tua chiamata. – Nate

Problemi correlati