I have a question on managing access to a singleton whose initialization may not be finished by this time its used the first time. I created a singleton called StoriesModel that includes some Core Data init code for opening or creating its database file. After initialization this singleton makes its ManagedObjectContext available to the various screens in the app for creating objects, displaying tables of objects, etc.
The first time that I call:
[StoriesModel sharedModel].context
it will obviously fail. In Objective C what is a good pattern to solve this problem? I know that I can just make the first call to the model class way before its used, but that won't always work. My previous languages have used things like events and data binding to solve this. I'm new to multithreading.
Here is some code for the header:
@interface StoriesModel : NSObject
+ (StoriesModel *)sharedModel;
@property (nonatomic,strong) NSManagedObjectContext *context;
@end
and the implementation:
@implementation StoriesModel
+ (StoriesModel *)sharedModel
{
static StoriesModel *sharedSingleton;
@synchronized(self)
{
if (!sharedSingleton)
{
sharedSingleton = [[StoriesModel alloc] init];
[sharedSingleton doInit];
}
return sharedSingleton;
}
}
- (void)doInit
{
// do some stuff that results in the context property being set in a few seconds
}
@end
thanks,
Gerry
-- Sample modified context getter:
- (NSManagedObjectContext *)context
{
if (!self.storyDatabase)
{
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:@"StoryDatabase"];
self.storyDatabase = [[UIManagedDocument alloc] initWithFileURL:url];
// if file doesn't exist create it
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.storyDatabase.fileURL path]])
{
[self.storyDatabase saveToURL:_storyDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success)
{
_context = self.storyDatabase.managedObjectContext;
[self populateSampleStories];
}];
}
// if file exists but is closed open it
else if (self.storyDatabase.documentState == UIDocumentStateClosed)
{
[self.storyDatabase openWithCompletionHandler:^(BOOL success)
{
_context = self.storyDatabase.managedObjectContext;
}];
}
// if file exists and is open use it
else if (self.storyDatabase.documentState == UIDocumentStateNormal)
{
_context = self.storyDatabase.managedObjectContext;
}
}
}