【问题标题】:Difference between @interface declaration and @property declaration@interface 声明和@property 声明的区别
【发布时间】:2011-01-10 17:03:25
【问题描述】:

我是 C 的新手,也是目标 C 的新手。对于 iPhone 子类,我在 @interface 类定义中声明变量我希望对类中的所有方法可见

@interface myclass : UIImageView {
    int aVar;
}

然后我再次声明为

@property int aVar;

后来我

@synthesize aVar;

你能帮我理解三个步骤的目的吗?我是在做一些不必要的事情吗?

谢谢。

【问题讨论】:

  • 第一个是使Objective-C与C兼容。第二个是声明属性。第三个是您可以将属性的定义与特定的翻译单元相关联。欢迎来到 C.

标签: objective-c iphone properties


【解决方案1】:

在这里,您声明了一个名为 aVar 的实例变量:

@interface myclass : UIImageView {
    int aVar;
}

你现在可以在你的类中使用这个变量了:

aVar = 42;
NSLog(@"The Answer is %i.", aVar);

然而,实例变量在 Objective-C 中是私有的。如果您需要其他类能够访问和/或更改aVar,该怎么办?由于方法在 Objective-C 中是公共的,因此答案是编写一个返回 aVar 的访问器(getter)方法和一个设置 aVar 的修改器(setter)方法:

// In header (.h) file

- (int)aVar;
- (void)setAVar:(int)newAVar;

// In implementation (.m) file

- (int)aVar {
    return aVar;
}

- (void)setAVar:(int)newAVar {
    if (aVar != newAVar) {
        aVar = newAVar;
    }
}

现在其他类可以通过以下方式获取和设置aVar

[myclass aVar];
[myclass setAVar:24];

编写这些访问器和修改器方法会变得相当乏味,因此在 Objective-C 2.0 中,Apple 为我们简化了它。我们现在可以写:

// In header (.h) file

@property (nonatomic, assign) int aVar;

// In implementation (.m) file

@synthesize aVar;

...访问器/修改器方法将自动为我们生成。

总结一下:

  • int aVar; 声明一个实例变量aVar

  • @property (nonatomic, assign) int aVar; 声明aVar 的访问器和修改器方法

  • @synthesize aVar; 实现了aVar 的访问器和修改器方法

【讨论】:

  • 很好的解释(虽然Rob和chpwn也很清楚),谢谢大家。
  • @Nigel:很高兴能提供帮助! :)
  • 请注意,对于 iPhone OS 和 64 位 Mac OS X,环境变量声明是可选的。
  • 美丽解说+1! @史蒂夫哈里森
  • 今天不再需要@synthesize。
【解决方案2】:

这会在你的对象中声明一个实例变量:

@interface myclass : UIImageView {
    int aVar;
}

实例变量是类的私有实现细节。

如果希望其他对象能够读取或设置实例变量(ivar)的值,可以将其声明为属性:

@property int aVar;

这意味着编译器希望看到属性的 setter 和 getter 访问器方法。

当您使用 @synthesize 关键字时,您要求编译器自动为您生成 setter 和 getter 访问器方法。

所以,在这种情况下,编译器在遇到@synthesize 关键字时会生成类似这样的代码:

- (int) aVar
{
    return aVar;
}

- (void)setAVar:(int)someInt
{
    aVar = someInt;
}

默认情况下,在 iPhone 上(以及在 Mac 上的 32 位运行时),@synthesize 需要一个实例变量才能存储属性的值。此 ivar 通常与属性命名相同,但不一定非要如此,例如您可以这样做:

@interface myclass : UIImageView {
    int aVar;
}

@property int someValue;

@synthesize someValue = aVar;

@synthesize@property 实际上都不是必需的,您可以创建自己的 getter 和 setter 方法,只要您使用符合 Key-Value Coding 的语法创建它们,该属性仍然可以使用。

要求存在 ivar 以及 @property 声明是由于 Mac 和 iPhone 上 32 位 Objective-C 运行时的 fragile base class 限制。使用 Mac 上的 64 位运行时,您不需要 ivar,@synthesize 会为您生成一个。

请注意,您可以在 @property 声明中使用许多关键字来控制创建哪种合成访问器代码,例如 readonly 用于仅 getter 访问器、copyatomic、@ 987654336@等。更多信息在Objective-C 2.0 Programming Language 文档中。

【讨论】:

  • 谢谢 - 为什么我需要 setter 和 getter 方法(假设它们是由综合创建的通用方法)?是否需要它们才能使属性对外部类可见?
  • @Nigel:是的——如果你没有 setter 和 getter 方法,其他类将无法访问或更改实例变量(实例变量是私有的)。
  • 很好的解释+1。 @Rob Keniger
【解决方案3】:

类可以有实例变量(ivars)。这些在第一部分中,并且仅对该类中的代码可见,而不是任何外部代码。我喜欢在它们前面加上下划线以显示它们的内在性。在低级术语中,ivars 是作为附加成员添加到您正在创建的类在内部使用的结构中的。

第二个声明,@property,是一个声明的属性。它不是必需的(除非您使用@synthesize),但它可以帮助其他程序员(和编译器!)知道您正在处理一个属性,而不仅仅是-setAVar-aVar 这两个方法,这是这样做的替代方法。

第三,@synthesize 实际上创建了从类外部设置和访问属性的方法。您可以将其替换为您自己的 setter 和 getter 方法,但仅在需要时才这样做,因为内置方法具有一些您必须自己编写代码的功能。事实上,使用@synthesize aVar = _someVariable; 语法,您可以让您的属性实际引用一个不同命名的实例变量!

短版: @property 只是向编译器和其他程序员提示您正在创建属性,而不仅仅是 getter/setter 方法。实例变量是类的内部变量,否则无法从其外部正常访问。 @synthesize 只是为您创建简单的 getter 和 setter,以配合您的 @property,但您也可以像任何其他方法一样自己编写这些 getter 和 setter。

【讨论】:

  • 谢谢 - 是否建议在拥有它们的类中使用合成方法?例如,我应该使用 [self setaVar:123];而不是 aVar=123?
  • @Nigel:我认为通常最好在类中使用访问器和修改器。您可能会发现我的问题stackoverflow.com/questions/1551966/… 很有帮助。
【解决方案4】:
Class A      

      @interface myclass : UIImageView {
    int aVar;
}

If you declare like this then you can only use this variable within your class A.


But suppose in Class B

    A *object=[A new];
object.aVar---->not available



For this you should **declare aVar as a property in Class A**

so class A should look like 

Class A      

  @interface myclass : UIImageView {
    int aVar;
}
@property int iVar;


and 


.m file 
@synthesize iVar;



So now you can use this iVar in another class Suppose B


 Class B
#import "Class A.h"

    enter code here

A *object=[A new];
object.aVar---->available
means
object.aVar=10;

【讨论】:

    【解决方案5】:

    @interface 在 obj-c 中声明一个类的实例变量。您需要它来创建实例变量。但是默认情况下,该变量在类外部不可见(因为该字段默认受保护)。

    @property 告诉编译器指定一个特定的属性访问器(get/set)方法。但是,您需要使用 @synthesize 让编译器自动生成简单的访问器,否则您需要自己创建它们。

    【讨论】:

      【解决方案6】:

      我最近开始学习 iphone 应用程序。据我所知,@property 在 .h 文件中用作 setter 方法,@synthesize 在 .m 文件中用作 getter 方法。在Java中我们使用setter和getter方法,和Java一样,在Objective C中我们使用@property和@synthesize。

      如果你认为我误导了你,请原谅我。

      【讨论】:

      • 不完全。 @property 声明可以使用点表示法获取和/或设置的属性。 @synthesize 实际上在实现中创建底层方法,并让您有机会指定支持公共方法名称的 ivar 的名称。在 Xcode/LLDB 的现代版本中,不需要 @synthesize 关键字,因为它是由编译器自动创建的。 (@ 和属性/synthesize 之间的空格 StackOverflow 认为我正在尝试通知人们!)
      猜你喜欢
      • 1970-01-01
      • 2012-03-10
      • 2017-10-02
      • 2013-05-15
      • 1970-01-01
      • 2014-06-26
      • 1970-01-01
      • 2017-11-10
      • 2015-10-20
      相关资源
      最近更新 更多