@synthesize会干扰继承

时间:2011-12-01 23:04:29

标签: iphone objective-c

  

最终编辑

     

解决所有生活中的问题:   enter image description here

     

将xcode的“编译器版本”设置切换为“LLVM编译器2.0”解决了这个问题,非常感谢Firoze Lafeer提供的协调一致的建设性帮助!

意图是在我的所有类中构建一些非常基本的功能,通过继承NSObject和UIViewController来获取应用程序委托,稍微扩展viewDidAppear机制等等。我有一个看起来像这样的基类(只包括相关的行):

@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

编辑我应该在这里提一下,属性“委托”并不意味着指向ivar“appDelegate”或任何东西......我只是留下它来说明这个超类使用@synthesize 。由于它不是一个相关的用途我认为并不重要,但我不会说我知道

子类的接口:

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

编译:

@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];
}

这不编译:

@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];
}

在标记的位置,我得到“”“appDelegate”未声明(首次使用此功能)“”“我的第一步是清理,重新启动并再次清理(本周使用该程序修复了三个错误)以及何时那些不起作用的我开始尝试有意义的事情,最后是一些没有意义的事情。

以下DOES编译(并运行)但我老实说不明白为什么:

@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];
}

在此修剪中,它将响应“self.map”,但认为“map”未声明。

编辑“自我”要求现在对我有意义,但消失/重新出现的“appDelegate”ivar是我真正担心的。对不起,如果以前不清楚。但严重的是,那是怎么回事?

2 个答案:

答案 0 :(得分:2)

嗯,对于初学者来说,PinMap没有名为'map'的实例变量(ivar)。

它有一个名为'map'的属性,您可以这样访问:

region = self.map.region;

或者它有一个名为_map的ivar。所以你可以这样做:

region = _map.region;

但前者是推荐的。你创建了一个属性,所以你可能想要使用它(在initXXX和dealloc之外)

修改

此外,UIViewController的指定初始化程序是initWithNibName:bundle:

因此,请确保您是否将UIViewController子类化为您指定的初始化程序。

再次编辑

在评论中的那些情况下,您可能有一个ivar和一个同名的属性。如果你只是做@synthesize propname,那就是你得到的。但是在这种情况下你做了@synthesize map = _map。

值得花时间了解您何时直接访问ivar,而不是财产。否则很多事情都没有意义,其他错误也会发生。要访问该属性,您必须执行'self.propertyName'(或[self propertyName]或[self setPropertyName:something])

如果你没有使用self,你就不会使用getter / setter(这通常是一件坏事,例如你的getter / setter正在为你做内存管理或初始化)。如果您不打算使用该属性,您还必须使用实际的ivar名称。

再次编辑

我看到改变编译器有帮助。我会建议两件事:仔细检查你所有的@synthesize语句,以确保你没有要求编译器在已经存在于超类中的子类中合成一个ivar。当你对它进行排序时,我会建议你将你的ivars命名为variable_或_variable,这样你就可以很容易地看到你使用ivar和财产的位置。

更重要的是,您应该真正升级到XVM 4.2.1中包含的LLVM 3.0。

答案 1 :(得分:0)

@synthesize为属性创建setter和getter方法,但是它需要一些地方来存储该对象,因此您必须添加某种ivar以将@synthesize与属性一起使用

你可以做到

@interface ... : ... {
    Something* smth;
}

@property (nonatomic, retain) Something *smth;

@end

@implementation ...
@synthesize smth;
@end

@interface ... : ... {
    Something* _smth;
}

@property (nonatomic, retain) Something *smth;

@end

@implementation ...
@synthesize smth=_smth;
@end