地图注释显示所有点的所有相同图像/引脚

时间:2013-10-22 09:52:18

标签: ios objective-c mapkit mkannotation

我有一个条件语句,可以在下面的方法中添加地图注释图标/图钉。我遇到的问题是地图上填充了所有相同的图标。它应该检测cat id并根据检测到的cat id显示图标。我不确定问题是什么,因为这在iOS 6中有效,现在在iOS 7中,地图只显示所有相同的注释图标图像。

- (MKAnnotationView *) mapView:(MKMapView *)mapingView viewForAnnotation:(id <MKAnnotation>) annotation {
annView = nil;
if(annotation != mapingView.userLocation)
{

    static NSString *defaultPinID = @"";
    annView = (MKAnnotationView *)[mapingView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
    if ( annView == nil )
        annView = [[MKAnnotationView alloc]
                   initWithAnnotation:annotation reuseIdentifier:defaultPinID] ;


    UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    [rightButton setTitle:annotation.title forState:UIControlStateNormal];

    annView.rightCalloutAccessoryView = rightButton;

    MyAnnotation* annotation= [MyAnnotation new];

    annotation.catMapId = categoryIdNumber;
    NSLog(@"categoryIdNumber %@",categoryIdNumber);
    NSLog(@"annotation.catMapId %@",annotation.catMapId);


        if (annotation.catMapId == [NSNumber numberWithInt:9]) {
            annView.image = [UIImage imageNamed:@"PIN_comprare.png"];

            NSLog(@"annview 9");

        }

        else if (annotation.catMapId == [NSNumber numberWithInt:10]) {
            annView.image = [UIImage imageNamed:@"PIN_mangiare.png"];

            NSLog(@"annview 10");

        }

        else if (annotation.catMapId == [NSNumber numberWithInt:11]) {
            annView.image = [UIImage imageNamed:@"PIN_visitare.png"];

            NSLog(@"annview 11");

        }

        else if (annotation.catMapId == [NSNumber numberWithInt:12]) {
            annView.image = [UIImage imageNamed:@"PIN_vivere.png"];

            NSLog(@"annview 12");

        }

    annView.canShowCallout = YES;

}

return annView;

}

enter image description here

4 个答案:

答案 0 :(得分:1)

在最后添加此行:

annView.annotation = annotation;

答案 1 :(得分:1)

正如你所说,“这确实在iOS 6中有效”,你应该认为它相当幸运它(或似乎)并且这种设置注释图像的方法不应该是依赖于任何版本。

尽管@Ar Ma是正确的,应该设置注释视图的annotation属性(如果正在重用视图),这将无法解决主要问题。

注释视图的image是根据categoryIdNumber的值设置的,viewForAnnotation似乎是 viewForAnnotation委托方法之外的一些变量。

不能 假设:

    致电addAnnotation后,系统会立即致电
  1. viewForAnnotation。即使在iOS 6或更早版本中,也无法保证。
  2. 每个注释只会调用
  3. viewForAnnotation一次。对于相同的注释,可以多次调用委托方法,因为用户可以平移或缩放地图,并且注释会返回到屏幕上。
  4. addAnnotation将按照添加注释的顺序进行调用。这是第1点和第2点的结果。
  5. 我假设在您致电categoryIdNumber之前,viewForAnnotation已正确设置,然后根据上述错误假设,categoryIdNumber使用viewForAnnotation来设置图片。

    正在发生的事情是,在完成所有addAnnotation次调用或某些categoryIdNumber调用之后,地图视图会调用categoryIdNumber addAnnotation可能是与之相关的值添加了最后一个注释,所有注释都使用适用于最后一个注释的图像。


    要解决此问题(无论的iOS版本如何),您必须在 调用{之前“将正确的MyAnnotation值放入每个注释对象 中{1}}。

    看起来您的注记类是catMapId,并且您已经拥有addAnnotation属性。

    您必须在注释 之前设置此属性<{1}} - 而不是 viewForAnnotation方法为时已晚。 (顺便说一下,你在MyAnnotation方法中创建一个viewForAnnotation对象,这是没有意义的。)


    那么你在哪里创建和添加注释(不在viewForAnnotation中):

    MyAnnotation* myAnn = [[MyAnnotation alloc] init];
    myAnn.coordinate = ...
    myAnn.title = ...
    myAnn.catMapId = categoryIdNumber;  // <-- set catMapId BEFORE addAnnotation
    [mapView addAnnotation:myAnn];
    

    然后viewForAnnotation中的代码应该是这样的:

    - (MKAnnotationView *) mapView:(MKMapView *)mapingView viewForAnnotation:(id <MKAnnotation>) annotation
    {
        annView = nil;
        if(annotation != mapingView.userLocation)
        {
    
            static NSString *defaultPinID = @"MyAnnId";
            annView = (MKAnnotationView *)[mapingView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
            if ( annView == nil )
            {
                annView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:defaultPinID] ;
                annView.canShowCallout = YES;
            }
            else
            {
                //view is being re-used, re-set annotation to current...
                annView.annotation = annotation;
            }
    
            UIButton* rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
            [rightButton setTitle:annotation.title forState:UIControlStateNormal];
    
            annView.rightCalloutAccessoryView = rightButton;
    
    
            //Make sure we have a MyAnnotation-type annotation
            if ([annotation isKindOfClass:[MyAnnotation class]])
            {
                //Do not CREATE a local MyAnnotation object here.
                //Instead, get the catMapId from the annotation object
                //that was PASSED INTO the delegate method.
                //MyAnnotation* annotation= [MyAnnotation new];
                //annotation.catMapId = categoryIdNumber;
    
                MyAnnotation *myAnn = (MyAnnotation *)annotation;
    
                //The value of the external variable categoryIdNumber is irrelevant here.
                //NSLog(@"categoryIdNumber %@",categoryIdNumber);
    
                NSLog(@"myAnn.catMapId %@",myAnn.catMapId);
    
    
                //Put the NSNumber value into an int to simplify the code below.
                int myAnnCatMapId = [myAnn.catMapId intValue];
    
                NSString *imageName = nil;
                switch (myAnnCatMapId)
                {
                    case 9:
                    {
                        imageName = @"PIN_comprare.png";
                        break;
                    }
    
                    case 10:
                    {
                        imageName = @"PIN_mangiare.png";
                        break;
                    }
    
                    case 11:
                    {
                        imageName = @"PIN_mangiare.png";
                        break;
                    }
    
                    case 12:
                    {
                        imageName = @"PIN_vivere.png";
                        break;
                    }
    
                    default:
                    {
                        //set some default image for unknown cat ids...
                        imageName = @"default.png";
                        break;
                    }
                }
    
                annView.image = [UIImage imageNamed:imageName];
    
                NSLog(@"annview %d", myAnnCatMapId);
            }
        }
    
        return annView; 
    }
    

答案 2 :(得分:0)

同样的麻烦,对我来说决定不使用

pinView.animatesDrop   = YES;

自定义图标对我来说不适用于动画效果。

答案 3 :(得分:0)

万一任何人都需要使用MapView批注作为tableView,即在地图上显示一系列点。

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    let identifier = MKMapViewDefaultAnnotationViewReuseIdentifier
    if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) as? TrailAnnotationView {
            ///TrailAnnotation has an object of type trail ( can be any model you ///want ). and so is TrailAnnotationView
///inside TrailAnnotationView we extract data from trail and display it.
        annotationView.trail = (annotation as? TrailAnnotation)?.trail
        annotationView.annotation = annotation
        return annotationView
    }
    let annotationView = TrailAnnotationView(annotation: annotation, reuseIdentifier: identifier)
    annotationView.trail = (annotation as? TrailAnnotation)?.trail
    annotationView.canShowCallout = true
    return annotationView
}

这是一个TrailAnnotationView

protocol AnnotationViewProtocol {
    func didTapOnAnnotation()
}

class TrailAnnotationView: MKPinAnnotationView {

/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
    // Drawing code
}
*/

var trail: TrailModel? = nil


override var annotation: MKAnnotation? { didSet { configureDetailView() } }

override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
    super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
    configure()
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    configure()
}

}

private extension TrailAnnotationView {
    func configure() {
        canShowCallout = true
        configureDetailView()
    }

func configureDetailView() {
    guard let annotation = annotation else { return }

    let rect = CGRect(origin: .zero, size: CGSize(width: 300, height: 200))

    let snapshotView = UIView()
    snapshotView.translatesAutoresizingMaskIntoConstraints = false

    if let trail = self.trail, !trail.imageUrl.isEmpty {
        AppUtils.sharedInstance.fetchImageFor(path: trail.imageUrl) { (image) in
            guard let imageData = image else { return }
            DispatchQueue.main.async {
                let imageView = UIImageView(frame: rect)
                imageView.image = imageData
                snapshotView.addSubview(imageView)
            }
        }
    } else {
        let options = MKMapSnapshotter.Options()
        options.size = rect.size
        options.mapType = .satelliteFlyover
        options.camera = MKMapCamera(lookingAtCenter: annotation.coordinate, fromDistance: 250, pitch: 65, heading: 0)

        let snapshotter = MKMapSnapshotter(options: options)
        snapshotter.start { snapshot, error in
            guard let snapshot = snapshot, error == nil else {
                print(error ?? "Unknown error")
                return
            }

            let imageView = UIImageView(frame: rect)
            imageView.image = snapshot.image
            snapshotView.addSubview(imageView)
        }
    }

    detailCalloutAccessoryView = snapshotView
    NSLayoutConstraint.activate([
        snapshotView.widthAnchor.constraint(equalToConstant: rect.width),  
        snapshotView.heightAnchor.constraint(equalToConstant: rect.height)
    ])
}
}