MapView Pin Annotation的问题 - 当地图缩放/平移/区域更改时,Pin会丢失颜色 [英] Problems with MapView Pin Annotation - Pin loses color when map is zoomed/panned/region changes

查看:152
本文介绍了MapView Pin Annotation的问题 - 当地图缩放/平移/区域更改时,Pin会丢失颜色的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个显示现金点位置的mapview。删除注释并单击标注以转到包含有关该位置的更多详细信息的页面。有两种类型的cashpoint,免费和付费,免费cashpoint针是绿色,另一种是红色。当引脚掉落时,它们是正确的颜色。一切正常,直到我缩放到用户位置或地图的其他区域然后当我回到针脚时,他们已经失去了颜色格式并且都是原始的红色。



<我认为这与地图重新加载有关,当它下载瓷砖而不是正确地重新加载引脚时,虽然我可能是错的。



任何帮助都会很多赞。



这是我的代码:

  #importCashPointMapViewController .h
#importPinDrop.h
#importCashPointDetailViewController.h

@implementation CashPointMapViewController
@synthesize app,theCashList,mapview,ann, count,myArray,pinColor;

- (IBAction)getlocation {

MKCoordinateRegion region;
region.center = self.mapview.userLocation.coordinate;
region.span.longitudeDelta = 0.01f;
region.span.longitudeDelta = 0.01f;
[mapview setRegion:region animated:YES];
}

- (void)viewDidLoad {

[super viewDidLoad];

mapview.showsUserLocation = YES;

[mapview setMapType:MKMapTypeStandard];
[mapview setZoomEnabled:YES];
[mapview setScrollEnabled:YES];

MKCoordinateRegion region = {{0.0,0.0},{0.0,0.0}};
region.center.latitude = 53.801279;
region.center.longitude = -1.548567;
region.span.longitudeDelta = 0.3f;
region.span.longitudeDelta = 0.3f;
[mapview setRegion:region animated:YES];

app = [[UIApplication sharedApplication] delegate];

UIImage * locate = [UIImage imageNamed:@location arrow white.png];

UIBarButtonItem * userlocatebutton = [[UIBarButtonItem alloc] initWithImage:locate style:UIBarButtonItemStylePlain target:self action:@selector(getlocation)];

self.navigationItem.rightBarButtonItem = userlocatebutton;

[self performSelectorInBackground:@selector(annloop)withObject:self];

}


- (无效)annloop {

int i;
for(i = 0; i< = count-1; i = i + 1){
theCashList = [myArray objectAtIndex:i];

NSString * trimlat = [theCashList.lat stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString * trimlon = [theCashList.lon stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

double latdouble = [trimlat doubleValue];
double londouble = [trimlon doubleValue];

CLLocationCoordinate2D coord = {(latdouble),(londouble)};

ann = [[PinDrop alloc] init];

ann.index = i;

ann.title = [theCashList.name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

NSString * street = [theCashList.street stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString * town = [theCashList.town stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString * postcode = [theCashList.postcode stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

NSString * address = [[NSString alloc] initWithFormat:@%@,%@,%@,street,town,postcode];

ann.subtitle = address;
ann.coordinate = coord;

NSString * trimprice = [theCashList.price stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

if([trimprice isEqualToString:@Free])
{
ann.price = 1;
}
其他
{
ann.price = 0;
}
[mapview performSelectorOnMainThread:@selector(addAnnotation :) withObject:ann waitUntilDone:YES];
}
}


- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id< MKAnnotation>)注释{

if([annotation isKindOfClass:[MKUserLocation class]])
return nil;

MKPinAnnotationView * mypin = [[MKPinAnnotationView alloc] initWithAnnotation:ann reuseIdentifier:@current];
mypin.backgroundColor = [UIColor clearColor];
UIButton * goToDetail = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
mypin.rightCalloutAccessoryView = goToDetail;
mypin.draggable = NO;
mypin.animatesDrop = TRUE;
mypin.canShowCallout = YES;


if(ann.price == 1)
{
mypin.pinColor = MKPinAnnotationColorGreen;
}
其他
{
mypin.pinColor = MKPinAnnotationColorRed;
}
返回mypin;
}


- (无效)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control {

PinDrop * annView = view.annotation;
CashPointDetailViewController * detailView = [[CashPointDetailViewController alloc] init];
theCashList = [myArray objectAtIndex:annView.index];
detailView.theCashList = theCashList;
[self.navigationController pushViewController:detailView animated:YES];

}


- (void)viewDidUnload {

[super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return(interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

编辑:这是我的。如果它有帮助的话。

  #import< UIKit / UIKit.h> 
#importAppDelegate.h
#importCashPointList.h
#import< MapKit / MapKit.h>
#importPinDrop.h

@interface CashPointMapViewController:UIViewController {

MKMapView * mapview;
PinDrop * ann;
}

@property(非原子,保留)AppDelegate * app;
@property(非原子,保留)CashPointList * theCashList;
@property(非原子,保留)PinDrop * ann;
@property(非原子,保留)IBOutlet MKMapView * mapview;
@property(非原子,读写)int count;
@property(nonatomic,retain)NSMutableArray * myArray;
@property(nonatomic)MKPinAnnotationColor pinColor;

- (IBAction)getlocation;


@end


解决方案

这不是与地图重新加载相关的问题。



问题是 viewForAnnotation delegate正在使用 ann 对象,错误的假设是类 - 实例级 ann 对象将同步每当调用委托方法时。



viewForAnnotation 委托不一定按添加注释的顺序调用如果地图在返回视图时需要重新显示注释,则可以为同一个注释调用多个次。



对于先前添加的注释,再次调用委托方法, ann 注释不再指向同一对象。 ann 现在可能指向最后添加的注释,因此所有注释都会更改为其颜色。



委托方法,您必须使用 annotation 参数,该参数是地图视图在当前调用中想要视图的注释的引用可能与你的外部循环完全无关。)



所以这一行:

  MKPinAnnotationView * mypin = [[MKPinAnnotationView alloc] 
initWithAnnotation:ann reuseIdentifier:@current];

应为:

  MKPinAnnotationView * mypin = [[MKPinAnnotationView alloc] 
initWithAnnotation:annotation reuseIdentifier:@current];
^^^^^^^^^^

并且在检查注释的属性时,使用注释参数(并将其强制转换为自定义类以获取自定义属性):

  PinDrop * ann =(PinDrop *)注释; 
//请注意,本地ann与班级ann不同。
//可能想使用其他名称以避免混淆。
//编译器也可能会对此发出警告。

if(ann.price == 1)
...



一个单独的,不相关但强烈推荐的建议是使用 dequeueReusableAnnotationViewWithIdentifier 实现注释视图的重用。当您有大量注释时,这将提高性能。


I have a mapview that displays locations of cash points. Annotations are dropped and the callout can be clicked on to go to a page with more detail about that location. There are two categories of cashpoint, free and paid, free cashpoint pins are green and the other red. When the pins drop they are the correct colours. Everything works fine untill i zoom to user location or other areas of the map then when i go back to the pins they have lost their colour formatting and are all the original red colour.

I assume this is something to do with the map reloading when it downloads tiles and not reloading the pins properly, although i could be wrong.

Any help will be much appreciated.

here is my code:

#import "CashPointMapViewController.h"
#import "PinDrop.h"
#import "CashPointDetailViewController.h"

@implementation CashPointMapViewController
@synthesize app, theCashList, mapview, ann, count, myArray, pinColor;

- (IBAction) getlocation { 

    MKCoordinateRegion region;
    region.center = self.mapview.userLocation.coordinate;
    region.span.longitudeDelta = 0.01f;
    region.span.longitudeDelta = 0.01f;
    [mapview setRegion:region animated:YES];
}

- (void)viewDidLoad {

    [super viewDidLoad];

    mapview.showsUserLocation = YES;

    [mapview setMapType:MKMapTypeStandard];
    [mapview setZoomEnabled:YES];
    [mapview setScrollEnabled:YES];

    MKCoordinateRegion region = { {0.0, 0.0 }, {0.0, 0.0 } };
    region.center.latitude = 53.801279;
    region.center.longitude = -1.548567;
    region.span.longitudeDelta = 0.3f;
    region.span.longitudeDelta = 0.3f;
    [mapview setRegion:region animated:YES];

    app = [[UIApplication sharedApplication]delegate];

    UIImage *locate = [UIImage imageNamed:@"location arrow white.png"];

    UIBarButtonItem *userlocatebutton = [[UIBarButtonItem alloc] initWithImage:locate     style:UIBarButtonItemStylePlain target:self action:@selector(getlocation)];

    self.navigationItem.rightBarButtonItem = userlocatebutton;

    [self performSelectorInBackground:@selector(annloop) withObject:self];

}


-(void) annloop {

    int i;
    for (i=0; i<=count-1; i = i+1) {
    theCashList = [myArray objectAtIndex:i];

    NSString *trimlat = [theCashList.lat stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSString *trimlon = [theCashList.lon stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    double latdouble = [trimlat doubleValue];
    double londouble = [trimlon doubleValue];

    CLLocationCoordinate2D coord = {(latdouble),(londouble)};

    ann = [[PinDrop alloc] init];

    ann.index = i;

    ann.title = [theCashList.name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    NSString *street = [theCashList.street stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSString *town = [theCashList.town stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSString *postcode = [theCashList.postcode stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    NSString *address = [[NSString alloc] initWithFormat:@"%@, %@, %@", street, town, postcode];

    ann.subtitle = address;
    ann.coordinate = coord;

    NSString *trimprice = [theCashList.price stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

    if ([trimprice isEqualToString:@"Free"])
    {
        ann.price = 1;
    }
    else
    {
        ann.price = 0;
    }
    [mapview performSelectorOnMainThread:@selector(addAnnotation:) withObject:ann waitUntilDone:YES];
    }
}


-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {

    if ([annotation isKindOfClass:[MKUserLocation class]])
    return nil;

    MKPinAnnotationView *mypin = [[MKPinAnnotationView alloc]initWithAnnotation:ann reuseIdentifier:@"current"];
    mypin.backgroundColor = [UIColor clearColor];
    UIButton *goToDetail = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
    mypin.rightCalloutAccessoryView = goToDetail;
    mypin.draggable = NO;
    mypin.animatesDrop = TRUE;
    mypin.canShowCallout = YES;


    if (ann.price == 1)
    {
        mypin.pinColor = MKPinAnnotationColorGreen;
    }
    else
    {
        mypin.pinColor = MKPinAnnotationColorRed;
    }
    return mypin;
    }


- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control {

   PinDrop *annView = view.annotation;
    CashPointDetailViewController *detailView = [[CashPointDetailViewController alloc]init];
    theCashList = [myArray objectAtIndex:annView.index];
    detailView.theCashList = theCashList;
    [self.navigationController pushViewController:detailView animated:YES];

}


- (void)viewDidUnload {

    [super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:   (UIInterfaceOrientation)interfaceOrientation {
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

EDIT: Here is my .h if it helps.

#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "CashPointList.h"
#import <MapKit/MapKit.h>
#import "PinDrop.h"

@interface CashPointMapViewController : UIViewController  {

    MKMapView *mapview;
    PinDrop *ann;
}

    @property (nonatomic, retain) AppDelegate *app;
    @property (nonatomic, retain) CashPointList *theCashList;
    @property (nonatomic, retain) PinDrop *ann;
    @property (nonatomic, retain) IBOutlet MKMapView *mapview;
    @property (nonatomic, readwrite) int count;
    @property (nonatomic, retain) NSMutableArray *myArray;
    @property (nonatomic) MKPinAnnotationColor pinColor;

    -(IBAction) getlocation;


@end

解决方案

It's not a problem related to the map reloading tiles.

The issue is that the code in the viewForAnnotation delegate is using the ann object with the incorrect assumption that the class-instance-level ann object will be in sync with whenever the delegate method is called.

The viewForAnnotation delegate is not necessarily called in the order that you add annotations and can be called multiple times for the same annotation if the map needs to re-display an annotation when it comes back into view.

When the delegate method gets called again for a previously added annotation, ann and annotation no longer point to the same object. ann is now probably pointing to the last added annotation and so all the annotations change to its color.

In that delegate method, you must use the annotation parameter which is a reference to the annotation that the map view wants the view for in the current call (which may be completely unrelated to your outside loop).

So this line:

MKPinAnnotationView *mypin = [[MKPinAnnotationView alloc] 
    initWithAnnotation:ann reuseIdentifier:@"current"];

should be:

MKPinAnnotationView *mypin = [[MKPinAnnotationView alloc] 
    initWithAnnotation:annotation reuseIdentifier:@"current"];
                       ^^^^^^^^^^

and when checking the annotation's properties, use the annotation parameter (and cast it to your custom class to get at the custom properties):

PinDrop *ann = (PinDrop *)annotation;
//Note that this local "ann" is NOT the same as the class-level "ann".
//May want to use a different name to avoid confusion.
//The compiler may also warn you about this.

if (ann.price == 1)
...


A separate, unrelated, but highly recommended suggestion is to implement annotation view re-use by using dequeueReusableAnnotationViewWithIdentifier. This will improve performance when you have lots of annotations.

这篇关于MapView Pin Annotation的问题 - 当地图缩放/平移/区域更改时,Pin会丢失颜色的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆