2012-07-20 72 views
3

我正在处理从NSScreenCast处理导入到核心数据应用程序的代码示例。 (https://github.com/subdigital/nsscreencast/tree/master/012-core-data-importing-data/BeerBrowser)。我有大部分工作的例子。我能够推动刷新按钮,它解析json并将其导入到数据库中。但是,每次按刷新按钮时,都会重新添加相同的数据。我已经将其追溯到下面的代码。核心数据问题 - 检查项目是否存在

+ (Brewery *)breweryWithServerId:(NSInteger)serverId usingManagedObjectContext:(NSManagedObjectContext *)moc { 
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[Brewery entityName]]; 

[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"serverId = %d", serverId]]; 
[fetchRequest setFetchLimit:1]; 

NSError *error = nil; 
NSArray *results = [moc executeFetchRequest:fetchRequest error:&error]; 
NSLog(@"results: %@", results); 
if (error) { 
    NSLog(@"ERROR: %@ %@", [error localizedDescription], [error userInfo]); 
    exit(1); 
} 

if ([results count] == 0) { 
    return nil; 
} 
NSLog(@"results objectAtIndex:0 = %@", [results objectAtIndex:0]); 

return [results objectAtIndex:0]; 
} 

这种方法会发生什么,它会尝试查看数据库中是否已存在该项目。如果此调用返回nil,则MasterViewController中的代码将其再次添加到数据库中。我做了一些调试,并且serverId确实通过了。此外,fetchrequest似乎是有效的(无法确切地调试它)。正如你所看到的,我已经为结果添加了一个NSLog,但它返回一个空的结果。因此,如果结果数为0,则返回nil。因此我的问题。我没有看到这个问题可能成为一个问题。有什么想法吗?

迈克 - 莱利

回答

4

我只是修改你的方法,你可以只取一试:

+ (Brewery *)breweryWithServerId:(NSInteger)serverId usingManagedObjectContext:(NSManagedObjectContext *)moc { 
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:[Brewery entityName]]; 
    [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"serverId == %d", serverId]]; 
    [fetchRequest setFetchLimit:1]; 

    NSError *error = nil; 

    // if there's no object fetched, return nil 
    if ([managedObjectContext countForFetchRequest:fetchRequest error:&error] == 0) { 
    NSLog(@"!!!WARN: NO Object Matches."); 
    return nil; 
    } 

    // fetch your object 
    Brewery *result = [[moc executeFetchRequest:fetchRequest error:&error] lastObject]; 
    if (error != nil) { 
    NSLog(@"ERROR: %@ %@", [error localizedDescription], [error userInfo]); 
    return nil; 
    } 

    NSLog(@"results objectAtIndex:0 = %@", result); 
    return result; 
} 

注:-countForFetchRequest:error:更有效,因为它只有“返回对象给定的获取请求将数量已经返回'。您可以使用此方法来检查是否有匹配的对象。

+0

感谢您的帮助。我试了一下,仍然得到同样的问题。在深入挖掘它之后,似乎它正在比较的serverId在任何时候都不会保存到数据库中。所以setPredicate正在比较传递给没有数据的列的serverId。因此它从不匹配任何东西。我正在查看代码,看看我能否找到它。数据模型确实显示serverId。 – 2012-07-20 04:15:45

+0

@MikeRiley'NSLog的日志是什么(@“results:%@”,结果);' &'NSLog(@“results objectAtIndex:0 =%@”,[results objectAtIndex:0]);'? – Kjuly 2012-07-20 05:25:51

0

我认为你的谓词有问题。它应该阅读:

[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"serverId == %d", serverId]]; 

你错过了双等于....

发现这并不重要。你应该检查以确保你的moc不是零。你确定你正确地传递了它吗?

+1

实际上,这不是它 - '='和'=='在'NSPredicate'中是一样的。点击此处查看基本比较部分https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795-CJBDBHCB – ikuramedia 2012-07-20 04:41:45

+0

感谢您的指点那个。我一直使用double equals。文档不会撒谎。 – Jamie 2012-07-20 04:49:10

+0

@Jamie我总是太.. – Kjuly 2012-07-20 05:20:00

1

您试图在谓词中比较标量值(NSInteger)与对象值(NSNumber)。

尝试:

[NSPredicate predicateWithFormat:@"serverId = %@", [NSNumber numberWithInteger:serverId]]