我看到了下面这段代码:
//example.h MKMapView * mapView1; @property (nonatomic, retain) MKMapView * mapView; //example.m @synthesize mapView = mapView1
mapView和 mapView1之间是什么关系? 它是否为 mapView1创建了 set和 get方法?
mapView
mapView1
set
get
@synthesize为变量创建一个 getter 和一个 setter。
@synthesize
这使您可以为变量指定一些属性,当您将该属性 @synthesize为变量时,将为变量生成 getter 和 setter。
属性名可以与变量名相同。有时候人们希望它是不同的,以便在 init或 dealloc中使用它,或者当参数以相同的变量名传递时使用它。
init
dealloc
来自 文件:
如果在@实现块中没有提供 setter 和/或 getter 方法,那么可以使用@synize 关键字告诉编译器它应该合成属性的 setter 和/或 getter 方法。
参见 苹果文档
基本上,合成创建了一个 setMapView 和 mapView 方法来设置和获取 mapView1
它为你的对象创建 getter 和 setter:
MKMapView* m = object.mapView;
或者
object.mapView = someMapViewObject
MapView1是类中 ivar 的名称,mapView 是 getter/setter 方法的名称。
在您的示例中,mapView1是一个 实例变量(ivar) ,它是一块内存存储,属于在 example.h和 example.m中定义的类的一个实例。mapView是 财产的名称。属性是可以使用点符号 myObject.mapView读取或设置的对象的属性。属性 有不是基于变量的,但是大多数属性是基于变量的。@property声明只是告诉全世界有一个称为 mapView的属性。
example.h
example.m
myObject.mapView
@property
@synthesize mapView = mapView1;
这一行告诉编译器为 mapView创建一个 setter 和 getter,并且它们应该使用名为 mapView1的 ivar。如果没有 = mapView1部分,编译器将假定属性和 ivar 具有相同的名称。(在本例中,这将产生编译器错误,因为没有名为 mapView的变量。)
= mapView1
这个 @synthesize语句的结果类似于您自己添加的代码:
-(MKMapView *)mapView { return mapView1; } -(void)setMapView:(MKMapView *)newMapView { if (newMapView != mapView1) { [mapView1 release]; mapView1 = [newMapView retain]; } }
如果您自己将该代码添加到类中,则可以将 @synthesize语句替换为
@dynamic mapView;
主要的事情是要有一个非常清楚的区别,在概念上的变量和属性。它们实际上是两个完全不同的概念。
根据 apple 文档,@ 合成仅用于重命名实例变量
@property NSString *str; @synthesize str = str2;
现在在类中你不能使用 _str,因为上一行已经将实例变量重命名为 str2
_str
str2
@property允许其他类中的对象使用对象,换句话说,使对象公开。
当我在编辑遗留代码时遇到这个问题时,我想对现有的答案做一些额外的注释,这是需要注意的。
即使使用较新的编译器版本,省略 @synthesize propertyName或不省略 有时也会产生差异。
@synthesize propertyName
在这种情况下,你声明一个实例变量的 abc0下划线,同时仍然合成它,例如:
标题:
@interface SomeClass : NSObject { int someInt; } @property int someInt; @end
实施方法:
@implementation SomeClass @synthesize someInt; @end
self.someInt将访问与 someInt相同的变量。对 ivar 不使用前导下划线并不遵循命名约定,但是我只是遇到了必须阅读和修改这些代码的情况。
self.someInt
someInt
但是如果你现在认为 “嘿,合成已经不重要了,因为我们使用的是更新的编译器”你错了!那么你的类将导致 两个伊瓦尔,即 someInt加上一个自动生成的 _someInt变量。因此,self.someInt和 someInt将不再处理相同的变量。如果你没有预料到我会有这样的行为,你可能会很头疼地发现这一点。
_someInt
当您在@interface 中创建一个属性时,该属性将由一个名为 as _ properties 名称的实例变量自动返回。 因此,当您创建一个名为 firstName 的属性时,场景编译器将在默认情况下创建一个名为 as _ firstName 的实例变量。编译器还将为您创建 getter 和 setter 方法(即 firstName、 setFirstName)。
现在,当您通过@synize firstName 合成属性时,您只需告诉编译器通过 firstName 重命名我的实例变量(_ firstName)。如果你想用不同的名字来重命名备份的实例变量,你可以在合成属性名的时候简单地分配不同的名字(比如@synize firstName = myFirstName) ,这样你的属性就会被一个名为 myFirstName 的实例变量备份。
因此,简而言之,大多数时候@synize 用来重命名你的实例变量,并且备份了你的资产。