Put user profile photo to map pin in ios dynamically - ios

I want to show all user photos to map in iOS.Here,all user photos are coming from server through web service.
let me attach screen show what I want to achieve to get better idea.
e.g image of pin:
So I want to create custom pin like above for all users to show in map of iphone application.
can any one redirect me to achieve above task in ios.
Thanks in advance.

I am pasting a code from one of my project. but you will get main idea. i am dealing with bunch or different stores so i add tag on every annotation. also i am using SDWebImage library to load remote images dynamically.
the green pin is mapPin and circle image is dynamically loaded from server
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
MKAnnotationView *aView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"mapPin"];
if(aView){
aView.annotation = annotation;
} else {
aView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"mapPin"];
ESMapViewAnnotation *newAnnotation=(ESMapViewAnnotation *)annotation;
ZBStore *s=(ZBStore *)[dataArray objectAtIndex:newAnnotation.tag];
NSString *iURL=s.Icon;
UIImageView *imageView = [[UIImageView alloc] init];
[imageView setImageWithURL:[NSURL URLWithString:iURL]
placeholderImage:[UIImage imageNamed:#"Question.jpg"]];
imageView.layer.borderWidth=1;
imageView.layer.borderColor=[[UIColor whiteColor]CGColor];
imageView.backgroundColor=s.BColor;
CGRect f= CGRectMake(2,2,46,43);
[imageView setFrame:f];
imageView.layer.cornerRadius=22.0;
imageView.layer.masksToBounds=YES;
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[aView addSubview:imageView];
aView.enabled = YES;
aView.canShowCallout = YES;
aView.image = [UIImage imageNamed:#"gPin2.png"];//here we use a nice image instead of the default pins
}
return aView;
//return nil;
}

Related

MKMapView with custom pins return to red standard pins on reload

I have an MKMapView that I add pins to. They load correctly with their relevant graphics but if I zoom in and zoom back out they loose their graphic and turn into a standard red pin with the only customisation being the pin name (even my disclosure indicator disappear).
So far to try and fix it I've tried:
Tried png’s, checked on faster device, Changed everything from MKPinAnnotation to MKAnnotation, returning to a normal MKAnnotation instead of my custom CBAnnotation, Various sample codes for loading custom pins, Lowered quality of map overlay in case it was a loading issue but still an issue.
- (void)addPins {
mapPinsArray = [[NSMutableArray alloc] init];
for (MapPoint *mappoint in mapPointsArray) {
CBAnnotation *annotation = [[CBAnnotation alloc] init];
annotation.coordinate = CLLocationCoordinate2DMake(mappoint.loclat, mappoint.loclong);
annotation.title = mappoint.stopAreaName;
annotation.mapPoint = mappoint;
[mapPinsArray addObject:annotation];
[self.myMapView addAnnotation:annotation];
}
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(CBAnnotation *)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
//do nothing
return nil;
} else {
MKAnnotationView *annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"trailPoint"];
annotationView.canShowCallout = YES;
ButtonWithData *accessoryViewButton = [[ButtonWithData alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
[accessoryViewButton setBackgroundImage:[UIImage imageNamed:#"right_arrow"] forState:UIControlStateNormal];
accessoryViewButton.buttonData = annotation.mapPoint;
[accessoryViewButton addTarget:self action:#selector(disclosureButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView = accessoryViewButton;
if (![[NSUserDefaults standardUserDefaults] boolForKey:annotation.mapPoint.stopAnimalName]) {
annotationView.image = [annotation.mapPoint lockedPinImage];
} else {
annotationView.image = [annotation.mapPoint unlockedPinImage];
}
return annotationView;
}
}
Fixed my own problem. I subclassed MKMapView to GenericMapView so that my code was cleaner (removing showsUserLocation, zoom/scroll/rotateEnabled, showsCompass etc. from the actual View Controller) but this meant the delegate wasn't setting correctly and viewForAnnotation wasn't being called on the pins reload.

Custom Annotation Callout View or Custom View ?

I'm currently building an "Uber-like" application, not in the same business but same design, and I would like to know what should I do if I want to represent their "Set pickup location" View/Button.
I already saw this post : Customize MKAnnotation Callout View? which was about Custom Annotation Callout View
In older version it looked like a Custom Callout View, but now it's a bit different, and I don't know where to start if I want to have the same result :
Thanks for your help !
To set different image on left accessory and right accessory, use this code.
// set different pins colors
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKAnnotationView *annotationView = nil;
if( [annotation isKindOfClass:[YOURANNOTATION class] ] )
{
static NSString * AnnotationID = #"YOURANNOTATION";
annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationID];
if( annotationView == nil )
{
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation
reuseIdentifier:AnnotationID] ;
}
UIImage * flagImage = nil;
flagImage = [UIImage imageNamed:#"marker-map#1x.png"];
[annotationView setImage:flagImage];
annotationView.canShowCallout = YES;
// add an image to the callout window
UIImageView *leftIconView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"marker-map#1x.png"]];
annotationView.leftCalloutAccessoryView = leftIconView;
//adding right button accessory
UIButton *infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
annotationView.rightCalloutAccessoryView = infoButton;
//image size and adding image on left accessory
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;
}
Then to call selected annotation
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
YOURANNOTATION *annotation=(YOURANNOTATION*)view.annotation;
//do something with your annotation
}

Having trouble passing UIImage to MKPinAnnotationView

I subclassed MKPointAnnotation and added a NSString and a UIImage so I can pass these elements to an MKPinAnnotationView. The string passes into the MKPinAnnotationView fine, but the image attribute is coming through as null. I can't figure out why. I will say that one time running this code on my phone the image appeared on a pin once, so maybe I have a memory leak? The other 1000 times I've compiled the images show as null in the log and do not appear. Any help is appreciated.
Here is my subclass customMapAnnotation.h:
#interface customMapAnnotation : MKPointAnnotation
#property (strong, nonatomic) NSString *restaurantID;
#property (strong, nonatomic) UIImage *restaurantIcon;
#end
Here is where my customMapAnnotation is created. I'm using Parse.com so there is a statement here to convert a PFFile to a UIImage. If I check the log I confirm that foodPoint.restaurantIcon has a value when this is ran.
customMapAnnotation *foodPoint = [[customMapAnnotation alloc] init];
foodPoint.coordinate = spot;
foodPoint.restaurantID = [object objectId];
foodPoint.title = [object objectForKey:#"restaurantName"];
foodPoint.subtitle = [object objectForKey:#"cuisineType"];
leftIcon = [object objectForKey:#"restaurantImage"];
[leftIcon getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (!error) {
image = [UIImage imageWithData:data];
// image can now be set on a UIImageView
foodPoint.restaurantIcon = image;
}
}];
[self.mainMap addAnnotation:foodPoint];
Now here is all of my code for my MKPinAnnotationView. Notice I run an NSLog to confirm if fp.restaurantIcon has a value, and it is null. I know this use of NSLog is not graceful, but it should return the memory location of the image. It comes back null. Again, my other custom attribute fp.restaurantId is working fine.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
static NSString *identifier = #"RoutePinAnnotation";
if (annotation == mapView.userLocation)
{
return nil;
}
else
{
MKPinAnnotationView *pinView = [[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:identifier];
pinView.animatesDrop=NO;
pinView.canShowCallout=YES;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//cast annotation parameter to our class so compiler understands...
customMapAnnotation *fp = (customMapAnnotation *)annotation;
NSLog(fp.restaurantIcon);
//get restaurantID from the annotation parameter ("fp")...
[rightButton setTitle:fp.restaurantID forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(buttonMethod:)
forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = rightButton;
//NSLog(fp.restaurantIcon);
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
pinView.leftCalloutAccessoryView = profileIconView;
return pinView;
}
}
Here is my didSelectAnnotationView:
- (void) mainMap:(MKMapView *)mainMap didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[chwMapAnnotation class]])
{
chwMapAnnotation *fp = (chwMapAnnotation *)view.annotation;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
view.leftCalloutAccessoryView = profileIconView;
}
}
I agree with the comment by #Vincent that since the images are being loaded in the background asynchronously, they have not yet been loaded when viewForAnnotation is called and so the annotation's callout is stuck with a blank left icon.
When the image loading is finished by getDataInBackgroundWithBlock, there is no automated signal telling the annotation view to refresh its leftCalloutAccessoryView.
A crude workaround in this case would be to manually force the refresh of the leftCalloutAccessoryView when the annotation is selected (which is when the callout will be displayed containing the leftCalloutAccessoryView).
When an annotation is selected, the map view calls the didSelectAnnotationView delegate method. Here, the crude workaround can be applied:
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
if ([view.annotation isKindOfClass:[customMapAnnotation class]])
{
customMapAnnotation *fp = (customMapAnnotation *)view.annotation;
UIImageView *profileIconView = [[UIImageView alloc] initWithImage:fp.restaurantIcon];
profileIconView.frame = CGRectMake(0,0,31,31);
view.leftCalloutAccessoryView = profileIconView;
}
}
Of course, it's possible that the image still hasn't loaded for the annotation that was selected (it's either just taking very long or the image url is invalid, etc).
What you can do is in viewForAnnotation, if fp.restaurantIcon is nil, set the left icon to some generic "loading" icon that you add to the project resources. In didSelectAnnotationView, you can also first check if fp.restaurantIcon is still nil and, if so, do nothing (ie. leave the icon as the generic "loading" icon).
A less crude solution might be to create a custom annotation view class that listens for an "image finished loading" message from its associated annotation and refreshes itself automatically.
I would say don't try to subclass MKPointAnnotation, create your own object that conforms to the MKAnnotation protocol, and use annotation views that are NOT MKPinAnnotationViews.

iOS mapView - drag pin with only one tap

I have a MapView with two pins on it (custom pins).
Both pins are set to draggable, but my problem is before I can drag one of them I first have to select it before I can start dragging it. This means two taps on the screen.
I know about this answer, but he only has one pin ons his map and it seems to me only one pin at a time can be selected so setting the [MyPin setSelected:YES]; wouldn't help me in this case.
Thanks for the help!
//Custom pin on mapview
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKAnnotationView *MyPin=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
MyPin.draggable = YES;
//Get annotaion title to determine what image to use
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc]init];
annotationPoint = annotation;
if([annotationPoint.title isEqualToString:#"user"])
{
MyPin.image = [UIImage imageNamed:#"userLocation_pin"];
MyPin.centerOffset = CGPointMake(-13, -5); //Offset custom image to display at the exact pin point GPointMake([left/right], [up/down]);
}
else if ([annotationPoint.title isEqualToString:#"destination"])
{
MyPin.image = [UIImage imageNamed:#"destination_pin_up"];
MyPin.centerOffset = CGPointMake(-13, -5); //Offset custom image to display at the exact pin point GPointMake([left/right], [up/down]);
}
return MyPin;
}
Managed to solve my own problem by adding the [MyPin setSelected:YES]; inside the if statements like this:
//Custom pin on mapview
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKAnnotationView *MyPin=[[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
MyPin.draggable = YES;
//Get annotaion title to determine what image to use
MKPointAnnotation *annotationPoint = [[MKPointAnnotation alloc]init];
annotationPoint = annotation;
if([annotationPoint.title isEqualToString:#"user"])
{
MyPin.image = [UIImage imageNamed:#"userLocation_pin"];
MyPin.centerOffset = CGPointMake(-13, -5); //Offset custom image to display at the exact pin point GPointMake([left/right], [up/down]);
[MyPin setSelected:YES];
}
else if ([annotationPoint.title isEqualToString:#"destination"])
{
MyPin.image = [UIImage imageNamed:#"destination_pin_up"];
MyPin.centerOffset = CGPointMake(-13, -5); //Offset custom image to display at the exact pin point GPointMake([left/right], [up/down]);
[MyPin setSelected:YES];
}
return MyPin;
}

Map Annotation Adding Image

Below, I have created an Annotation for my map which works perfectly and shows up with the title and subtitle as it should.
But I wish to add a small image to the left of the annotation but can't figure out what I need to do to the below code to make it work.
// Annotation
CLLocationCoordinate2D poseLocation;
poseLocation.latitude = POSE_LATITUDE;
poseLocation.longitude = POSE_LONGITUDE;
Annotation *myAnnotation = [[Annotation alloc] init];
myAnnotation.coordinate = poseLocation;
myAnnotation.title = #"Pose Beauty Salon";
myAnnotation.subtitle = #"100, Moneyhaw Road";
[self.myMapView addAnnotation:myAnnotation];
You will need to set the delegate of your myMapView first and implement the viewForAnnotation delegate method.
There you will return MKAnnotationView instance which has a property leftCalloutAccessoryView:
The view to display on the left side of the standard callout bubble.
The default value of this property is nil. The left callout view is
typically used to display information about the annotation or to link
to custom information provided by your application. The height of your
view should be 32 pixels or less.
In the leftCalloutAccessoryView, you can assign your image there. For example:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.myMapView dequeueReusableAnnotationViewWithIdentifier:#"annotation"];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annotation"];
UIImageView *imageView = //initialize your image view here
annotationView.leftCalloutAccessoryView = imageView;
}
annotationView.annotation = annotation;
return annotationView;
}
PS: Apparently you have asked similar question before here: Add image to the left of my annotations. I am not sure you need to post another question. Please try to implement this first.
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
MKPinAnnotationView *MyPin=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
myImage = [UIImage imageNamed:imagename];
CGRect cropRect = CGRectMake(0.0, 0.0,35.0, 35.0);
myImageView = [[UIImageView alloc] initWithFrame:cropRect];
myImageView.clipsToBounds = YES;
myImageView.image = myImage;
MyPin.leftCalloutAccessoryView =myImageView;
MyPin.highlighted=YES;
MyPin.canShowCallout=YES;
return MyPin;
}
It works for me , try this one

Resources