1

I want to ensure at app start that nothing goes on until UIDocument openWithCompletionHandler: is finished. The thing is openWithCompletionHandler runs on the main thread and I believe it has to (?)

I am currently using the asynchronous approach but it's a race condition, sometimes core data is initialised sometimes not when my rootViewController loads

- (void)useDocument {
    [self setPersistentStoreOptionsInDocument:self.document];

    if(![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]) {
        [self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            self.isReady = YES;
            self.success = success;
        }];
    } else if (self.document.documentState == UIDocumentStateClosed) {
        [self.document openWithCompletionHandler:^(BOOL success) {
            self.isReady = YES;
            self.success = success;
        }];
    } else if (self.document.documentState == UIDocumentStateNormal) {
        self.isReady = YES;
        self.success = YES;
    }
}

Thank you in advance

Pedro Borges
  • 1,568
  • 1
  • 14
  • 25

1 Answers1

0

this is a sample code that works, to be strict, you might have to implement some other mechanism: 1. Add a clock or a maxTimes to restrict the iteration.

  1. Check if managedObjectContext is nil before the first time you use it, for YES, check the UIDocumentState as:

  2. More ***UIDocumentState***s should be considered, this includes:

UIDocumentStateClosed (haven’t done the open/create yet, just wait for a moment and try again) UIDocumentStateSavingError (success be NO in completion handler) UIDocumentStateEditingDisabled (temprorary situation, try again) UIDocumentStateInConflict (e.g., because some other deviece changed it via iCloud)

//header file
@interface file2CoredataClass : NSObject{

}
-(void)manualSave;
-(void)manualClose;
-(void)addAllPaths;
@property NSManagedObjectContext *managedObjectContext;
@end

//implementation
@implementation file2CoredataClass
UIManagedDocument *doc;
NSFileManager *fm;
-(id)init{
    self=[super init];
    if(self){
        fm = [NSFileManager defaultManager];
        NSURL *docDirectory = [[fm URLsForDirectory:NSDocumentationDirectory inDomains:NSUserDomainMask] firstObject];
        //notice:for some reason i don't know, the directory may not exist, and you can never create a document in this situation.
        //so, check if directory exists, and if not, create the directory.
        if(![fm fileExistsAtPath:[NSString stringWithFormat:@"%@",docDirectory] isDirectory:&isDir]){
            [fm createDirectoryAtPath:[NSString stringWithFormat:@"%@",docDirectory]  withIntermediateDirectories:YES attributes:nil error:nil];
        }
        NSString *docName = @"geoDoc";
        NSURL *url = [docDirectory URLByAppendingPathComponent:docName];
        doc = [[UIManagedDocument alloc]initWithFileURL:url]; // this creates the UIManagedDocument but not yet open or create the underlying file.
        //open or create the file
        [self openCreateFile:fm documentURL:url];

    }
    return self;
}

-(void)openCreateFile:(NSFileManager *)fm documentURL:(NSURL *)url{
    BOOL fileExists = [fm fileExistsAtPath:[url path]];
    if(fileExists){
        [doc openWithCompletionHandler:^(BOOL success) {
            //block to execute as file operation is asynchronous
            if(!success){
                [self openCreateFile:fm documentURL:url];
            }else if(doc.documentState == UIDocumentStateNormal){
                _managedObjectContext = doc.managedObjectContext;
            }
        }];
    }else{
        [doc saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
            //block to execute as file operation is asynchronous
            if(!success){
                [self openCreateFile:fm documentURL:url];
            }else if(doc.documentState == UIDocumentStateNormal){
                _managedObjectContext = doc.managedObjectContext;
            }
        }];
    }
}
@end