1

代码有问题吗?使用这个谓词我什么也得不到。注释掉谓词,然后我可以从实体“BankDetail”中获取所有对象。所以我认为问题在于这两行。

// self.bankInfo.name is set in prepareForSegue in first view controller
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"info.name = %@",self.bankInfo.name];
[request setPredicate:predicate];

我的模型包括两个实体,它们是一对一的关系

银行信息.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

银行明细.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绝对设置,我 NSLog 它就在谓词行之前

  • 我这样做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: 结果predicate 没有任何问题。该错误是由其他地方的粗心错误引起的(请参阅已接受的答案,它与重命名有关)。如果您对谓词有疑问,请忽略此帖子。

4

7 回答 7

1

如果它是一对一的关系,并且您已经有了self.bankInfo.name要匹配的字符串,为什么不获取BankInfo具有该名称的对象并访问该对象的.detail属性呢?这就是建立关系的全部意义,不是吗?

但是,您的谓词应该有效。虽然是什么self.bankInfo?你确定这self.bankinfo.name是一个有效的字符串吗?

于 2012-09-27T15:52:23.000 回答
1

您的谓词结构没问题。请参阅我的其他答案,了解一个简单的项目来证明基本原理。

根据对其他答案的响应,听起来您正在将其传递NSFetchRequest给 aNSFetchedResultsController并使用其行为来确定您的谓词不起作用。

我的第一个建议是记录谓词并查看它是否符合预期:

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"]);

最后一条日志语句实际上记录了所有银行名称的数组,因此您可以查看 in 中的值self.bankInfo.name是否如您所愿地出现在完整结果中。

于 2012-09-28T08:14:17.843 回答
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
于 2012-09-27T09:01:33.890 回答
0

最后我不得不使用一个不太优雅的解决方法。我最终也添加了一个name属性BankDetail。所以一个BankInfo.name 对应一个BankDetail.name。然后我使用谓词:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@",self.bankInfo.name];

它做了我想做的事:BankDetail为相应的对象获取一个BankInfo对象。我想知道这是最好的做法。

于 2012-09-25T08:52:58.023 回答
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.bankInfoorself.bankInfo.name为空,或者因为info您的BankDetail对象中没有任何内容(未设置关系)。

于 2012-09-26T23:20:56.630 回答
0

我终于修复了这个错误。这根本与谓词无关。我将实体从Xcode 编辑BankDetailsBankDetail中的 .xcdatamodeld 重命名为,只需按回车键并更改它,就像重命名任何其他文件一样。

然后我继续手动重命名自动生成的 NSManagedObject 子类文件和其他引用它的类文件中的各个部分,直到所有警告消失。我想我已经重命名了所有必要的,但我没有。该程序没有像我在问题中描述的那样运行,但是没有错误,没有警告,Xcode 只是编译并运行。

一段时间后,当我终于尝试重新生成子类文件以修复错误时,旧的BankDetails显示为类名,并且出现了很多命名错误。起初我认为这是 Xcode 的一些错误。所以我再次清理构建并重新生成子类文件。然而,它仍然是旧的BankDetails。经过几次尝试,我在 Data Model Inspector 中发现了问题(见下面的截图)。更改类名称,一切运行完美。

道德:总是非常谨慎地重命名!

在此处输入图像描述

于 2012-09-29T10:28:56.613 回答
-1

问题可能是=在谓词字符串中使用了运算符。

根据文档,LIKE运算符用于字符串比较,例如

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"info.name like %@",self.bankInfo.name];

该文档还提供了一个在谓词中遍历关系的示例,因此您应该能够获得所需的结果。从NSPredicate文档中:

您可以为关系创建谓词,例如:

  • group.name 像“工作*”
于 2012-09-26T19:11:37.377 回答