我的CoreData获取请求实际返回的是什么?

Mat*_*ick 3 iphone core-data objective-c nsarray

我从数据存储中取出一些对象,但结果并不是我所期待的.我是CoreData的新手,但我相当肯定这应该有用.我错过了什么?

请注意,User是一个有效的托管对象,我将其头文件包含在此代码中,并且该UserID是该类的有效属性.

NSFetchRequest *requestLocal = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:messageManagedObjectContext];
[requestLocal setEntity:entity];
// Set the predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY UserID IN %@", userList];
[requestLocal setPredicate:predicate];
// Set the sorting
... sorting details removed but exist and are fine ...
// Request the data
NSArray *fetchResults = [messageManagedObjectContext executeFetchRequest:requestLocal error:&error];
[requestLocal release];

for (int i; i < [fetchResults count]; i++) {
    [fetchResults objectAtIndex:i].UserID = ...<----HERE
}
Run Code Online (Sandbox Code Playgroud)

fetchResults不是User对象的数组吗?不会[fetchResults objectAtIndex:i]成为User对象吗?为什么在构建" 非结构或联合的成员'UserID'请求时"会出错?

对不起,如果这是一个基本错误,我显然缺少一些基本概念.我做了大量的搜索,看起来应该是正确的.(我也试过快速枚举,但它抱怨fetchResults项目不是有效的Objective C对象,我认为实际上是同样的错误.)


更新:

(来自下面的评论)

我的目标是更新对象,在更改后调用saveAction.KVC方法是否仍然引用实际对象?我试过快速枚举:

for (User thisUser in fetchResults) {

......但它不喜欢那样.

我使用了更通用的版本:

(id thisUser in fetchResults)

......但它不会让我设定

[thisUser valueForKey:@"FirstName"] = anything

......坚持没有左值.

将:

[[thisUser valueForKey:@"FirstName"] stringWithString:@"Bob"]

......诀窍还是有更好的方法?对不起,我知道这几乎是一个新问题,但我仍然没有得到fetchResults数组中的内容.

Tec*_*Zen 8

您的fetchedResults变量包含NSArray对象.但是,NSArray可以保存任意对象组.与标准C数组不同,不要求NSArray对象都是单个类.

您在此处使用的点符号:

[fetchResults objectAtIndex:i].UserID =
Run Code Online (Sandbox Code Playgroud)

...虽然合法的语法仍然混淆了编译器,因为编译器不知道返回了什么类的对象[fetchResults objectAtIndex:i].不知道课程,它不知道到底UserID是什么.因此错误"request for member 'UserID' in something not a structure or union".至少你必须将返回转换[fetchResults objectAtIndex:i]为某个类,以便编译器有一个关于'UserID'是什么的线索.

但是,你不应该使用这种结构,即使它是合法的,因为它是危险的.请参阅下面的最佳实践表格.

理解NSManagedObject及其子类可能很棘手,因为NSManagedObject本身使用了一个技巧associative storage,该技巧允许任何通用NSManagedObject实例存储任何模型中定义的任何实体的任何属性.这可能会使新手感到困惑,因为有多种方法可以引用相同的实体,实例和属性.有时,这些示例使用泛型NSMangedObjects和setValue:forKey:/ valueForKey:或其他时候使用objectInstance.propertyName.

关联存储的作用类似于附加到NSManagedObject类的每个实例的字典.当您插入这样的通用NSManagedObject时:

NSManagedObject *mo=[NSEntityDescription insertNewObjectForEntityForName:@"User" 
                                                  inManagedObjectContext:self.managedObjectContext];
Run Code Online (Sandbox Code Playgroud)

...您将获得NSManageObject类的实例,其关联存储键设置为User数据模型中定义的实体属性.然后,您可以使用键值编码(与字典具有相同的语法)来设置和检索值:

[mo setValue:@"userid0001" forKey:@"UserID"];
NSString *aUserID=[mo valueForKey:@"UserID"];
Run Code Online (Sandbox Code Playgroud)

关联存储允许您在代码中表示任何复杂的数据模型,而无需编写任何自定义NSManagedObject子类.(在Cocoa中,它允许您使用绑定,使您可以创建整个程序而无需编写任何数据管理代码.)

但是,通用的NSManagedObject类比一个自动处理保存和读取的美化字典要好一些.如果需要具有自定义行为的数据对象,则需要显式定义NSManagedObject子类.如果你让Xcode从数据模型中的实体生成类,你最终得到的源文件如下:

User.h
@interface User :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * firstName;
@property (nonatomic, retain) NSString * userID;
@property (nonatomic, retain) NSString * lastName;

@end

User.m
#import "User.h"


@implementation User 

@dynamic firstName;
@dynamic userID;
@dynamic lastName;

@end
Run Code Online (Sandbox Code Playgroud)

现在,您不再受限于关联存储的键值语法.您可以使用点语法,因为编译器有一个类可以引用:

User *aUser=[NSEntityDescription insertNewObjectForEntityForName:@"User" 
                                                  inManagedObjectContext:self.managedObjectContext];
aUser.userID=@"userID0001";
NSString *aUserID=aUser.userID;
Run Code Online (Sandbox Code Playgroud)

考虑到所有这些,对fetchedResults阵列的正确引用形式变得清晰.假设您要将所有userID属性设置为单个默认值.如果您使用通用NSManagedObject类,则使用:

for (NSManagedObject *aMO in fetchedResults) {
    [aMO setValue:@"userid0001" forKey:@"UserID"];
    NSString *aUserID=[aMO valueForKey:@"UserID"];
}
Run Code Online (Sandbox Code Playgroud)

如果您使用专用子类,您将使用:

for (User *aUserin fetchedResults) {
    aUser.userID=@"userID0001";
    NSString *aUserID=aUser.userID;
}
Run Code Online (Sandbox Code Playgroud)

(注意:您也可以始终对所有NSManagedObject子类使用泛型表单.)