我正在关注Joe Conway的Big Nerd Ranch iOS编程,当我看到以下代码时,我有点不解。
WebViewController.h
#import <Foundation/Foundation.h>
@interface WebViewController : UIViewController
@property (nonatomic, readonly) UIWebView *webView;
@end
WebViewController.m
#import "WebViewController.h"
@implementation WebViewController
- (void)loadView
{
// Create an instance of UIWebView as large as the screen
// Tell web view to scale web content to fit within bounds of webview
}
- (UIWebView *)webView
{
return (UIWebView *)[self view];
}
@end
不应该合成.h文件中声明的属性吗? Xcode也没有给出警告(当我声明一个带有合成的属性时它通常会这样做)。
顺便说一下,在书中,他也提到了
在WebViewController.h中,添加属性(但不是实例变量)
不声明属性会自动为您生成实例变量吗?让我知道我错过了什么。感谢。
答案 0 :(得分:5)
这是一个很好的问题,我认为答案有点微妙,往往不会立即开始使用Objective-C。首先,让我们消除关于财产的神话。神话是这样的:
Objective-C属性与实例变量相关。
这不一定是真的。 经常是真的,但在每种情况下都不是真的。这是真的:
Objective-C属性声明了一个getter和一个setter方法
(或者在readonly
属性的情况下,只是一个吸气剂)。尤其是当你宣布一个名为属性foo
(为便于讨论,我们假设它不是只读),你真的做的唯一的事情是,告诉你写的类有一个方法{编译{1}}以及名为-foo
的方法。通过在.m文件中添加-setFoo:
声明,您告诉编译器自己生成这些方法。在这里,您要说,“编译器,创建一个实例变量(也称为@synthesize foo;
),并为访问此实例变量的foo
和-foo
方法生成实现。特别是,返回值setFoo:
中此变量的值,并在-foo
中设置变量的值。
注意,没有必要让编译器为您合成方法。相反,您可以自己编写-setFoo:
和-foo
。此外,您无需以任何方式创建实例变量来支持这些方法的实现。你可以随意写下它们。
总结一下:-setFoo:
只告诉编译器getter和setter方法的存在。然后,您可以:@property
.m中的方法或自己编写方法。
答案 1 :(得分:3)
这是因为“webView
”getter方法是在.m文件中实现的,因此,“@synthesize
”不是必需的。
如果在代码中没有明确地创建“webView
”方法,那么编译器会抱怨该属性未被合成。在这种情况下,合成一个“只读”属性只会创建一个“getter”方法,它与你在代码中看到的大致相同。
是的,根据Apple docs on declared properties,它说的是“@synthesize
”:
使用@synthesize指令告诉编译器它应该合成属性的setter和/或getter方法 你没有在@implementation块中提供它们。的的 @synthesize指令还合成了一个合适的实例 变量,如果没有另外声明。