OpenWithCompletionHandler完成后如何返回结果

想要查询Coredata数据库中的照片

这是我的代码

这是NSObjectSubclass类别

//Photo+creak.h #import "Photo+creat.h" @implementation Photo (creat) +(Photo *)creatPhotoByString:(NSString *)photoName inManagedObjectContext:(NSManagedObjectContext *)context{ Photo *picture = nil; NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"]; request.predicate = [NSPredicate predicateWithFormat:@"name = %@", photoName]; NSArray *matches = [context executeFetchRequest:request error:nil]; if (!matches || [matches count]>1) { //error } else if ([matches count] == 0) { picture = [NSEntityDescription insertNewObjectForEntityForName:@"Photo" inManagedObjectContext:context]; picture.name = photoName; } else { picture = [matches lastObject]; } return picture; } + (BOOL)isPhoto:(NSString *)photoName here:(NSManagedObjectContext *)context{ NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"]; request.predicate = [NSPredicate predicateWithFormat:@"name = %@", photoName]; NSArray *matches = [context executeFetchRequest:request error:nil]; switch ([matches count]) { case 1: return YES; break; default: return NO; break; } } @end 

视图控制器内的代码

 //View Controller - (IBAction)insertData:(UIButton *)sender { NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; url = [url URLByAppendingPathComponent:@"test"]; UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url]; if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) { [defaultDocument saveToURL:defaultDocument.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:NULL]; } [defaultDocument openWithCompletionHandler:^(BOOL success) { [Photo creatPhotoByString:@"test" inManagedObjectContext:defaultDocument.managedObjectContext]; [defaultDocument saveToURL:defaultDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL]; }]; [sender setTitle:@"Okay" forState:UIControlStateNormal]; [sender setEnabled:NO]; } - (IBAction)queryFromDatabase:(UIButton *)sender { NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; url = [url URLByAppendingPathComponent:@"test"]; UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url]; BOOL isItWorking = [checkPhoto isPhoto:@"test" inManagedDocument:defaultDocument]; if (isItWorking) { [sender setTitle:@"Okay" forState:UIControlStateNormal]; } else { [sender setTitle:@"NO" forState:UIControlStateNormal]; } } 

挂钩它们的NSObject类。

  // checkPhoto.m #import "checkPhoto.h" @implementation checkPhoto + (BOOL)isPhoto:(NSString *)photoToCheck inManagedDocument:(UIManagedDocument *)document{ __block BOOL isPhotoHere = NO; if (document.documentState == UIDocumentStateClosed) { [document openWithCompletionHandler:^(BOOL success) { isPhotoHere = [Photo isPhoto:photoToCheck here:document.managedObjectContext]; }]; } return isPhotoHere; } @end 

Coredata只有名为“Photo”的Entity,并且只有一个属性“name”。 问题是返回总是在块完成之前得到执行,并且总是返回NO。 testing代码在这里

或者在查询时我应该做一些比openWithCompletionHandler更好的事情?

你需要重做你的方法来asynchronous工作,就像-openWithCompletionHandler: 它需要采取一个块,当答案已知,并接收答案,真或假,作为参数调用。

然后,调用者应该通过一个在答案已知之后做任何事情的块。

或者,或者,您应该延迟关心照片在数据库中的整个逻辑块。 这应该在公开完成之后完成。

您必须展示更多代码才能获得更具体的build议。


所以,你可以重新把isPhoto...方法改为:

 + (BOOL)checkIfPhoto:(NSString *)photoToCheck isInManagedDocument:(UIManagedDocument *)document handler:(void (^)(BOOL isHere))handler { if (document.documentState == UIDocumentStateClosed) { [document openWithCompletionHandler:^(BOOL success) { handler([Photo isPhoto:photoToCheck here:document.managedObjectContext]); }]; } else handler(NO); } 

那么你可以重写这个:

 - (IBAction)queryFromDatabase:(UIButton *)sender { NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; url = [url URLByAppendingPathComponent:@"test"]; UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url]; [checkPhoto checkIfPhoto:@"test" isInManagedDocument:defaultDocument handler:^(BOOL isHere){ if (isHere) { [sender setTitle:@"Okay" forState:UIControlStateNormal]; } else { [sender setTitle:@"NO" forState:UIControlStateNormal]; } }]; } 

试试看

 +(BOOL)isPhoto:(Photo *)photo inDataBase:(UIManagedDocument *)defaultDocument{ __block BOOL isPhotoThere = NO; dispatch_semaphore_t sema = dispatch_semaphore_create(0); [defaultDocument openWithCompletionHandler:^(BOOL success) { [defaultDocument.managedObjectContext performBlock:^{ isPhotoThere = [Photo checkPhoto:photo]; dispatch_semaphore_signal(sema); }]; }]; dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); dispatch_release(sema); return isPhotoThere; }