@synthesize到底是做什么的?


148

我看过以下代码:

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

//example.m
@synthesize mapView = mapView1

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


1
更新:但有了最新的工具集,现在(几乎)不再需要@synthesize。请参阅其他堆栈溢出问题的答案。
Ali Beadle13年

Answers:


228

在您的示例中,mapView1实例变量(ivar),这是一块内存存储,属于example.h和中定义的类的实例example.mmapView属性的名称。属性是可以使用点符号读取或设置的对象的属性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和属性之间有一个非常清晰的概念区分。它们实际上是两个截然不同的概念。


31

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

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

属性名称可以与变量名称相同。有时人们希望它与众不同,以便在使用相同变量名传递参数时init或中使用它dealloc


16

文档中

您可以使用@synthesize关键字来告诉编译器,如果未在@implementation块中提供它们,则应合成该属性的setter和/或getter方法。


8

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

即使有新的编译器版本有时确实有差别,如果你忽略@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.someIntsomeInt将不再处理相同的变量。如果您不期望像我这样的行为,这可能会让您有些头疼。


“ synchronize”!=“合成”?
jameshfisher

是的,这是两个不同的概念。@synchronize是用于在访问属性时如何同步线程的指令,用于@synthesize通过getter和setter将属性绑定到实例变量。
拉尔斯·布隆伯格

1
jameshfisher的评论旨在提醒您,您对答案的同步和综合感到困惑。您可以将两者互换使用。

1
感谢您让我意识到这一点!我完全监督了这一点,我已经更新了答案,以不使用不存在的@synchronize关键字。
拉尔斯·布隆伯格

在这种情况下,xcode 10将警告该问题:Autosynthesized property 'someInt' will use synthesized instance variable '_someInt', not existing instance variable 'someInt'。(我不知道这个警告是在哪个版本的xcode中添加的。)
zwcloud

7

根据Apple文档,@ Synthesize仅用于重命名实例变量。例如

@property NSString *str;

@synthesize str = str2; 

现在,在该类中您将无法使用,_str因为上述行将实例变量重命名为str2

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


3
显然,从Xcode 4.4开始,Clang为声明的属性的自动合成提供了支持。因此,@ synthesize在大多数情况下不再是必需的。见useyourloaf.com/blog/2012/08/01/...
huyz

5

在@interface中创建属性时,该属性将由名为_propertyName的实例变量自动返回。因此,当您创建一个名为firstName的属性时,在后台编译器将默认创建一个名为_firstName的实例变量。编译器还将为您创建getter和setter方法(即firstName,setFirstName)。

现在,当您通过@synthesize firstName合成属性时,您只是在告诉编译器通过firstName重命名我的实例变量(_firstName)。如果要使用其他名称重命名备份的实例变量,则可以在合成属性名称时(即@synthesize firstName = myFirstName)简单地分配其他名称,这样做可以通过名为myFirstname的实例变量来备份属性。

简而言之,大多数情况下@synthesize用来重命名由属性备份的实例变量。



2

它为您的对象创建吸气剂和吸气剂。您可以通过以下方式访问:

MKMapView* m = object.mapView;

要么

object.mapView = someMapViewObject

mapView1是该类中ivar的名称,mapView是getter / setter方法的名称。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.