仅初始化一次类

时间:2009-08-14 00:24:43

标签: iphone objective-c cocoa macos

我有一个包含一些需要从另一个类调用的实例方法的类。我知道怎么做 -

TimeFormatter *myTimeFormatter = [[TimeFormatter alloc] init];
[myTimeFormatter formatTime:time];

但是,每次我需要调用其中一个方法时,我不想分配和初始化TimeFormatter。 (我需要从另一个类中的各种方法调用TimeFormatter的方法。)

我尝试了

TimeFormatter *myTimeFormatter = [[TimeFormatter alloc] init];

“本身”,或者不在任何块中,但是当我编译时,我得到“初始化元素不是常量”错误。

非常感谢任何输入!

6 个答案:

答案 0 :(得分:7)

您可以使用单例模式。您可以阅读更多相关信息here

具体来说,你会做类似的事情:

static TimeFormatter* gSharedTimeFormatter = nil;

@implementation TimeFormatter

+ (TimeFormatter*)sharedTimeFormatter {
  if (!gSharedTimeFormatter) {
    @synchronized(self) {
        if (!gSharedTimeFormatter) {
            gSharedTimeFormatter = [[TimeFormatter alloc] init];
        }
    }
  }
  return gSharedTimeFormatter;
}

...

@end

请注意,我们检查变量是否为null,如果是,我们会锁定,然后再次检查。这样,我们只在分配路径上产生锁定成本,这在程序中只发生一次。此模式称为double-checked locking

答案 1 :(得分:3)

  

但是,每次我需要调用其中一个方法时,我不想分配和初始化TimeFormatter。 (我需要从另一个类中的各种方法调用TimeFormatter的方法。)

我认为值得澄清一些OOP术语。

您需要allocinit TimeFormatter的原因是因为您的方法是实例方法。因为它们是实例方法,所以您需要一个实例,这就是allocinit提供的内容。然后调用您的方法(发送消息)实例([myTimeFormatter formatTimeString:…])。

允许实例的优点是您可以在实例变量中保留每个实例中的状态和设置,并使后者成为公开可见的属性。然后你可以故意拥有多个实例,每个实例都有自己的设置,无论使用哪个实例都可以配置。

如果您不需要该功能,则无需制作这些实例方法。您可以使它们成为类方法甚至是C函数,然后您就不需要TimeFormatter实例。使用类方法,您可以将消息直接发送到类([TimeFormatter formatTimeString:…])。

如果您确实希望在所有实例之间共享设置(并且您没有任何状态可以保留),那么您就可以拥有一个实例 - 一个单例。

该括号的原因是共享状态不好,特别是如果两个线程可以同时使用时间格式化器。 (就此而言,你也可以说关于设置。如果一个线程想要秒而另一个不想怎么办?如果一个人想要24小时而另一个想要12小时怎么办?)最好让每个线程使用它自己的时间格式器,这样他们就不会被对方的状态绊倒。

(顺便说一句,如果TimeFormatter是你班级的实际名称:你知道NSDateFormatter,对吗?它只允许你格式化/解析时间。)

答案 2 :(得分:2)

这是sharedMethod的详细示例。积分为here

@implementation SearchData

@synthesize searchDict;
@synthesize searchArray;

- (id)init {
    if (self = [super init]) {
        NSString *path = [[NSBundle mainBundle] bundlePath];
        NSString *finalPath = [path stringByAppendingPathComponent:@"searches.plist"];
        searchDict = [[NSDictionary alloc] initWithContentsOfFile:finalPath];
        searchArray = [[searchDict allKeys] retain];
    }

    return self;
}

- (void)dealloc {
    [searchDict release];
    [searchArray release];
    [super dealloc];
}

static SearchData *sharedSingleton = NULL;

+ (SearchData *)sharedSearchData {
    @synchronized(self) {
        if (sharedSingleton == NULL)
                sharedSingleton = [[self alloc] init];
    }   
    return(sharedSingleton);
}

@end

答案 3 :(得分:2)

设置Singleton的一种非常好用且简单的方法是使用Matt Gallager的SYNTHESIZE_SINGLETON_FOR_CLASS

答案 4 :(得分:0)

听起来你想让TimeFormatter成为一个单例,其中只能创建一个实例。 Objective-C并不会让这变得非常容易,但基本上你可以暴露一个返回指向TimeFormatter的指针的静态方法。该指针将在第一次分配和初始化,并且每次在使用相同的指针之后。 This question有一些在Objective-C中创建单例的例子。

答案 5 :(得分:0)

你试图在课外声明你的变量?如果按照你想要的方式去做,你必须将它声明为静态,所以

静态TimeFormatter * myFormatter = ...

从类的名称虽然我不明白你为什么要保留你班级的一个实例...你也可以用一个单例来完成这个,如上所述,也就是你想保留你的一个实例整个应用程序的类。