【问题标题】:What is the best way to declare a property?申报财产的最佳方式是什么?
【发布时间】:2010-12-30 03:45:48
【问题描述】:

我们使用 @property 关键字声明属性并在实现文件中综合它。我的问题是,

如果我使用@property 关键字声明一个属性,并在接口块中声明一个同名变量怎么办?例如,考虑以下代码,

界面:

@interface myClass : NSObject {

    NSString *myClass_name;  // LINE 1
}

@property(nonatomic, retain) NSString *myClass_name;  // LINE 2

@end

实施:

@implementation myClass

@synthesize myClass_name  // LINE 3

@end

在 LINE 1 中声明 myClass_name 会有什么问题吗?像任何参考问题或任何不必要的内存消耗问题?

【问题讨论】:

    标签: iphone objective-c ios


    【解决方案1】:

    不,事实上,声明这样的属性是需要的。您可以将您的声明替换为:

    @interface MyClass : NSObject {
        NSString *ivar;
    }
    
    @property (nonatomic, retain) NSString *myClass_name;
    
    @end
    

    然后将您的实现更改为

    @implementation MyClass
    
    @synthesize myClass_name = ivar;
    
    @end
    

    (如果不指定 = some_ivar,则假定 ivar 与属性同名。)

    你总是需要有以下几行:

    • 财产声明(第 2 行)
    • 属性综合(第 3 行)

    在合成属性时,如果不指定使用哪个ivar(最后使用=ivar),则会假定存在与该属性同名的ivar。

    【讨论】:

    • 在这种情况下,我不需要 LINE 2?
    • @Justin Spahr-Summers:我是否需要 LINE 2?我真的不知道。请告诉我。
    • 我不明白你的问题,根据我的说法,你声明正确只是在 dealloc 部分释放它
    • @Matt:谢谢伙计.. 你的@synthesize myClass_name = ivar 概念对我真的很有帮助.. 我以前不知道。谢谢分享..
    • 也许您已经有了答案,但要明确您的问题:您不需要 LINE 1。
    【解决方案2】:

    声明属性并合成它不会在您的情况下产生任何参考问题。 这样做将为您的类中的实例变量创建访问器和设置器方法。 如果属性中的变量名和类中声明的变量名,那么 xcode 会将两者都称为单个变量。

    第 3 行和第 4 行是必须的。第 1 行是可选的

    【讨论】:

    • 第 4 行是指哪一行?
    • 对不起,我的错误,我的意思是第 2 行和第 3 行是必须的。我也尝试省略第 1 行并运行代码。在您的情况下,如果省略第 1 行,是否会导致任何错误?
    • 您能否在答案中将“第 3 行和第 4 行”更改为“第 2 行和第 3 行”。
    【解决方案3】:

    我从 Apple 的文档中为 Declared Properties 获得了以下内容。我将其发布在这里,以便将来可能对某人有所帮助。

    运行时差异

    一般来说,属性的行为在所有运行时都是相同的(参见Objective-C Runtime Programming Guide 中的Runtime Versions and Platforms)。有一个关键区别:现代运行时支持实例变量合成,而传统运行时不支持。

    要使@synthesize 在旧版运行时中工作,您必须提供具有相同名称和兼容类型的属性的实例变量,或者在@synthesize 语句中指定另一个现有实例变量。对于现代运行时,如果您不提供实例变量,编译器会为您添加一个。例如,给定以下类声明和实现:

    @interface MyClass : NSObject {
    
        float sameName;
        float otherName;
    }
    
    @property float sameName;
    @property float differentName;
    @property float noDeclaredIvar;
    
    @end
    
    
    @implementation MyClass
    
    @synthesize sameName;
    @synthesize differentName=otherName;
    @synthesize noDeclaredIvar;
    
    @end
    

    旧版运行时的编译器会在 @synthesize noDeclaredIvar; 处生成错误,而现代运行时的编译器会添加一个实例变量来表示 noDeclaredIvar

    【讨论】:

      【解决方案4】:

      以下是面向对象的方式:

      声明属性.h

      @interface DeclaringProperties : NSObject
      // ivars and {} can be omitted
      
      @property (nonatomic, readwrite, retain) NSString *normal;
      @property (nonatomic, readwrite, retain) NSString *alias;
      @property (nonatomic, readonly, retain) NSString *readonly;
      
      - (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias;
      
      @end
      

      DeclaringProperties.m

      #import "DeclaringProperties.h"
      
      // private interface
      @interface DeclaringProperties ()
      
      @property (nonatomic, readwrite, retain) NSString *readonly; // readwrite for self
      @property (nonatomic, readwrite, retain) NSString *private;
      @property (nonatomic, readwrite, retain) NSString *retain;
      
      @end
      
      #pragma mark -
      
      @implementation DeclaringProperties
      
      @synthesize normal, alias = _alias, readonly, private, retain;
      
      // You can not use "normal" here;
      // But you can still use "alias", and it is highlighted in XCode!
      - (id) initWithNormal:(NSString *)aNormal alias:(NSString *)alias {
          self = [super init];
          if (self) {
              self.normal = aNormal;
              self.alias = alias;
              self.readonly = @"readonly";
              self.private = @"private";
      
              // allocated(copied) variable for retained(copied) property should be released or autoreleased
              NSString *alloc = [[NSString alloc] init];
              self.retain = alloc;
              [alloc release];
              // or
              self.retain = [[NSString alloc] init];
              [self.retain release];
              // or
              self.retain = [[[NSString alloc] init] autorelease];
              // I don't like ;)
              retain = [[NSString alloc] init];
          }
          return self;
      }
      
      - (void) dealloc {
          self.normal = nil;
          self.alias = nil;
          self.readonly = nil;
          self.private = nil;
          self.retain = nil;
          [super dealloc];
      }
      
      @end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-08
        • 2018-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多