简体   繁体   English

我应该在iOS / OS X应用程序的哪个位置初始化我的单例?

[英]Where should I initialize my singleton in iOS/OS X app?

I want to initialize my singleton object which stores and manages the application settings over the entire class within my app. 我想初始化我的单例对象,该对象存储和管理应用程序中整个类的应用程序设置。 Also, the singleton instance should be initialized by loading the data from NSUserDefaults upon launch. 另外,应该通过在启动时从NSUserDefaults加载数据来初始化单例实例。 However, I'm not fully sure where I should initialize the singleton upon launch. 但是,我不确定在启动时应在哪里初始化单例。

In Cocoa app, I first wrote the singleton initialization code within applicationWillFinishLaunching: , taking parameters from NSUserDefaults . 在Cocoa应用程序中,我首先在applicationWillFinishLaunching:编写了单例初始化代码,并从NSUserDefaults获取参数。 However, later I found that this doesn't work properly if I also write the singleton initialization code (taking no parameter!) within my initial view controller, set in storyboard, because the viewWillLoad: , viewDidLoad: etc. of the class of the view controller are called before the applicationWillFinishLaunching: . 但是,后来我发现,如果我还在情节viewWillLoad:设置的初始视图控制器中编写单例初始化代码(不带参数!),此操作将无法正常工作,因为该类的viewWillLoad:viewDidLoad:等。在applicationWillFinishLaunching: 之前调用视图控制器。

So now I'm sure I should write the singleton initalization code within viewWillLoad: earlier than applicationWillFinishLaunching , but still not sure whether it is appropriate. 所以现在我确定我应该在applicationWillFinishLaunching 之前viewWillLoad:编写单例初始化代码,但仍不确定是否合适。 Specifically, I know the NSApplicationMain is the first method to be called upon launch, but it seems that the next method is not anything within AppDelegate , at least if you use storyboard. 具体来说,我知道NSApplicationMain是启动时要调用的第一个方法,但似乎下一个方法在AppDelegate不是任何东西,至少如果使用情节AppDelegate话。

To summary, what I want to ask are the following: 总而言之,我想问的是以下几点:

  • What method from what class will be called after NSApplicationMain , if you use storyboard. 如果使用情节NSApplicationMain ,将在NSApplicationMain之后从哪个类中调用什么方法。

  • Where should I write my singleton initialization code within my app? 我应该在应用程序中的哪儿编写单例初始化代码? I want to initialize it as soon as possible. 我想尽快初始化它。

  • Does it differ between iOS and OS X app? iOS和OS X应用之间有区别吗?

You should initialize it when it's first accessed. 您应该在首次访问它时对其进行初始化。 Something like this, maybe: 可能是这样的:

+ (instancetype)sharedInstance {
  static dispatch_once_t onceToken;
  dispatch_once(&onceToken, ^{
    _instance = [[self alloc] init];
  });
  return _instance;
}

As a side note, if you're literally only using this class as an accessor to NSUserDefaults , you might want to consider using static methods instead. 附带说明一下,如果您实际上只是使用此类作为NSUserDefaults的访问NSUserDefaults ,则可能要考虑使用静态方法。

+ (id)mySpecificDataPoint {
  return [[NSUserDefaults standardUserDefaults] objectForKey:@"whatever"];
}
+ (void)setMySpecificDataPoint:(id)data {
  [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"whatever"];
}

Or maybe a more well-designed way might be to add a category to NSUserDefaults for this purpose. 或者,也许设计得更好的方法可能是为此目的向NSUserDefaults添加类别。

@interface NSUserDefaults (MyData)
@property (nonatomic) NSString *someDataPoint;
@property (nonatomic) NSInteger somePrimitiveDataPoint;
@end

@implementation NSUserDefaults (MyData)
- (NSString *)someDataPoint {
  return [self objectForKey:@"someDataPoint"];
}
- (void)setSomeDataPoint:(NSString *)someDataPoint {
  [self setObject:someDataPoint forKey:@"someDataPoint"];
}
- (NSInteger)somePrimitiveDataPoint {
  return [[self objectForKey:@"somePrimitiveDataPoint"] integerValue];
}
- (void)setSomePrimitiveDataPoint:(NSInteger)somePrimitiveDataPoint {
  [self setObject:@(somePrimitiveDataPoint) forKey:@"somePrimitiveDataPoint"];
}
@end

You init the singleton when you have to use it. 您必须在必须使用单例时对其进行初始化。 So as Daji Djan said: lazy wins. 因此,正如达吉·达詹(Daji Djan)所说:懒赢。 Just take attention that, you should not do a long-run process in your applicationWillFinishLaunching , it should return as soon as possible. 请注意,您不应该在applicationWillFinishLaunching执行长期运行的过程,它应该尽快返回。

If the singleton is not mandatory during applicationWillFinishLaunching, you should call it in viewWillAppear of first view controller if you need to initialize it ASAP. 如果在applicationWillFinishLaunching期间单例不是必需的,则如果需要尽快对其进行初始化,则应在第一个视图控制器的viewWillAppear中调用它。

lazy always wins 懒惰总是赢

if you can get away with it: as late as possible :) AND always do the minimum needed (but do as much as is reasonable to keep your code clean!) 如果您可以摆脱它:尽可能晚:)并始终执行所需的最低要求(但要尽一切可能使代码保持干净!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM