2013-02-05 46 views
5

मेरे ऐप में, उपयोगकर्ता मानचित्र पर एक आकार खींचता है और UIBeizerPath का उपयोग करके मैं उस पथ को चित्रित कर रहा हूं। फिर पथ के निर्देशांक के आधार पर मैं परिणाम प्रदर्शित कर रहा हूं जो केवल उस क्षेत्र में हैं। सबकुछ बढ़िया काम करता है सिवाय इसके कि जब मानचित्र मानचित्र पर टिप्पणियां गिरती हैं तो पिन दिखते हैं कि वे पथ के पीछे हैं जिसका मतलब है कि पथ सामने की ओर दिखता है।एक एमकेएनोटेशन ऑब्जेक्ट के पीछे UIBezierPath कैसे लाया जाए?

मैं एनोटेशन और पथ प्रदर्शित करने के लिए इस कोड का उपयोग कर रहा हूँ:

-(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]; 
     } 
    } 
} 

इसके अलावा एक बार मैं इस और दृश्य से वापस जाने के लिए और आ फिर से अपनी भी पथ ड्राइंग नहीं।

कृपया मदद करें।

धन्यवाद,

उत्तर

3

जाहिर है, जब आप के माध्यम से नक्शा करने के लिए अपने बेज़ियर पथ जोड़ें:

 [_mapView.layer addSublayer:shapeLayer]; 

यह ऊपर कुछ आंतरिक परत MKMapView एनोटेशन आकर्षित करने के लिए उपयोग करता है जोड़ा जा रहा है। यदि you take a look at this somewhat related question, तो आप देखेंगे कि आप MKMapViewDelegate प्रोटोकॉल को कार्यान्वित कर सकते हैं, और नए स्टेशन एनोटेशन जोड़े जाने पर कॉलबैक प्राप्त कर सकते हैं। जब ऐसा होता है, तो आप मूल रूप से नए जोड़े गए एनोटेशन के दृश्य विरासत का निरीक्षण करते हैं, और के नीचे एक नया, पारदर्शी UIView परत डालें। आप सभी एनोटेशन को इस पारदर्शी 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]; 
     } 
    } 
} 

फिर, बजाय _mapView.layer करने के लिए अपने आकार परत को जोड़ने का, आप इसे अपने पारदर्शी दृश्य परत को जोड़ने के लिए, यह भी समन्वय रूपांतरण में इस नए परत का उपयोग:

- (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 
     */    
    } 
} 

जहां मैंने नई पारदर्शी परत के लिए ivar (और संपत्ति) भी जोड़ा:

UIView* pathOverlay; 

मैं स्टेशनों की एक फर्जी ग्रिड के साथ इस परीक्षण किया है और निम्न परिणाम है:

enter image description here

पी.एस. मैं आपके static चर से छुटकारा पाने की भी सिफारिश करता हूं। बस उन्हें अपनी कक्षा के ivars/गुण बनाओ।

+0

मैंने यह किया और अब मैं मानचित्र पर खींची गई परत को भी नहीं देख सकता। हालांकि यह सही एनोटेशन की जांच करता है और उन्हें प्रदर्शित करता है। – Ashutosh

+0

@ आशुतोष, यह वास्तव में आपकी मदद करने के लिए पर्याप्त जानकारी नहीं है। ऊपर बहुत सारे कोड हैं, और कुछ चीजें हैं जो मैं कल्पना कर सकता हूं कि आप बदल रहे हैं। क्या आपको 'pathOverlay' संपत्ति बनाना याद रखना पड़ा? 'हैंडल जेस्चर' में, क्या आपने कोड पढ़ा है, ध्यान दें कि मैंने स्पष्टता के लिए अपने मूल कोड के हिस्सों को काट दिया है? या आप बस पूरी विधि में पेस्ट किया था? क्या आपने उन आंकड़ों को बदल दिया जैसा मैंने सुझाव दिया था? इस पंक्ति पर: '[parentView addSubview: pathOverlay];', क्या आप डीबगर में रुक सकते हैं और सुनिश्चित कर सकते हैं कि 'parentView' शून्य नहीं है? – Nate

+0

@ आशुतोष, यह भी आपके लिए ऊपर दिए गए प्रश्न को अपडेट करने के लिए जरूरी हो सकता है, जो आप अब ** ** का उपयोग कर रहे कोड में पेस्ट कर रहे हैं, इसलिए मैं डीबग करने में मदद कर सकता हूं। या अगर आपको लगता है कि यह बहुत अव्यवस्थित हो रहा है तो एक नया सवाल शुरू करें। तुम्हारा कॉल। – Nate