如何等待UIDocument openWithCompletionHandler执行?

时间:2014-10-07 17:30:01

标签: ios asynchronous io synchronous uidocument

我想在应用程序启动时确保在UIDocument openWithCompletionHandler:完成之前不会发生任何事情。 事情是openWithCompletionHandler在主线程上运行,我相信它必须(?)

我目前正在使用异步方法,但它是竞争条件,有时核心数据有时不会在我的rootViewController加载时初始化

- (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;
    }
}

提前谢谢

1 个答案:

答案 0 :(得分:0)

这是一个有效的示例代码,严格来说,您可能必须实现其他一些机制: 1.添加 时钟 maxTimes 以限制迭代。

  1. 在第一次使用之前检查 managedObjectContext 是否为零,对于YES,请将UIDocumentState检查为:

  2. 更多***应考虑UIDocumentState ***,其中包括:

  3. UIDocumentStateClosed (尚未完成打开/创建,只需稍等片刻再试一次)      UIDocumentStateSavingError (在完成处理程序中成功为NO)      UIDocumentStateEditingDisabled (时效情况,请重试)      UIDocumentStateInConflict (例如,因为其他一些人通过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