MapView Pin Annotation的问题 - 当地图缩放/平移/区域更改时,Pin会丢失颜色 [英] Problems with MapView Pin Annotation - Pin loses color when map is zoomed/panned/region changes
问题描述
我有一个显示现金点位置的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屋!