Answers:
在您的示例中,mapView1
是实例变量(ivar),这是一块内存存储,属于example.h
和中定义的类的实例example.m
。mapView
是属性的名称。属性是可以使用点符号读取或设置的对象的属性myObject.mapView
。一个属性不会有是基于伊娃,但大多数属性。该@property
声明只是告诉世界,有一个名为的属性mapView
。
@synthesize mapView = mapView1;
这行代码告诉编译器为其创建一个setter和getter mapView
,并且他们应该使用称为的ivar mapView1
。没有该= mapView1
部分,编译器将假定属性和ivar具有相同的名称。(在这种情况下,由于没有调用ivar,因此会产生编译器错误mapView
。)
该@synthesize
语句的结果类似于您自己添加以下代码的结果:
-(MKMapView *)mapView
{
return mapView1;
}
-(void)setMapView:(MKMapView *)newMapView
{
if (newMapView != mapView1)
{
[mapView1 release];
mapView1 = [newMapView retain];
}
}
如果您确实将代码添加到类中,则可以将@synthesize
语句替换为
@dynamic mapView;
最主要的是在ivars和属性之间有一个非常清晰的概念区分。它们实际上是两个截然不同的概念。
当我在编辑遗留代码时遇到这个问题时,我想对现有答案做一些补充说明,这是需要注意的。
即使有新的编译器版本有时确实有差别,如果你忽略@synthesize propertyName
或没有。
如果您声明实例变量时不带下划线,但仍对其进行合成,例如:
标头:
@interface SomeClass : NSObject {
int someInt;
}
@property int someInt;
@end
实现方式:
@implementation SomeClass
@synthesize someInt;
@end
self.someInt
将访问与相同的变量someInt
。不为ivars使用领先的下划线并没有遵循命名约定,但是我只是遇到了必须阅读和修改此类代码的情况。
但是,如果您现在认为“嘿,@ synthesize不再重要,因为我们使用的是更新的编译器”,那么您错了!这样,您的课程将产生两个ivars,即someInt
加上一个自动生成的_someInt
变量。因此self.someInt
,someInt
将不再处理相同的变量。如果您不期望像我这样的行为,这可能会让您有些头疼。
@synchronize
是用于在访问属性时如何同步线程的指令,用于@synthesize
通过getter和setter将属性绑定到实例变量。
Autosynthesized property 'someInt' will use synthesized instance variable '_someInt', not existing instance variable 'someInt'
。(我不知道这个警告是在哪个版本的xcode中添加的。)
根据Apple文档,@ Synthesize仅用于重命名实例变量。例如
@property NSString *str;
@synthesize str = str2;
现在,在该类中您将无法使用,_str
因为上述行将实例变量重命名为str2
@property
允许对象被其他类中的对象使用,或者换句话说,将对象公开。
在@interface中创建属性时,该属性将由名为_propertyName的实例变量自动返回。因此,当您创建一个名为firstName的属性时,在后台编译器将默认创建一个名为_firstName的实例变量。编译器还将为您创建getter和setter方法(即firstName,setFirstName)。
现在,当您通过@synthesize firstName合成属性时,您只是在告诉编译器通过firstName重命名我的实例变量(_firstName)。如果要使用其他名称重命名备份的实例变量,则可以在合成属性名称时(即@synthesize firstName = myFirstName)简单地分配其他名称,这样做可以通过名为myFirstname的实例变量来备份属性。
简而言之,大多数情况下@synthesize用来重命名由属性备份的实例变量。