“合成”到底是做什么的?

我看到了下面这段代码:

//example.h
MKMapView * mapView1;
@property (nonatomic, retain) MKMapView * mapView;


//example.m
@synthesize mapView = mapView1

mapViewmapView1之间是什么关系? 它是否为 mapView1创建了 setget方法?

81337 次浏览

@synthesize为变量创建一个 getter 和一个 setter。

这使您可以为变量指定一些属性,当您将该属性 @synthesize为变量时,将为变量生成 getter 和 setter。

属性名可以与变量名相同。有时候人们希望它是不同的,以便在 initdealloc中使用它,或者当参数以相同的变量名传递时使用它。

来自 文件:

如果在@实现块中没有提供 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.hexample.m中定义的类的一个实例。mapView财产的名称。属性是可以使用点符号 myObject.mapView读取或设置的对象的属性。属性 不是基于变量的,但是大多数属性是基于变量的。@property声明只是告诉全世界有一个称为 mapView的属性。

@synthesize mapView = mapView1;

这一行告诉编译器为 mapView创建一个 setter 和 getter,并且它们应该使用名为 mapView1的 ivar。如果没有 = mapView1部分,编译器将假定属性和 ivar 具有相同的名称。(在本例中,这将产生编译器错误,因为没有名为 mapView的变量。)

这个 @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

@property允许其他类中的对象使用对象,换句话说,使对象公开。

当我在编辑遗留代码时遇到这个问题时,我想对现有的答案做一些额外的注释,这是需要注意的。

即使使用较新的编译器版本,省略 @synthesize propertyName或不省略 有时也会产生差异。

在这种情况下,你声明一个实例变量的 abc0下划线,同时仍然合成它,例如:

标题:

@interface SomeClass : NSObject {
int someInt;
}
@property int someInt;
@end

实施方法:

@implementation SomeClass
@synthesize someInt;
@end

self.someInt将访问与 someInt相同的变量。对 ivar 不使用前导下划线并不遵循命名约定,但是我只是遇到了必须阅读和修改这些代码的情况。

但是如果你现在认为 “嘿,合成已经不重要了,因为我们使用的是更新的编译器”你错了!那么你的类将导致 两个伊瓦尔,即 someInt加上一个自动生成的 _someInt变量。因此,self.someIntsomeInt将不再处理相同的变量。如果你没有预料到我会有这样的行为,你可能会很头疼地发现这一点。

当您在@interface 中创建一个属性时,该属性将由一个名为 as _ properties 名称的实例变量自动返回。 因此,当您创建一个名为 firstName 的属性时,场景编译器将在默认情况下创建一个名为 as _ firstName 的实例变量。编译器还将为您创建 getter 和 setter 方法(即 firstName、 setFirstName)。

现在,当您通过@synize firstName 合成属性时,您只需告诉编译器通过 firstName 重命名我的实例变量(_ firstName)。如果你想用不同的名字来重命名备份的实例变量,你可以在合成属性名的时候简单地分配不同的名字(比如@synize firstName = myFirstName) ,这样你的属性就会被一个名为 myFirstName 的实例变量备份。

因此,简而言之,大多数时候@synize 用来重命名你的实例变量,并且备份了你的资产。