【问题标题】:MapKit Memory Leaks. No Idea WhyMapKit 内存泄漏。不知道为什么
【发布时间】:2011-07-26 22:50:55
【问题描述】:

我正在设备上的仪器中运行泄漏工具。我得到了 MKReverseGeocoder、MKReverseGeocoderInternal 和 NSCFString 的泄漏(指向 -(void)reverseGeocoder: didFindPlacemark)。我已经处理这些泄漏超过 2 天,但找不到解决方案。如果有人能指出我正确的方向,我会非常亲切。

.H

@interface ReviewViewController : UIViewController <MKMapViewDelegate, MKReverseGeocoderDelegate,MKAnnotation > {
    IBOutlet UIImageView *_changingStationIV;
    IBOutlet UIImageView *_feedingAreaIV;
    IBOutlet UIImageView *_highChairIV;
    IBOutlet MKMapView *_mapView;
    MKReverseGeocoder *_reverseGeocoder;
    SGFeature *_place;
    MKPlacemark *_loc;

}

@property(nonatomic,retain)IBOutlet UIImageView *changingStationIV;
@property(nonatomic,retain)IBOutlet UIImageView *feedingAreaIV;
@property(nonatomic,retain)IBOutlet UIImageView *highChairIV;
@property(nonatomic,retain)IBOutlet MKMapView *mapView;
@property(nonatomic,retain) MKReverseGeocoder *reverseGeocoder;
@property(nonatomic,retain) SGFeature *place;
@property(nonatomic,retain) MKPlacemark *loc;

@end

.M

        @implementation ReviewViewController
     @synthesize changingStationIV=_changingStationIV,feedingAreaIV=_feedingAreaIV, highChairIV= _highChairIV, reverseGeocoder= _reverseGeocoder, mapView=_mapView,loc=_loc,coordinate=_coordinate,place=_place;

     // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
        [super viewDidLoad];
        NSLog(@"ViewDidLoad");

    NSLog(@"CURRENT PLACE %@",  [[self.place asDictionary] description]);

    NSDictionary *props = [self.place properties];

    self.title = [props objectForKey:@"name"];

    NSLog(@"changingStation: %@", [props objectForKey:@"changingStation"]);

    NSLog(@"feedingArea: %@", [props objectForKey:@"feedingArea"]);

    NSLog(@"highChair: %@", [props objectForKey:@"highChair"]);

    if ([[props objectForKey:@"changingStation"] boolValue]==YES) {
        self.changingStationIV.image = [UIImage imageNamed:@"check.png"];
    }else {
        self.changingStationIV.image = [UIImage imageNamed:@"x.png"];
    }
    if ( [[props objectForKey:@"feedingArea"] boolValue]==YES) {
        self.feedingAreaIV.image = [UIImage imageNamed:@"check.png"];
    }else {
        self.feedingAreaIV.image = [UIImage imageNamed:@"x.png"];
    }
    if ( [[props objectForKey:@"highChair"] boolValue]==YES) {
        self.highChairIV.image = [UIImage imageNamed:@"check.png"];
    }else {
        self.highChairIV.image = [UIImage imageNamed:@"x.png"];
    }

    SGPoint *point = (SGPoint*)[self.place geometry];
    CLLocationCoordinate2D locCoord = CLLocationCoordinate2DMake(point.latitude, point.longitude);
    NSDictionary *locDict = [NSDictionary dictionaryWithObject:[props objectForKey:@"name"] forKey:@"Country"];
    self.loc = [[MKPlacemark alloc] initWithCoordinate:locCoord addressDictionary:locDict];
    [self.mapView addAnnotation:self.loc];


    MKUserLocation *userLocation = self.mapView.userLocation;
    CLLocationCoordinate2D coord = userLocation.location.coordinate;
    [self.mapView setCenterCoordinate:coord animated:YES];

    MKCoordinateRegion region;
    MKCoordinateSpan span;
    region.center = locCoord;
    span.latitudeDelta =0.005334;
    span.longitudeDelta = 0.011834;
    region.span = span;

    [self.mapView setCenterCoordinate:locCoord animated:YES];
    [self.mapView setRegion:region animated:YES];


        self.reverseGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:locCoord];
        self.reverseGeocoder.delegate = self;
            [self.reverseGeocoder start];



    }


        -(void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFailWithError:(NSError *)error{

        }

        -(void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark{

                self.mapView.userLocation.title = placemark.title;

        }   


        - (void)didReceiveMemoryWarning {
            // Releases the view if it doesn't have a superview.
            [su

per didReceiveMemoryWarning];

        // Release any cached data, images, etc. that aren't in use.
    }

    - (void)viewDidUnload {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;

    NSLog(@"ViewDidUnload");


        self.changingStationIV =nil;
        self.feedingAreaIV=nil;
        self.highChairIV=nil;
        self.reverseGeocoder=nil;
        self.place=nil;
        self.loc=nil;


    }


    - (void)dealloc {

        NSLog(@"Review-Dealloc");


        self.reverseGeocoder=nil;
        self.mapView=nil;
        self.changingStationIV =nil;
        self.feedingAreaIV=nil;
        self.highChairIV=nil;
        self.place=nil;
        self.loc=nil;


        [super dealloc];

    }


    @end

【问题讨论】:

  • 我发现 Mapkit 也到处泄漏——即使你正在实现一个非常基本的开箱即用地图
  • 能否也发布头文件,以便我们查看属性是如何声明的?
  • (nonatomic,retain) 标头来了...
  • 您是否还保留了代表?我建议将委托设置为分配,这样就没有保留周期。
  • 您能进一步解释一下吗?我很困惑..我添加了 self.mapView.delegate = self;

标签: iphone cocoa-touch memory-management memory-leaks


【解决方案1】:

您肯定在这里泄漏了内存:

    self.loc = [[MKPlacemark alloc] initWithCoordinate:locCoord 
                                     addressDictionary:locDict];

由于您已将loc 定义为retain 属性,分配给它会在参数上调用retaing,您最终会得到一个MKPlacemark,该产品被保留但从未释放。

我会按如下方式更改该行:

    self.loc = [[[MKPlacemark alloc] initWithCoordinate:locCoord 
                                     addressDictionary:locDict] autorelease];

另外,请仔细检查您的代码是否有此模式,因为正如 @omz 所建议的,您在分配给 reverseGeocoder 时也会这样做。

【讨论】:

【解决方案2】:

在您的viewDidLoad 方法中,您可以像这样设置reverseGeocoder 属性:

self.reverseGeocoder = [[MKReverseGeocoder alloc] initWithCoordinate:locCoord];

这会泄漏,因为属性设置器已经保留了对象。设置属性后需要释放或自动释放MKReverseGeocoder实例,例如:

self.reverseGeocoder = [[[MKReverseGeocoder alloc] initWithCoordinate:locCoord] autorelease];

【讨论】:

  • [self.reverseGeocoder release] 会怎样?我仍然对为什么要释放该财产感到困惑
  • 您已将您的属性声明为保留(请参阅标题),因此self.reverseGeocoder = ... 将自动向您用作属性的对象发送retain。由于您需要平衡每个alloc-initretain 与相应的releaseautorelease,因此您缺少一个release
猜你喜欢
  • 1970-01-01
  • 2012-01-01
  • 2013-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多