2
votes

I've been trying to get rid of memory leaks in mapview. I am using custom map pin class. Everything works, but problem is - I need to filter mapview results. when i remove all mapview annotations - and add filtered results - performance tool finds leaks. but in this mapPin class I am using are used autorelease, so they should be released, but they aren't. what am I doing wrong?

MapPin.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#import <MapKit/MKMapView.h>
#import <MapKit/MKAnnotation.h>

@interface MapPin : NSObject<MKAnnotation> {
    CLLocationCoordinate2D coordinate;
    NSString * picture;
    NSInteger tag_number;
}

@property (nonatomic,assign) CLLocationCoordinate2D coordinate;
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSString *subtitle;


- (id) initWithCoordinate:(CLLocationCoordinate2D) coord;
- (id) initWithCoordinate:(CLLocationCoordinate2D) coord title:(NSString *) title;
- (id) initWithCoordinate:(CLLocationCoordinate2D) coord title:(NSString *) title subtitle:(NSString *) subtitle;
- (id) initWithCoordinate:(CLLocationCoordinate2D) coord title:(NSString *) title subtitle:(NSString *) subtitle image:(NSString *) pic;
- (id) initWithCoordinate:(CLLocationCoordinate2D) coord title:(NSString *) title subtitle:(NSString *) subtitle image:(NSString *) pic num:(NSInteger) number;
- (void) setPic:(NSString *) picture;
- (NSString* ) getPic;

- (void) setNum:(NSInteger) tag_number;
- (NSInteger ) getNum;

@end

MapPin.m

#import "MapPin.h"


@implementation MapPin

@synthesize coordinate = _coordinate;
@synthesize title = _title;
@synthesize subtitle = _subtitle;


- (id) initWithCoordinate:(CLLocationCoordinate2D) coord
{
    return [self initWithCoordinate:coord title:@""];
}

- (id) initWithCoordinate:(CLLocationCoordinate2D) coord title:(NSString *) title {
    return [self initWithCoordinate:coord title:title subtitle:@""];

}
- (id) initWithCoordinate:(CLLocationCoordinate2D) coord title:(NSString *) title subtitle:(NSString *) subtitle {
    return [self initWithCoordinate:coord title:title subtitle:subtitle image:@""];}

- (id) initWithCoordinate:(CLLocationCoordinate2D) coord title:(NSString *) title subtitle:(NSString *) subtitle image:(NSString *) pic{
    MapPin * me = [[[MapPin alloc] init] autorelease];
    me.coordinate = coord;
    me.title = title;
    me.subtitle = subtitle;

    [me setPic:pic];

    return me;
}

- (id) initWithCoordinate:(CLLocationCoordinate2D) coord title:(NSString *) title subtitle:(NSString *) subtitle image:(NSString *) pic num:(NSInteger) number{
    MapPin * me = [[[MapPin alloc] init] autorelease];
    me.coordinate = coord;
    me.title = title;
    me.subtitle = subtitle;

    [me setPic:pic];
    [me setNum:number];
    return me;
}

- (void) setPic:(NSString*) pic {
    picture = pic;
}

- (NSString * ) getPic{
    return picture;
}

- (void) setNum:(NSInteger) number {
    tag_number = number;

}

- (NSInteger ) getNum{
    return tag_number;
}

@end
2
I don't see any dealloc method implementation. Are you using ARC?Denis
no ARC, just found this code on internet, and been using this class since then. just now decided to test on memory leaks.user979250

2 Answers

1
votes

I have been using cutom map pin created by Mayur Birari, which i tweaked a little bit, to support custom map pin images and id's.

CustomMapPin.h

#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>

@interface CustomMapPin : NSObject<MKAnnotation> {

    CLLocationCoordinate2D  coordinate;
    NSString*               title;
    NSString*               subtitle;

    NSString*               pic;
    NSInteger               tag_number;

}

@property (nonatomic, assign)   CLLocationCoordinate2D  coordinate;
@property (nonatomic, copy)     NSString*               title;
@property (nonatomic, copy)     NSString*               subtitle;
@property (nonatomic, copy)     NSString*               pic;
@property (nonatomic)           NSInteger               tag_number;


@end

CustomMapPin.m

#import "CustomMapPin.h"


@implementation CustomMapPin

@synthesize title;
@synthesize subtitle;
@synthesize coordinate;
@synthesize pic;
@synthesize tag_number;


- (void)dealloc 
{
    self.title = nil;
    self.pic = nil;
    self.subtitle = nil;
    [super dealloc];
}

@end

and using it in class like this:

CLLocationCoordinate2D pinlocation;

in a loop I set up required values and create a map pin:

pinlocation.latitude = ...;

pinlocation.longitude = ...;

NSInteger pinID = ....;


CustomMapPin* customMapPin=[[CustomMapPin alloc] init];

customMapPin.coordinate=(CLLocationCoordinate2D
    {pinlocation.latitude,pinlocation.longitude};

customMapPin.title=@"title";

customMapPin.subtitle=@"subtitle";

customMapPin.pic = @"customImageName";

customMapPin.tag_number = pinId;


[mapView addAnnotation:customMapPin];

Setting up custom image:

- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
    if ([annotation isKindOfClass: [CustomMapPin class]]) 
    {
        CustomMapPin * a = annotation;

        [annView setImage:[UIImage imageNamed:a.pic]];
    }
}

Getting pin id on callout:

- (void)mapView:(MKMapView *)mp annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
    CustomMapPin * v = (CustomMapPin *) view.annotation;

   int tagNumber = v.tag_number;

   ....
}

and finally - in my project It was required to have filter buttons - so I needed to remove all pins, and add required. By default calling mapview to remove all annotations created memory leaks. So when I need to clear mapview from annotations, I call this function:

- (void)removeAnnotations
{
    NSMutableArray *toRemove = [NSMutableArray arrayWithCapacity:[mapView.annotations count]];

    for (id annotation in mapView.annotations)
    {
        if (annotation != mapView.userLocation)
        {
            [toRemove addObject:annotation];
        }
    }

    [mapView removeAnnotations:toRemove];

    for(int i = 0; i < [toRemove count]; i++)
    {
        CustomMapPin * a = [toRemove objectAtIndex:i];

        [a release];

        a = nil;
    }
}

Hope this helps Happy coding! :)

0
votes

You were just missing dealloc implementation!

for example:

- (void)dealloc 
{
    [self.title release];

    self.title = nil;

    self.subtitle release];

    self.subtitle = nil;

    [super dealloc];
}