1

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」という名前のエンティティにのみ存在し、属性「name」は1つだけです。問題は、ブロックが完了する前にリターンが常に実行され、常にNOを返すことです。ここでコードをテストします

または、クエリを実行するときにopenWithCompletionHandler以外のことを行う必要がありますか?

4

2 に答える 2

2

のように、非同期で動作するようにメソッドを作り直す必要があります-openWithCompletionHandler:。答えがわかっているときに呼び出され、trueまたはfalseの答えをパラメーターとして受け取るブロックを取得する必要があります。

次に、発信者は、回答がわかった後に発生するはずのことをすべて実行するブロックを渡す必要があります。

または、代わりに、データベースにある写真を気にするロジックのチャンク全体を遅らせる必要があります。オープンが完了した後に行う必要があります。

より具体的な提案を行うには、より多くのコードを表示する必要があります。


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];
        }
    }];
}
于 2012-06-03T08:21:58.780 に答える
0

それを試してみてください

+(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;
}
于 2012-06-03T08:24:29.340 に答える