[英]What exactly does @synthesize do?
我看到了下面的一段代码:
//example.h
MKMapView * mapView1;
@property (nonatomic, retain) MKMapView * mapView;
//example.m
@synthesize mapView = mapView1
mapView
和mapView1
之间有什么关系? 它是否为mapView1
创建了set
和get
方法?
在您的示例中, mapView1
是一个实例变量(ivar),这是一块内存存储,属于example.h
和example.m
定义的类的实例。 mapView
是属性的名称。 属性是可以使用点表示法读取或设置的对象的属性: myObject.mapView
。 一个属性不必是基于伊娃,但大多数属性。 @property
声明只是告诉全世界有一个名为mapView
的属性。
@synthesize mapView = mapView1;
这一行告诉编译器为mapView
创建一个 setter 和 getter,并且他们应该使用名为mapView1
的 ivar。 如果没有= mapView1
部分,编译器将假定属性和 ivar 具有相同的名称。 (在这种情况下,这会产生编译器错误,因为没有名为mapView
ivar。)
这个@synthesize
语句的结果类似于如果你自己添加了这个代码:
-(MKMapView *)mapView
{
return mapView1;
}
-(void)setMapView:(MKMapView *)newMapView
{
if (newMapView != mapView1)
{
[mapView1 release];
mapView1 = [newMapView retain];
}
}
如果您自己将该代码添加到类中,则可以将@synthesize
语句替换为
@dynamic mapView;
最主要的是在 ivars 和属性之间有一个非常清晰的概念区别。 它们实际上是两个非常不同的概念。
@synthesize
为变量创建一个 getter 和一个 setter。
这使您可以为变量指定一些属性,并且当您将该属性@synthesize
到变量时,您将为变量生成 getter 和 setter。
属性名称可以与变量名称相同。 有时人们希望它是不同的,以便在init
或dealloc
使用它,或者在使用相同变量名传递参数时使用它。
从文档:
您可以使用 @synthesize 关键字告诉编译器,如果您不在 @implementation 块中提供它们,则它应该为属性合成 setter 和/或 getter 方法。
当我在编辑遗留代码时遇到这个问题时,我想对需要注意的现有答案做额外的说明。
即使使用较新的编译器版本,如果省略@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
将不再处理相同的变量。 如果你不期望像我那样的行为,这可能会让你头疼。
根据苹果文档@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 大部分时间用于重命名由您的属性支持的实例变量。
查看苹果文档
基本上合成创建了一个 setMapView 和 mapView 方法,它们设置和获取 mapView1
它为您的对象创建 getter 和 setter。 您可以使用以下内容访问:
MKMapView* m = object.mapView;
或者
object.mapView = someMapViewObject
mapView1 是类中 ivar 的名称,mapView 是 getter/setter 方法的名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.