【问题标题】:What exactly does @synthesize do?@synthesize 到底是做什么的?
【发布时间】:2010-07-16 15:32:45
【问题描述】:

我看过下面这段代码:

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

//example.m
@synthesize mapView = mapView1

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

【问题讨论】:

标签: iphone objective-c


【解决方案1】:

在您的示例中,mapView1 是一个实例变量 (ivar),它是属于example.hexample.m 中定义的类的实例的一段内存存储。 mapView属性的名称。属性是可以使用点表示法读取或设置的对象的属性:myObject.mapView。属性必须基于 ivar,但大多数属性都是。 @propertydeclaration 只是告诉全世界有一个名为 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 和属性之间有一个非常清晰的概念区别。它们实际上是两个非常不同的概念。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

      来自the documentation

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

      【讨论】:

        【解决方案4】:

        由于我在编辑遗留代码时遇到了这个问题,所以我想对需要注意的现有答案做额外的注释。

        即使使用较新的编译器版本,如果省略 @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 是用于在访问属性时如何同步线程的指令,@synthesize 用于通过 getter 和 setter 将属性绑定到实例变量。
        • jameshfisher 的评论旨在提醒您,您在回答中混淆了同步和综合。您可以互换使用这两者。
        • 感谢您让我意识到这一点!我完全监督了这一点,我已经更新了不使用不存在的 @synchronize 关键字的答案。
        • 在这种情况下,xcode 10 将警告该问题:Autosynthesized property 'someInt' will use synthesized instance variable '_someInt', not existing instance variable 'someInt'。 (我不知道这个警告是在哪个版本的 xcode 中添加的。)
        【解决方案5】:

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

        @property NSString *str;
        
        @synthesize str = str2; 
        

        现在在类中你不能使用_str,因为上面的行已将实例变量重命名为str2

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

        【讨论】:

        • 显然,从 Xcode 4.4 开始,Clang 提供了对声明属性的自动合成的支持。所以大多数情况下不再需要@synthesize。见useyourloaf.com/blog/2012/08/01/…
        【解决方案6】:

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

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

        因此,简而言之,@synthesize 大部分时间用于重命名由您的属性支持的实例变量。

        【讨论】:

          【解决方案7】:

          the apple docs

          基本上synthesize 会创建setMapView 和mapView 方法来设置和获取mapView1

          【讨论】:

            【解决方案8】:

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

            MKMapView* m = object.mapView;
            

            object.mapView = someMapViewObject
            

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

            【讨论】:

              猜你喜欢
              • 2015-08-06
              • 2013-09-02
              • 2014-01-02
              • 2013-10-10
              • 2017-05-08
              • 2022-01-20
              • 2012-10-17
              • 2017-06-15
              • 2011-05-20
              相关资源
              最近更新 更多