代码有问题吗?我可以使用这个谓词取任何东西。注释掉谓词然后我可以从实体“BankDetail”中获取所有对象。所以我认为问题在于这两行。
// self.bankInfo.name is set in prepareForSegue in first view controller
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"info.name = %@",self.bankInfo.name];
[request setPredicate:predicate];
我的模型包含两个实体,它们是一对一的关系
BankInfo.h
@class BankDetail;
@interface BankInfo : NSManagedObject
@property (nonatomic, retain) NSString * city;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * state;
@property (nonatomic, retain) BankDetail * detail;
@end
BankDetail.h
@class BankInfo;
@interface BankDetail : NSManagedObject
@property (nonatomic, retain) NSString * closeDate;
@property (nonatomic, retain) NSString * updateDate;
@property (nonatomic, retain) NSString * zip;
@property (nonatomic, retain) NSString * acquiringInstitution;
@property (nonatomic, retain) BankInfo * info;
@end
修改
提供更多细节:
self.bankInfo.name
肯定已设置,我在谓词行之前将其存储
我在viewDidLoad
中执行此操作:
NSEntityDescription *entity = [NSEntityDescription entityForName:@"BankDetail" inManagedObjectContext:context];
NSLog(@"[entity description] is %@",[entity description]);
在控制台中获取此内容:
info = "(<NSRelationshipDescription: 0x6d3eb30>), name info, isOptional 1, isTransient 0, entity BankDetail, renamingIdentifier info, validation predicates (\n), warnings (\n), versionHashModifier (null)\n userInfo {\n}, destination entity BankInfo, inverseRelationship detail, minCount 1, maxCount 1, isOrdered 0, deleteRule 2";
EDIT2: 结果是谓词没有错误。这个错误是由其他地方的粗心错误引起的(参见接受的答案,它是关于重命名)。如果您对谓词有疑问,请点击这篇文章。
答案 0 :(得分:1)
如果它是一对一的关系,并且您已经拥有要匹配的self.bankInfo.name
字符串,为什么不提取具有该名称的BankInfo
对象并访问该对象.detail
财产?这是建立关系的重点,不是吗?
但是,你的谓词应该有效。但self.bankInfo
是什么?您确定self.bankinfo.name
是有效的字符串吗?
答案 1 :(得分:1)
你的谓词结构没问题。请参阅我的其他answer,了解一个简单的项目来证明基本原理。
根据对其他答案的回答,您可能会将此NSFetchRequest
传递给NSFetchedResultsController
并使用其行为来确定您的谓词不起作用。
我的第一个建议是记录谓词并查看它是否符合预期:
NSLog(@"%@", predicate);
如果可以,那么为了测试谓词不起作用的理论,你应该在构建请求后立即直接执行NSFetchRequest
,并检查结果,例如
// self.bankInfo.name is set in prepareForSegue in first view controller
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"info.name = %@",self.bankInfo.name];
[request setPredicate:predicate];
NSArray *results = [myMangedObjectContext executeFetchRequest:request error:nil];
如果这没有说明问题,那么我建议您从请求中删除谓词,执行请求,并使用以下日志语句来检查完整结果:
NSLog(@"%@", self.bankInfo.name);
NSLog(@"%@", [results valueForKeyPath:@"info.name"]);
最后一条日志语句实际记录了所有银行名称的数组,因此您可以查看self.bankInfo.name
中的值是否出现在您想要的完整结果中。
答案 2 :(得分:0)
最后,我必须使用一个不那么优雅的解决方法。我最终也为name
添加了BankDetail
属性。因此,一个BankInfo.name对应一个BankDetail.name。然后我使用谓词:
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@",self.bankInfo.name];
它可以实现我想要的:为相应的BankDetail
对象获取一个BankInfo
对象。我不知道这是最好的做法..
答案 3 :(得分:0)
据我所知,你的谓词没有任何问题。我在我的应用程序中有一个非常相似的,它工作正常:
@class Hospital;
@interface Patient : NSManagedObject
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) Hospital *hospital;
@end
和
@class Patient;
@interface Hospital : NSManagedObject
@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSSet *patients;
@end
我的谓词:
request.predicate = [NSPredicate predicateWithFormat:@"hospital.name = %@", self.hospital.name];
所以你的代码没有问题。问题必须是因为self.bankInfo
或self.bankInfo.name
为空,或者因为info
对象中BankDetail
中没有任何内容(未设置关系)。
答案 4 :(得分:0)
您最初发布的谓词代码是正确的。下面是一个测试基本原理的快速测试项目:(正确记录“银行名称”)
// Xcode 4.5:
// Create a new iOS Master-Detail project called "BankInfoTest" tick the "Use Core Data" check box (and ARC).
// Delete all files except the AppDelegate and the BankInfoTest data model (leave supporting files).
// Delete all properties and methods from AppDelegate.h
// Paste this code into AppDelegate.m
// Delete the default entity from the data model
// Add "BankInfo" entity, add attribute "name" of type string.
// Add "BankDetail" entity, add relationship called "info" to BankInfo (leave default 1 to 1 type).
// On BankInfo entity add inverse relationship "detail" to BankDetail (leave default 1 to 1 type).
// Select both entities then select "Editor -> Create NSManagedObject Subclass" to create subclasses.
// Run.
#import "AppDelegate.h"
#import "BankDetail.h"
#import "BankInfo.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
/////////////////////////////////////////////////////////////////////////////////////
// Setup the core data stack.
/////////////////////////////////////////////////////////////////////////////////////
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"BankInfoTest" withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
NSURL *appDocsDirectory = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
NSURL *storeURL = [appDocsDirectory URLByAppendingPathComponent:@"BankInfoTest"];
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:nil];
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
context.persistentStoreCoordinator = coordinator;
/////////////////////////////////////////////////////////////////////////////////////
// Load some test data and reset the context.
/////////////////////////////////////////////////////////////////////////////////////
BankDetail *detailObject = [NSEntityDescription insertNewObjectForEntityForName:@"BankDetail" inManagedObjectContext:context];
BankInfo *infoObject = [NSEntityDescription insertNewObjectForEntityForName:@"BankInfo" inManagedObjectContext:context];
infoObject.name = @"bank name";
detailObject.info = infoObject;
[context save:nil];
[context reset];
/////////////////////////////////////////////////////////////////////////////////////
// Test the Predicate
/////////////////////////////////////////////////////////////////////////////////////
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"BankDetail"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"info.name = %@", @"bank name"];
[request setPredicate:predicate];
NSArray *results = [context executeFetchRequest:request error:nil];
BankDetail *fetchedObject = [results lastObject];
NSLog(@"%@", fetchedObject.info.name);
return YES;
}
@end
答案 5 :(得分:0)
我终于修复了这个bug。它根本不是谓词。我在Xcode编辑器中的.xcdatamodeld中将实体从BankDetails
重命名为BankDetail
,只需按回车键并更改它,就像重命名任何其他文件一样。
然后我继续手动重命名自动生成的NSManagedObject子类文件中的各个部分,以及引用它的其他类文件,直到所有警告都消失。我想我已经重命名了所有必要的东西,但我没有。该程序没有像我在问题中描述的那样运行,但没有错误,没有警告,Xcode只是编译和运行。
过了一段时间,当我最终尝试重新生成子类文件来修复bug时,旧的BankDetails
显示为类名,并且出现了许多命名错误。起初我认为这是Xcode的一些错误。所以我清理构建并再次重新生成子类文件。然而,它仍然是好老BankDetails
。经过几次尝试后,我在Data Model Inspector中发现了问题(见下面的截图)。更改班级名称,一切运行完美。
道德:总是极其谨慎地重命名!
答案 6 :(得分:-1)
问题可能是在谓词字符串中使用=
运算符。
根据文档,LIKE
运算符用于字符串比较,例如
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"info.name like %@",self.bankInfo.name];
该文档还提供了遍历谓词中关系的示例,以便您能够实现所需的结果。来自NSPredicate
文档:
您可以为关系创建谓词,例如:
- group.name喜欢“work *”