0

我正在关注 Joe Conway 的 Big Nerd Ranch iOS Programming,当我看到以下代码时有点困惑。

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 中,添加一个属性(但不是实例变量)

声明属性不会自动为您生成实例变量吗?让我知道我错过了什么。谢谢。

4

2 回答 2

5

这是一个很好的问题,我认为这个问题的答案有点微妙,而且对于刚开始使用 Objective-C 的人来说往往不是直接的。首先,让我们消除关于属性的神话。神话是这样的:

Objective-C 属性与实例变量有关

这不一定是真的。这通常是正确的,但并非在所有情况下都是正确的。这是真的:

Objective-C 属性声明了一个 getter 和一个 setter 方法

(或者在readonly属性的情况下,只是一个吸气剂)。特别是当您声明一个名为的属性时foo(为了讨论,我们假设它不是只读的),您真正要做的唯一一件事就是告诉编译器您正在编写的类有一个名为的方法-foo和一个名为的方法-setFoo:。通过在 .m 文件中添加@synthesize foo;声明,您是在告诉编译器自己生成这些方法。在这里你说,“编译器,创建一个实例变量(也称为)并为我的和访问这个实例变量的方法foo生成实现。特别是,返回这个变量的值并设置变量的值。-foosetFoo:-foo-setFoo:

请注意,没有必要让编译器为您合成方法。相反,你可以写-foo-setFoo:你自己。此外,您无需创建实例变量来支持这些方法的实现。您可以随心所欲地编写它们。

总结一下:@property唯一告诉编译器getter和setter方法的存在。然后,您可以:@synthesize您的 .m 中的方法或自己编写方法。

于 2012-06-12T04:15:28.430 回答
3

这是因为“ webView”getter 方法是在 .m 文件中实现的,因此,“ @synthesize”不是必需的。

如果webView没有在代码中明确创建“”方法,那么编译器会抱怨该属性没有被合成。在这种情况下,合成一个“只读”属性只会创建一个“getter”方法,它的作用与您在上面的代码中看到的大致相同。

是的,根据声明属性的 Apple 文档,它说的是“ @synthesize”:

您使用@synthesize 指令告诉编译器如果您不在@implementation 块中提供它们,它应该为属性合成setter 和/或getter 方法。如果没有另外声明,@synthesize 指令还会合成适当的实例变量。

于 2012-06-12T04:07:32.777 回答