views:

58

answers:

3

The question is if insertSubview is retaining the views and if I'm doing it right.

I would say yes. Since I'm not using the property anymore I don't receive an EXC_BAD_ACCESS. I think when releasing the view all subviews are also released. And so mapView is over-released. I'm right or do I still have a memory management issue?

My ViewController.h

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

@interface MapViewController : UIViewController <MKMapViewDelegate> {

MKMapView *mapView;
// ...
}

//@property (nonatomic, retain) MKMapView *mapView;
// ...

@end

My ViewController.m

#import "MapViewController.h"

@implementation MapViewController

//@synthesize mapView;

- (void)viewDidLoad {
    [super viewDidLoad];

    //self.mapView=[[[MKMapView alloc] initWithFrame:self.view.bounds] autorelease];
    mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];

    [self.view insertSubview:mapView atIndex:0];
    [mapView release];

    // ...
}

- (void)dealloc {
    //[mapView release];
    [super dealloc];
}

@end
+2  A: 

Yes, you are correct on all counts:

  1. the call to insertSubView: should be retaining the mapView that you are passing it.
  2. releasing your reference to the mapView after you add it to the parent view
  3. the parent view will release all the retained subviews when it is released
highlycaffeinated
Do I have to worry about that `mapView` is not locally retained by my view controller?
testing
@testing - You don't need to retain `mapView` in your controller unless you are going to access it directly from your controller. Otherwise, your controller retains your view, your view retains it's subViews.
highlycaffeinated
@highlycaffeinated: I'm accessing it from my view controller (e.g. `[mapView setRegion:region animated:TRUE];`). Since the `mapView` is bounded to my view controller in most cases I'd not need the retain. But for safety reason I'll retain it.
testing
+1  A: 

As a rule, you should not worry about whether or how another object will retain an instance you give it. That's up to that object to deal with; you only have to worry about making sure an instance that you intend to directly access later is retained. Don't rely on another object to keep an instance retained for you.

In your example, you have an instance (mapView) which is accessible to MapViewController but MapViewController does not have it's own retention for it. self.view could release mapView at any time for any number of reasons and you'd suddenly have bad memory there.

What can I do against this? I wanted to use the property but this causes a crash ...
testing
You should be able to assign it to the property as in your commented out line (self.mapView = ...); just don't call [mapView release] after you add it to self.view. The autorelease plus that release will deallocate mapView at the end of the run loop.
@user168681: As you said now it works.
testing
+2  A: 
- (void)dealloc {
    //[mapView dealloc];
    [super dealloc];
}

You should never call dealloc directly (save for [super dealloc]; at the end of the method). That will most assuredly cause a crash in most situations.


Since that isn't the source of your crash, you have an over-release somewhere. Use Instrument's Zombie Detection to figure out where.

bbum
You're absolutely right! But if I release the property I still would get a crash.
testing
@bbum: I don't know why but now everything works fine. Before I used Instrument's and the view with "invalidateSubviewCache" was over-releasing the `mapView`. Perhaps I really missed the `dealloc` call.
testing