如何在OpenWithCompletionHandler后返回结果:完成 [英] how to return result after OpenWithCompletionHandler: is complete

查看:244
本文介绍了如何在OpenWithCompletionHandler后返回结果:完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要在Coredata数据库中查询照片

Want to query a photo in the Coredata database

这是我的代码

这是NSObjectSubclass类别

this is the NSObjectSubclass category

//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类连接起来。

The NSObject Class that hook them up.

 //  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只有Entity命名为Photo ,并且它只有一个属性name。
问题是返回总是在块完成之前得到执行并总是返回NO。
测试代码此处

The coredata only have on Entity named "Photo", and it got only one attribute "name". The problem is that the return always get execute before the block is complete and always return NO. Test code here

或在查询时应该执行openWithCompletionHandler以外的操作吗?

推荐答案

您的方法异步工作,例如 -openWithCompletionHandler:。它需要一个块,当答案是已知的时候被调用,并且它接收的答案,true或false作为参数。

You need to rework your method to work asynchronously, like -openWithCompletionHandler:. It needs to take a block which is invoked when the answer is known and which receives the answer, true or false, as a parameter.

然后,调用者应该传入

或者,你应该延迟整个逻辑块,关心照片在数据库。

Or, alternatively, you should delay the whole chunk of logic which cares about the photo being in the database. It should be done after the open has completed.

您必须为更具体的建议显示更多代码。

You'd have to show more code for a more specific suggestion.

因此,您可以将 isPhoto ... 方法修改为:

So, you could rework the isPhoto... method to something like:

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

这篇关于如何在OpenWithCompletionHandler后返回结果:完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆