I'm trying to replace the MKAnnotationView image depending on an object value, the code is executed but the images are randomly assigned so they are not matched with the correct values.
- (MKAnnotationView *)mapView:(MKMapView *)mapview viewForAnnotation:(EventAnnotation *)annotation{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
MKAnnotationView *annotationView = [mapview dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
if(annotationView)
return annotationView;
else
{
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationIdentifier];
annotationView.canShowCallout = YES;
annotationView.image = [self setImageByType:annotation];
annotationView.draggable = NO;
return annotationView;
}
return nil;
}
setImageByType method:
- (UIImage*)setImageByType:(EventAnnotation *)annotation{
//Set annotation image depending on its type
UIImage *image = [[UIImage alloc]init];
NSString *type = annotation.type;
if ([type isEqualToString:#"event"]) {
image = [UIImage imageNamed:#"geolocalization_events"];
}else if ([type isEqualToString:#"show"]){
image = [UIImage imageNamed:#"geolocalization_shows"];
}else if ([type isEqualToString:#"culture"]){
image = [UIImage imageNamed:#"geolocalization_culture"];
}else if ([type isEqualToString:#"eat"]){
image = [UIImage imageNamed:#"geolocalization_eat"];
}else if ([type isEqualToString:#"drink"]){
image = [UIImage imageNamed:#"geolocalization_drink"];
}else if ([type isEqualToString:#"cybercafe"]){
image = [UIImage imageNamed:#"geolocalization_cybercafe"];
}
UIImage *finalImage = [self imageWithImage:image scaledToSize:CGSizeMake(50, 50)];
return finalImage;
}
resize the image:
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
//Resize annotation image
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I would say the code is executed faster than the images are assigned to the views. Any ideas?
Option 1
Try changing this line:
static NSString* AnnotationIdentifier = #"AnnotationIdentifier";
To this:
NSString* AnnotationIdentifier = annotation.type;
Option 2:
After this line:
MKAnnotationView *annotationView = [mapview dequeueReusableAnnotationViewWithIdentifier:AnnotationIdentifier];
Add this line:
annotationView.image = [self setImageByType:annotation];
Related
I have 2 MKPointAnnotation and i want to display them on map with two different pins(MKAnnotationView having image).
// MKPointAnnotation - 1
CLLocationCoordinate2D cordinate;
cordinate.latitude = [_latitudeString doubleValue];
cordinate.longitude = [_longitudeString doubleValue];
MKPointAnnotation *point1 = [[MKPointAnnotation alloc] init];
point1.coordinate = CLLocationCoordinate2DMake(cordinate.latitude, cordinate.longitude);
[self.mapView addAnnotation:point1];
P.S - When i get second MKPointAnnotation i needed self zoom on that area.
// MKPointAnnotation - 2
CLLocationCoordinate2D cordinate;
cordinate.latitude = [_latStr doubleValue];
cordinate.longitude = [_longStr doubleValue];
MKPointAnnotation *point2 = [[MKPointAnnotation alloc] init];
point2.coordinate = CLLocationCoordinate2DMake(cordinate.latitude, cordinate.longitude);
[self.mapView addAnnotation:point2];
//This is my code for MKAnnotationView
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[MKPointAnnotation class]]){
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if(!pinView){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"annotation"];
pinView.calloutOffset = CGPointMake(0, 0);
}
else{
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
What i need to change in the viewForAnnotation method?
For example, you can create subclass of MKPointAnnotation.
#interface SecondAnnotation: MKPointAnnotation
#end
#implementation SecondAnnotation
#end
Add SecondAnnotation to the mapView.
// MKPointAnnotation - 2
...
SecondAnnotation *point2 = [[SecondAnnotation alloc] init];
point2.coordinate = CLLocationCoordinate2DMake(cordinate.latitude,
cordinate.longitude);
[self.mapView addAnnotation:point2];
You can use different MKAnnotationView with the following code.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[MKPointAnnotation class]]){
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if(!pinView){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"Annotation"];
pinView.calloutOffset = CGPointMake(0, 0);
}
else{
pinView.annotation = annotation;
}
return pinView;
} else if ([annotation isKindOfClass:[SecondAnnotation class]]){
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if(!pinView){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"Second"];
pinView.calloutOffset = CGPointMake(0, 0);
}
else{
pinView.annotation = annotation;
}
return pinView;
}
return nil;
}
Writing the viewForAnnotation as below solved my problem -
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation{
if ([annotation isKindOfClass:[MKPointAnnotation class]]){
MKAnnotationView *pinView = (MKAnnotationView*)[mapView dequeueReusableAnnotationViewWithIdentifier:#"CustomPinAnnotationView"];
if(!pinView){
pinView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"CustomPinAnnotationView"];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"annotation"];
pinView.calloutOffset = CGPointMake(0, 0);
}
else{
pinView.annotation = annotation;
if ([annotation isKindOfClass:[SecondAnnotation class]]) {
pinView.image = [UIImage imageNamed:#"range"];
}
else{
pinView.image = [UIImage imageNamed:#"annotation"];
}
}
return pinView;
}
return nil;
}
For some annotationViews I set some sublayer. First load sublayers match images, but
when I refresh map (clear annotationViews and re-parse info) sublayers not match places and images.
And after each refresh sublayer appears at different positions.
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
SYLocationItem * currentItem;
static NSString *identifier = #"SYLocationItem";
if ([annotation isKindOfClass:[SYLocationItem class]]) {
CATextLayer* subtitle1Text = [CATextLayer layer];
CALayer *sublayer = [CALayer layer];
MKAnnotationView *annotationView = (MKAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = NO;
} else {
annotationView.annotation = annotation;
}
currentItem = annotationView.annotation;
SYJabberClient *client = [SYJabberClient sharedClient];
[client retrieveProfileForUserWithEmail:[(SYLocationItem*)annotation email]
withSuccessBlock:^(NSDictionary *dict, NSError *error) {
if (dict) {
UIImage *image = [dict objectForKey:#"imageFile"];
UIImage *displayImage = [UIImage circularScaleNCrop:image
withRect:
CGRectMake(0.0f,0.0f,30.0f,30.0f)];
annotationView.image = displayImage;
if(currentItem.groupSamePlace != nil){
sublayer.backgroundColor = [UIColor redColor].CGColor;
sublayer.cornerRadius = 9.0;
sublayer.frame = CGRectMake(20, -7, 20, 20);
[subtitle1Text setFontSize:12];
[subtitle1Text setFrame:CGRectMake(0, 3, 20, 20)];
NSString *string = [NSString stringWithFormat:#"%#", currentItem.samePlaceCount];
[subtitle1Text setString:string];
[subtitle1Text setAlignmentMode:kCAAlignmentCenter];
[subtitle1Text setForegroundColor:[[UIColor whiteColor] CGColor]];
[sublayer addSublayer:subtitle1Text];
[annotationView.layer addSublayer:sublayer];
}
}
}];
return annotationView;
}
return nil;
}
p.s. Images in correct places.
I found solution.
When refresh just don't use clause:
if (annotationView == nil){
} else {
annotationView.annotation = annotation;
}
I am parse Json with coordinates and download individual profile image for each annotation view. When I do zoom or move on map I see what images replaced on wrong places. For example I have annotation view with coordinates 111.1111, 111.1111. First time image and coordinate is correct, but after moves/zoom/reopen tab with map I see other annotation view with coordinates 222.222, 222.222 with image which is suitable for 111.111, 111.1111.
(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
static NSString *identifier = #"SYLocationItem";
if ([annotation isKindOfClass:[SYLocationItem class]]) {
MKAnnotationView *annotationView = (MKAnnotationView *) [_mapView dequeueReusableAnnotationViewWithIdentifier:identifier];
if (annotationView == nil) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:identifier];
annotationView.enabled = YES;
annotationView.canShowCallout = NO;
SYJabberClient *client = [SYJabberClient sharedClient];
[client retrieveProfileForUserWithEmail:[(SYLocationItem*)annotation email]
withSuccessBlock:^(NSDictionary *dict, NSError *error) {
if (dict) {
UIImage *image = [dict objectForKey:#"imageFile"];
UIImage *displayImage = [UIImage circularScaleNCrop:image
withRect:
CGRectMake(0.0f,0.0f,30.0f,30.0f)];
annotationView.image = displayImage;
}
}];
} else {
annotationView.annotation = annotation;
}
return annotationView;
}
return nil;
}
In this code now I get image from local, but if downloading images I have same issue.
Based on my different enum values, I need to display the different images in my mapview.
How I can do that ? I am new to iOS development. Please anybody help me.
You need to use "ViewForAnnotation" delegate method in your view Controller.
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation
{
if( [annotation isKindOfClass:[Annotation class] ] )
{
static NSString * AnnotationID = #"Annotation";
Annotation * pannotation = (Annotation *)annotation;
//if( pannotation == nil ) return nil;
MKAnnotationView *annotationView = nil;
annotationView = [self.mMapView dequeueReusableAnnotationViewWithIdentifier:AnnotationID];
if( annotationView == nil )
{
annotationView = [[[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationID] autorelease];
}
UIImage * flagImage = nil;
if(Your enum Values)
flagImage = [UIImage imageNamed:#"darkgreendot.png"];
else if(....)
flagImage = [UIImage imageNamed:#"orangedot.png"];
else
flagImage = [UIImage imageNamed:#"bluedot.png"];
CGRect resizeRect;
resizeRect.size = flagImage.size;
resizeRect.origin = (CGPoint){0.0f, 0.0f};
UIGraphicsBeginImageContext(resizeRect.size);
[flagImage drawInRect:resizeRect];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
annotationView.image = resizedImage;
return annotationView;
}
}
Hope this helps you.
I have made an app, but on ipad 1 it crashes in the end part. On ipad-higher it remains working, but still I think I am doing something wrong, I really need to make something working more economically. But what is it?
In the end part it all happens. Before that, several screens are put onto each other and in the simulator when you go back they all are dismissed. But on the ipad 1 you will not even reach the end of the end part. I will try to explain what happens and several idea's about what is happening I have.
You can swipe on the screen and retina images (big images) are exchanged with the four corners that can get selected, each with a different image-background. There are six different scenes, so there are 6x4 + 6x1 for-normal-0-situation, 25 big retina images. There are only 5 frames working on top of each other (4 corners and 1 background), but I set inactive stuff to nil and load active images with imageNamed. It goes well on the simulator, but it crashes on the ipad 1, with no low memory warning or what so ever.
I've studied improvements: a) autorelease pool b) imageNamed replaced by imageContentsOfFile.
The autorelease pools don't have any effect. imageNamed, I couldn't get imageContentsOfFile working, so I skipped the operation.
Any ideas of what is so excessively wrong and what kind of thoughts can be applied to have it work more economically, for it somewhere is demanding way too much in the end.
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
CGPoint tappedPt = [[touches anyObject] locationInView:self.view];
NSArray *subviews = [[NSArray alloc]init];
subviews = [self.view subviews];
// Return if there are no subviews
if ([subviews count] == 0) return;
for (UIView *subview in subviews) {
if ([subview pointInside:[self.view convertPoint:tappedPt toView:subview] withEvent:event]){
[self checkAndChange:subview];
[self modifyChoice:subview];
}
}
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// Get the subviews of the view
CGPoint tappedPt = [[touches anyObject] locationInView:self.view];
NSArray *subviews = [[NSArray alloc]init];
subviews = [self.view subviews];
// Return if there are no subviews
if ([subviews count] == 0) return;
for (UIView *subview in subviews) {
if ([subview pointInside:[self.view convertPoint:tappedPt toView:subview] withEvent:event]){
[self checkAndChange:subview];
[self modifyChoice:subview];
}
}
}
-(void) modifyChoice:(UIView *)subview
{
if(subview==area1LinksBoven){[gekozenExpressieBijDimensie replaceObjectAtIndex:dimensie-1 withObject:[NSNumber numberWithInteger:1]];}
if(subview==area2RechtsBoven){[gekozenExpressieBijDimensie replaceObjectAtIndex:dimensie-1 withObject:[NSNumber numberWithInteger:2]];}
if(subview==area3RechtsOnder){[gekozenExpressieBijDimensie replaceObjectAtIndex:dimensie-1 withObject:[NSNumber numberWithInteger:3]];}
if(subview==area4LinksOnder){[gekozenExpressieBijDimensie replaceObjectAtIndex:dimensie-1 withObject:[NSNumber numberWithInteger:4]];}
if(maxChoice<dimensie){maxChoice=dimensie;
if(maxChoice==1){headerGevuld.image = [UIImage imageNamed:#"TOP1.png"];}
if(maxChoice==2){headerGevuld.image = [UIImage imageNamed:#"TOP2.png"];}
if(maxChoice==3){headerGevuld.image = [UIImage imageNamed:#"TOP3.png"];}
if(maxChoice==4){headerGevuld.image = [UIImage imageNamed:#"TOP4.png"];}
if(maxChoice==5){headerGevuld.image = [UIImage imageNamed:#"TOP5.png"];}
if(maxChoice==6){headerGevuld.image = [UIImage imageNamed:#"TOP6.png"];}
}
}
-(void) checkAndChange:(UIView *)subview{
if(subview==area1LinksBoven){
area1LinksBoven.image = [UIImage imageNamed:#"SELECTION1.png"];
area2RechtsBoven.image = nil;
area3RechtsOnder.image = nil;
area4LinksOnder.image = nil;
footer.image = [UIImage imageNamed:#"FOOT1.png"];
#autoreleasepool {
if(dimensie==1){
filmAchtergrond0.image = [UIImage imageNamed:#"1PassiefActiefOntspanning.jpg"];}
if(dimensie==2){
filmAchtergrond0.image = [UIImage imageNamed:#"1MakkelijkMoeilijkMaster.jpg"];}
if(dimensie==3){
filmAchtergrond0.image = [UIImage imageNamed:#"1VeiligGevaarlijkGeborgenheid.jpg"];}
if(dimensie==4){filmAchtergrond0.image = [UIImage imageNamed:#"1NormaalBijzonderGeaard.jpg"];}
if(dimensie==5){filmAchtergrond0.image = [UIImage imageNamed:#"1AlleenSamenUniek.jpg"];}
if(dimensie==6){filmAchtergrond0.image = [UIImage imageNamed:#"1OrdeChaosDuidelijk.jpg"];}
}
[arrowRight setImage:[UIImage imageNamed:#"ARROW_RIGHT_ACTIVE.png"] forState:UIControlStateNormal];
}
if(subview==area2RechtsBoven){
area1LinksBoven.image = nil;
area2RechtsBoven.image = [UIImage imageNamed:#"SELECTION2.png"];
area3RechtsOnder.image = nil;
area4LinksOnder.image = nil;
footer.image = [UIImage imageNamed:#"FOOT2.png"];
#autoreleasepool {
if(dimensie==1){filmAchtergrond0.image = [UIImage imageNamed:#"2PassiefActiefEnergiek.jpg"];}
if(dimensie==2){
filmAchtergrond0.image = [UIImage imageNamed:#"2MakkelijkMoeilijkUitdagend.jpg"];}
if(dimensie==3){
filmAchtergrond0.image = [UIImage imageNamed:#"2VeiligGevaarlijkSpannend.jpg"];}
if(dimensie==4){filmAchtergrond0.image = [UIImage imageNamed:#"2NormaalBijzonderWow.jpg"];}
if(dimensie==5){filmAchtergrond0.image = [UIImage imageNamed:#"2AlleenSamenGezellig.jpg"];}
if(dimensie==6){filmAchtergrond0.image = [UIImage imageNamed:#"2OrdeChaosImproviseren.jpg"];}
}
[arrowRight setImage:[UIImage imageNamed:#"ARROW_RIGHT_ACTIVE.png"] forState:UIControlStateNormal];
}
if(subview==area3RechtsOnder){
area1LinksBoven.image = nil;
area2RechtsBoven.image = nil;
area3RechtsOnder.image = [UIImage imageNamed:#"SELECTION3.png"];
area4LinksOnder.image = nil;
footer.image = [UIImage imageNamed:#"FOOT3.png"];
#autoreleasepool {
if(dimensie==1){
filmAchtergrond0.image = [UIImage imageNamed:#"3PassiefActiefUitputting.jpg"];}
if(dimensie==2){
filmAchtergrond0.image = [UIImage imageNamed:#"3MakkelijkMoeilijkFrustrerend.jpg"];}
if(dimensie==3){
filmAchtergrond0.image = [UIImage imageNamed:#"3VeiligGevaarlijkGevaarlijk.jpg"];}
if(dimensie==4){
filmAchtergrond0.image = [UIImage imageNamed:#"3NormaalBijzonderOnbegrijjpelijk.jpg"];}
if(dimensie==5){filmAchtergrond0.image = [UIImage imageNamed:#"3AlleenSamenGroepsdruk.jpg"];}
if(dimensie==6){filmAchtergrond0.image = [UIImage imageNamed:#"3OrdeChaosRommeltje.jpg"];}
}
[arrowRight setImage:[UIImage imageNamed:#"ARROW_RIGHT_ACTIVE.png"] forState:UIControlStateNormal];
}
if(subview==area4LinksOnder){
area1LinksBoven.image = nil;
area2RechtsBoven.image = nil;
area3RechtsOnder.image = nil;
area4LinksOnder.image = [UIImage imageNamed:#"SELECTION4.png"];
footer.image = [UIImage imageNamed:#"FOOT4.png"];
#autoreleasepool {
if(dimensie==1){filmAchtergrond0.image = [UIImage imageNamed:#"4PassiefActiefApathie.jpg"];}
if(dimensie==2){filmAchtergrond0.image = [UIImage imageNamed:#"4MakkelijkMoeilijkSaai.jpg"];}
if(dimensie==3){
filmAchtergrond0.image = [UIImage imageNamed:#"4VeiligGevaarlijkBeklemmend.jpg"];}
if(dimensie==4){filmAchtergrond0.image = [UIImage imageNamed:#"4NormaalBijzonderSleur.jpg"];}
if(dimensie==5){filmAchtergrond0.image = [UIImage imageNamed:#"4AlleenSamenEenzaam.jpg"];}
if(dimensie==6){filmAchtergrond0.image = [UIImage imageNamed:#"4OrdeChaosRigide.jpg"];}
}
[arrowRight setImage:[UIImage imageNamed:#"ARROW_RIGHT_ACTIVE.png"] forState:UIControlStateNormal];
}
if(dimensie==1){headerPositie.image = [UIImage imageNamed:#"OUT1.png"];}
if(dimensie==2){headerPositie.image = [UIImage imageNamed:#"OUT2.png"];}
if(dimensie==3){headerPositie.image = [UIImage imageNamed:#"OUT3.png"];}
if(dimensie==4){headerPositie.image = [UIImage imageNamed:#"OUT4.png"];}
if(dimensie==5){headerPositie.image = [UIImage imageNamed:#"OUT5.png"];}
if(dimensie==6){headerPositie.image = [UIImage imageNamed:#"OUT6.png"];}
}
Load the images using UIImage imageWithContentsOfFile:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"fileName" ofType:#"fileExtension"];
UIImage *img = [UIImage imageWithContentsOfFile:filePath];
See here the difference between imageNamed and imageWithContentsOfFile:
http://developer.apple.com/library/ios/#documentation/uikit/reference/UIImage_Class/Reference/Reference.html