4

我偶然发现了 Objective-C 中的一些奇怪行为。我有一个 main.m:

#include <Foundation/Foundation.h>
#include "AClass.h"

int main(int argc, char* argv[]) {
  AClass* tmpClass = [[AClass alloc] init];
  [tmpClass setAVariable:12];
  return -1;
}

头文件 AClass.h:

#include <Foundation/Foundation.h>

@interface AClass: NSObject; 

-(void) setAVariable:(int) bVariable;

@property int aVariable;

@end

以及对应的实现文件AClass.m:

#include <Foundation/Foundation.h>
#include <AClass.h>

@implementation AClass
@dynamic aVariable;
int aVariable;

-(void) setAVariable:(int)bVariable {
  NSLog(@"foo:");
  self.aVariable = bVariable;  
}

@end

在 Linux 上使用 clang 或通过 OSX 上的 Xcode 编译此代码时,setAVariable:会触发无限递归。我想知道这是否是 clang/Objective-C 中的错误。

4

1 回答 1

7

这是意料之中的。您正在您的 setter 中访问您的 setter。

self.aVariable = bVariable实际上是在调用[self setAVariable:bVariable],因此是递归。点语法就是这样,一种特殊的语法,实际上只是实际 setter 方法的简写。当您编写自己的 setter 方法时,您应该访问支持的实例变量,而不是属性本身。例如

- (void) setAVariable:(int)bVariable {
  NSLog(@"foo:");
  aVariable = bVariable;  
}

通常的做法是为您的实例变量使用前导下划线,因此当您直接访问实例变量而不是属性(通过 getter 和 setter 访问支持实例变量)时,很容易识别。

此外,最好使用#import 而不是#include,因为即使同一个文件有多个#import 语句,#import 也只包含一次文件,这可能会加快编译时间。

于 2013-04-17T19:29:05.643 回答