我有一个条件语句,可以在下面的方法中添加地图注释图标/图钉。我遇到的问题是地图上填充了所有相同的图标。它应该检测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;
}
答案 0 :(得分:1)
在最后添加此行:
annView.annotation = annotation;
答案 1 :(得分:1)
正如你所说,“这确实在iOS 6中有效”,你应该认为它相当幸运它(或似乎)并且这种设置注释图像的方法不应该是依赖于任何版本。
尽管@Ar Ma是正确的,应该设置注释视图的annotation
属性(如果正在重用视图),这将无法解决主要问题。
注释视图的image
是根据categoryIdNumber
的值设置的,viewForAnnotation
似乎是 viewForAnnotation
委托方法之外的一些变量。
你 不能 假设:
addAnnotation
后,系统会立即致电viewForAnnotation
。即使在iOS 6或更早版本中,也无法保证。viewForAnnotation
一次。对于相同的注释,可以多次调用委托方法,因为用户可以平移或缩放地图,并且注释会返回到屏幕上。addAnnotation
将按照添加注释的顺序进行调用。这是第1点和第2点的结果。我假设在您致电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)
])
}
}