@property和@synthesize有什么作用?

5

我一直没能搞清楚,也没有网站能够清晰地解释...那么 @property@synthesize 到底有什么作用呢?

谢谢。

4个回答

13

Objective-C Runtime编程指南:Declared Properties

@property声明了你想要实现的公共属性的getter和setter方法。例如,这个属性声明:

@property float value;

等同于:

- (float)value;
- (void)setValue:(float)newValue;

@synthesize为这两个访问器提供了默认实现。

更新:上述内容解释了这两个访问器的工作,但并没有解释它们的目的。 :-)

  • @property将一个成员添加到公共接口中,充当类客户端的数据变量,但使用方法进行读写。这使您可以更好地控制在客户端和代码之间交换的数据,例如,您可以对您的代码所接收的值执行扩展验证。
  • @synthesize允许您不显式编写将由客户端调用的代码,并且实际上将属性视为自己的数据变量。

@seanny94 请看这个问题:https://dev59.com/oHI_5IYBdhLWcg3wAeHl - Tobias Cohen
@Franci。属性不像数据成员那样行为。你不能从类外使用->操作符访问属性,也不能在类内省略self./self->。此外,使用@property声明的属性和手动编写访问器声明的属性之间没有功能上的区别。 - JeremyP
当然,如果你想要严谨一些的话,属性和数据成员之间确实存在某些语法上的差异。毕竟它们是两种不同的语言构造(而Objective-C设计得比较糟糕也没有什么帮助:-))。但是,对于客户端代码来说,一个属性的语义与一个数据成员是相同的 - 它是一个值的表示,而不是一个动作的表示。 - Franci Penov
1
链接已失效(评论必须超过15个字符) - Rog
更新了更加最新的链接。(希望苹果有一天能够理解固定链接的概念。) - Franci Penov
显示剩余3条评论

3
我希望这能对您有所帮助。
@property和@synthesize用于访问另一个类中的对象或变量。
下面是一个小例子: 这是第一个类
#import <UIKit/UIKit.h>
#import "ClassB.h"
@interface ViewController : UIViewController
@property(nonatomic, retain) NSString *FirstName;
@property(nonatomic, retain) NSString *LastName;


#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize FirstName, LastName;

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.FirstName = @"Ashvin";
    self.LastName  = @"Ajadiya";
    ClassB *ClassBOb = [[ClassB alloc] init];
    ClassBOb.ViewCntrlrOb = self;
    [ClassBOb CallMe];
}
@end

这是另一个类:

#import <UIKit/UIKit.h>
@class ViewController;
@interface ClassB : UIViewController
@property(nonatomic, retain) ViewController *ViewCntrlrOb;
-(void) CallMe;
@end

#import "ClassB.h"
#import "ViewController.h"
@interface ClassB ()
@end
@implementation ClassB
@synthesize ViewCntrlrOb;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

-(void) CallMe
{
   NSLog(@"FirstName = %@",ViewCntrlrOb.FirstName);
   NSLog(@"LastName = %@",ViewCntrlrOb.LastName); 
}

所以您可以将FirstName和LastName访问到ClassB中。

他们的输出如下:

2012-05-25 14:38:10.766 MyExample[8751:c07] FirstName = Ashvin 2012-05-25 14:38:10.768 MyExample[8751:c07] LastName = Ajadiya


3
"@"符号被编译器解释为指令。这是Objective-C对C语言的“附加”。当您声明@property,然后使用@synthesize指令时,您正在指示编译器为您创建getter和setter的指令和相应符号。请记住,在C语言中,“=”运算符表示“赋值”。在Objective-C扩展提供的OO上下文中,我们大多数时间都在使用指向isa数据结构(Objective-C中的类)的指针(也称为引用)。
在Objective-C 2.0之前,开发人员必须为每个属性编写所有getter和setter方法,而这在大多数情况下都是复制/粘贴代码。要完全符合KVC / KVO需要很多非常繁琐的代码...willAccessValueForKey,didUpdateValueForKey等,新编译器在使用@property / @synthesize语法时会自动添加这些代码。这对开发人员来说是巨大的生产力提升。语言中的点语法添加在社区中有点争议,因为它隐藏了编译器在解释object.property = anotherObject.property;语句时为您执行的“魔术”,将其解释为[object setProperty:[anotherObject property]];。
来自其他答案中引用的苹果文档:
属性声明属性
您可以通过使用@ property(attribute [,attribute2,...])形式对属性进行装饰。与方法一样,属性作用域限定为其封闭接口声明。对于使用逗号分隔的变量名称列表的属性声明,属性属性适用于所有命名属性。
如果使用@synthesize指令告诉编译器创建访问器方法,则生成的代码与关键字给出的规范匹配。如果您自己实现访问器方法,请确保它符合规范(例如,如果指定复制,则必须确保在setter方法中复制输入值)。"

0

这里有一个快速示例说明,为什么你可能不想只使用 "variable = 0":

假设你有以下属性:

@property (nonatomic, retain) id <MyDelegate> theDelegate;

无论何时您用新的委托替换它,您的合成setter和getter将在每次设置时为您处理释放/保留:
self.theDelegate = newObject;

实际上发生的是这样的:

[self setTheDelegate:newObject];

- (void)setTheDelegate:(id <MyDelegate>)anObject {
    [theDelegate release];
    theDelegate = [anObject retain];
}

(当然,这是简化的)

你可以在自己的setter和getter中做非常强大的事情,synthesize用于那些反复发生的保留属性等。编译时会查看你的@property并相应地构建方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接