我正在观看演示,我意识到我不了解目标c中编程风格的几个基本内容。该演示恰好是斯坦福大学CS193P的第14讲。请参阅下面的代码,看看让我感到困惑的是什么。我认为,与制定者有关。
@synthesize photoDatabase = _photoDatabase;
- (void)setPhotoDatabase:(UIManagedDocument *)photoDatabase
{
if (_photoDatabase != photoDatabase)
_photoDatabase = photoDatabase;
}
此代码是从this lecture/Demo的YouTube视频中的25:00开始的。这里称为photoDatabase的合成属性恰好是UIManagedDocument类型。
我的第一个问题是,我们为什么要在@synthesize myProperty = _myProperty中使用下划线。我对它有点困惑,对于一般的编程是新的。从XCode 4开始,我们不能合成部分以在引用此属性时消除对下划线的需要吗?
我的第二个问题是setPhotoDatabase:方法的目的是什么。我假设讲师超越了这种方法。究竟是为了什么目的?
答案 0 :(得分:5)
我将解决您的第一个问题...当您使用合成属性时,您只是自动创建实例变量的setter和getter。说你有:
@property (nonatomic, strong) NSString *title;
综合:
@synthesize title;
创建以下方法:
- (NSString) title;
- (void) setTitle:(NSString *)value;
现在,在您的班级中,您想要访问title属性,您可以使用title
或self.title
来执行此操作。即使这两者看起来都是一回事,但事实并非如此。 title
访问实例变量本身,而self.title
正在访问“合成”方法- (NSString) title;
如果我们有某种方式更容易区分两者,难道不会让事情变得更简单吗?那就是@synthesize title = _title;
的确切位置。它创建标准的setter和getter,但是将实例变量设置为_title
而不是title
。
@synthesize <variable> = _<variable>
,因此您无需亲自执行此操作。
答案 1 :(得分:2)
下划线是生成实际ivar的默认方式。 它可以让你成为一种元。 在类的内部,您可以像这样直接引用它们,避免对getter或setter进行不必要的方法调用。 它还使范围保持清晰,并允许您使用与属性相同的名称以及其他方法声明中参数的变量名称的getter。这使得它隐含了该方法的参数旨在与该属性相关。 下划线使局部变量不会与方法中的ivar发生冲突。
您可以通过手动将其归类为非常不同的东西,故意将子类名称与子类创建者混淆。 使用它是为了保护ivar免受子类创建者的影响,以防你的SPI无法使用。
这样的setter方法的目的是符合约定和键值编码。其他类使用它来设置ivar。
当您需要提供超出合成的功能时,您可以手动实现自己的setter。 这可能包括数据验证或触发通知或其他事情。
答案 2 :(得分:1)
下划线只是将变量标记为实例变量而非方法变量的一种方法。使用公共成员是一种不好的做法,因此使用setter和getter是正常的。 @synthesize
会自动生成getter和setter,具体取决于@property
关键字后的关键字。它可以生成retain
(使用arc时为strong
),assign
(使用arc时为weak
)等等setter和getter。
此外,您可以覆盖任何这些自动生成的方法来添加一些逻辑。例如,您可能希望每次更改此值时都将消息打印到控制台,或者在更改属性后更新视图。