目标C中的单例属性访问

时间:2012-09-27 23:48:09

标签: objective-c properties singleton

我正在使用标准的现代单例类,其中包含一个包含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); 

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

2 个答案:

答案 0 :(得分:3)

自Xcode 4.4起,当您声明@property时,编译器将自动为您创建一个ivar,并为@synthesize创建访问器方法。默认的ivar是带有下划线的ivar。

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

您应该使用.表示法而不是->来访问该媒体资源。或者只使用自动生成的名为_paintingFont的ivar。

您还可以通过添加以下代码在您的实现文件中创建属性readwrite。这将允许您在实现中使用点语法来设置属性,但仍然只为其他类保留它。

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

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

@implementation MySingleton
@synthesize paintingFont;
....
@end

答案 1 :(得分:2)

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

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

完成
  1. 解决方案中的实例sharedInstance->_paintingFont = ...
  2. 使用属性和。符号sharedInstance.paintingFont = ...。这将调用生成的方法setPaintingFont,然后将其分配给实例变量。
  3. 但是在这种情况下,属性是只读的,所以不能使用方法2.