@synthesize interferes with inheritance

FINAL EDIT

The solution to all life's problems:

Switching xcode's "Compiler Version" setting to "LLVM compiler 2.0" solves this issue, many thanks to Firoze Lafeer for the concerted, constructive assistance!

Intention was to build some really basic functionality into all my classes by subclassing NSObject and UIViewController with something to grab the application delegate, extend the viewDidAppear mechanism a little, etc. I've got a base class that looks something like this (only relevant lines included):

@interface PHView : UIViewController {
    id<PHAppDelegate> appDelegate;
}
-(id)init;
//some other method prototypes
@property (nonatomic, retain) id delegate;
@end

@implementation PHView
@synthesize delegate;

-(id)init {
    self = [super init];
    appDelegate = (id<PHAppDelegate>)[[UIApplication sharedApplication] delegate];
    visible = FALSE;
    initialized = FALSE;
    return self;
}
    //some other methods
@end

EDIT I should mention here that the property "delegate" isn't meant to point to ivar "appDelegate" or anything... I only left it in to illustrate that this superclass uses @synthesize. Since it's not a related useage I think it doesn't matter, but I wouldn't say that I know that.

Interface for the subclass:

@interface PinMap : PHView <MKMapViewDelegate> {
//@interface PinMap : UIViewController <MKMapViewDelegate> {
//    NSObject<PHAppDelegate>* appDelegate;
}
-(id)init;
-(void)zoomToUser;
@property (nonatomic, retain) IBOutlet MKMapView* map;
@end

This compiles:

@implementation PinMap
//@synthesize map;

-(PinMap*) init{
    self = [super init];
    //appDelegate = (NSObject<PHAppDelegate>*)[[UIApplication sharedApplication] delegate];    
    return self;
}

-(void)zoomToUser {
    //MKCoordinateRegion region = map.region;
    MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake((CLLocationDegrees)300, (CLLocationDegrees)300), MKCoordinateSpanMake((CLLocationDegrees)20,(CLLocationDegrees)20)); //random region
    region.center = [[appDelegate location] coordinate];
    region.span.longitudeDelta /= 50.0;
    region.span.latitudeDelta /= 50.0;
//    [map setRegion:region animated:NO];
}

This does not compile:

@implementation PinMap
@synthesize map;

-(PinMap*) init{
    self = [super init];
    //appDelegate = (NSObject<PHAppDelegate>*)[[UIApplication sharedApplication] delegate];    
    return self;
}

-(void)zoomToUser {
    MKCoordinateRegion region = map.region;
    //MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake((CLLocationDegrees)300, (CLLocationDegrees)300), MKCoordinateSpanMake((CLLocationDegrees)20,(CLLocationDegrees)20)); //random region
    region.center = [[appDelegate location] coordinate]; // <-- ERROR HERE
    region.span.longitudeDelta /= 50.0;
    region.span.latitudeDelta /= 50.0;
    [map setRegion:region animated:NO];
}

At the marked location, I get """'appDelegate' undeclared (first use in this function)""" My first step was to Clean, reboot and Clean again (fixed three bugs this week using that procedure) and when that didn't work I started trying things that make sense, and eventually some things that DON'T make sense.

The following DOES compile (and run) but I honestly don't understand why:

@interface PinMap : PHView <MKMapViewDelegate> {
//@interface PinMap : UIViewController <MKMapViewDelegate> {
    //NSObject<PHAppDelegate>* appDelegate;
    MKMapView* _map;
}
-(id)init;
-(void)zoomToUser;
@property (nonatomic, retain) IBOutlet MKMapView* map;
@end

@implementation PinMap
@synthesize map=_map;

-(PinMap*) init{
    self = [super init];
    //appDelegate = (NSObject<PHAppDelegate>*)[[UIApplication sharedApplication] delegate];    
    return self;
}

-(void)zoomToUser {
    MKCoordinateRegion region = self.map.region;
    //MKCoordinateRegion region = MKCoordinateRegionMake(CLLocationCoordinate2DMake((CLLocationDegrees)300, (CLLocationDegrees)300), MKCoordinateSpanMake((CLLocationDegrees)20,(CLLocationDegrees)20)); //random region
    region.center = [[appDelegate location] coordinate];
    region.span.longitudeDelta /= 50.0;
    region.span.latitudeDelta /= 50.0;
    [self.map setRegion:region animated:NO];
}

In this trim it'll respond to "self.map" but considers "map" to be undeclared.

EDIT The "self" requirement makes sense to me now, but the disappearing / reappearing "appDelegate" ivar is what I'm actually worried about. Sorry if that was unclear before. But seriously, what's up with that?

Answers


Well, for starters, PinMap doesn't have an instance variable (ivar) called 'map'.

It has a property called 'map', which you can access like so:

region = self.map.region;

Or it has an ivar called _map. So you could do this:

region = _map.region;

But the former is recommended. You made a property, so you probably want to use it (outside of initXXX and dealloc)

EDIT

Also, the designated initializer for UIViewController is initWithNibName:bundle:

So just make sure if you subclass UIViewController that you call its designated initializer.

EDIT AGAIN

In those cases in your comment, you probably have an ivar and a property with the same name. If you just do @synthesize propname, that's what you get. But in this case you did @synthesize map = _map.

It's worth taking the time to understand when you are accessing the ivar directly, versus the property. Otherwise a lot of things won't make sense, and other bugs will happen. To access the property you must do 'self.propertyName' (or [self propertyName] or [self setPropertyName:something])

If you aren't using self, you aren't using the getter/setter (this is often a bad thing, if for example your getter/setter is doing your memory mgmt or initialization for you). You also have to use the actual ivar name if you aren't going to use the property.

EDIT AGAIN AGAIN

I see changing the compiler helped. I would suggest two things then: double check all of your @synthesize statements to make sure you aren't asking the compiler to synthesize an ivar in a subclass that already exists in a superclass. While you're sorting that out, I would recommend you name your ivars as variable_ or _variable so you can easily see where you are using the ivar versus the property.

And more importantly, you should really upgrade to LLVM 3.0, which is included in Xcode 4.2.1.


Need Your Help

Understanding F# memory consumption

memory f#

I've been toying around with F# lately and wrote this little snippet below, it just creates a number of randomized 3d-vectors, puts them into a list, maps each vector to its length and sums up all ...

Why NodeList and node = NodeList behave differently?

javascript xml dom

In the following code excerpt, products is a xml nodelist, which structure is:

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.