2

我正在使用一个标准的现代单例类,其中一个单例持有 CTFontRef,如下所示:

@interface MySingleton : NSObject {
    CTFontRef paintingFont;
}

@property (readonly) CTFontRef paintingFont;

@end


@implementation MySingleton

+ (MySingleton*)sharedInstance
{
    static dispatch_once_t once;
    static MySingleton *sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];

        //NB
        sharedInstance->paintingFont = 
           CTFontCreateWithName(CFSTR("Helvetica"), 80.0, nil);   
    });
   return sharedInstance;
}

@end

然后我在其他地方打电话[[MySingleton sharedinstance] paintingFont]

但是,这个调用会返回nil,直到我paintingFont像这样插入下划线:

        sharedInstance->_paintingFont = 
           CTFontCreateWithName(CFSTR("Helvetica"), 80.0, nil); 

为什么是这样?编译器不应该要求我包含下划线吗?如果不是,早期版本的目的是什么?这个下划线是从哪里来的?我从来没有用下划线声明属性,我只是在调试器窗口中看到这些看似随机的插入到变量名中。

4

2 回答 2

3

从 Xcode 4.4 开始,当您声明 a 时,编译器会自动为您和访问器方法@property创建一个 ivar 。@synthesize默认的 ivar 是带下划线的。

使用->您直接访问 ivars 而不是属性的语法。因此,在您的sharedInstance方法中,您可以设置自己的 ivar(不带下划线)。但是,当您稍后尝试访问它时,您使用[ ]which 将使用自动合成的 getter 方法来访问您的属性(以及带有下划线的自动生成的 ivar)。

您应该使用.符号而不是->来访问该属性。或者干脆使用自动生成的名为_paintingFont.

您还可以通过添加以下代码在您的实现文件中进行属性读写。这将允许您在实现中使用点语法来设置属性,但对于其他类仍然是只读的。

@interface MySingleton ()
@property (readwrite) CTFontRef paintingFont;
@end

如果你想要一个不同的 ivar,你可以使用@synthesize它来覆盖它。在这两种情况下,您都不必再声明 ivar。

@implementation MySingleton
@synthesize paintingFont;
....
@end
于 2012-09-27T23:52:31.627 回答
2

这是因为在声明一个属性paintingFont 时,Obj C 编译器会创建一个实例变量_paintingFont。

通常,属性/变量的设置可以通过

  1. 您的解决方案中的实例sharedInstance->_paintingFont = ...
  2. 使用属性和 。符号sharedInstance.paintingFont = ...。这会调用生成的方法 setPaintingFont,然后将其分配给实例变量。

但是在这种情况下,该属性是只读的,因此不能使用方法 2。

于 2012-09-27T23:53:38.020 回答