将获取的 NSManagedObject 分配给属性

Posted

技术标签:

【中文标题】将获取的 NSManagedObject 分配给属性【英文标题】:Assigning fetched NSManagedObject to a property 【发布时间】:2013-08-18 18:21:55 【问题描述】:

这个问题可能看起来很长,但我相信对于核心数据专家来说它是相对简单的。显示配置使这个问题变得很长。谢谢!

在 CoreData 中,我有一个 User 实体和一个从该实体创建的 NSManagedObject 子类 (User.h/.m)。不确定它是否相关,但我正在使用带有 Stackmob 的远程数据库。

这是我的 fetch 请求在 Review.m 中的样子:

获取请求:

-(NSArray *)fetchRequest

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"User" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];

   //Please Note the line below:
    [fetchRequest setReturnsObjectsAsFaults:NO];

    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"username == %@", self.usernameField.text];
    [fetchRequest setPredicate:predicate];

    NSError *error = nil;
    NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];

    return fetchedObjects;



if (fetchedObjects.count>=1)
        
            NSLog(@"Number of Objects Returned %i", fetchedObjects.count);
            NSManagedObject *fetchedObject = [fetchedObjects objectAtIndex:0];
        

这是日志:

2013-08-18 10:26:25.082 Time[995:c07] Number of Objects Returned 1
2013-08-18 10:26:25.082 Time[995:c07] User Object: <User: 0xe07b260> (entity: User; id: 0xa65ab70 <x-coredata://392983AD-D649-4D68-A93F-D86109BC009C-995-000004B584F1BB06/User/piphone5> ; data: <fault>)

几周前,我使用以下内容成功创建了用户对象:

User *newUser = [[User alloc] initIntoManagedObjectContext:self.managedObjectContext];

[newUser setValue:self.usernameField.text forKey:[newUser primaryKeyField]];
[newUser setValue:self.emailAddressField.text forKey:@"email"];

[newUser setPassword:self.passwordField.text];
[newUser setValue:self.gender forKey:@"gender"];

[self.managedObjectContext saveOnSuccess:^

    [self.client loginWithUsername:self.usernameField.text password:self.passwordField.text onSuccess:^(NSDictionary *results) 

        NSLog(@"Login Success %@",results);

     onFailure:^(NSError *error) 
        NSLog(@"Login Fail: %@",error);
    ];

这就是我想在 Review.m 中做的事情:

@interface Review()
@property (strong, nonatomic) User *user;
@end
@sythesize = user;
....
if (fetchedObjects.count>=1)

    NSLog(@"Number of Objects Returned %i", fetchedObjects.count);
    NSManagedObject *fetchedObject = [fetchedObjects objectAtIndex:0];
    NSLog(@"fetchObject Object %@", fetchedObject);

    //Addition
    user = (User*)(fetchedObject);
    NSLog(@"User %@", user);

这是日志:

2013-08-18 11:07:13.313 Time[1177:c07] Number of Objects Returned 1
2013-08-18 11:07:13.314 Time[1177:c07] fetchObject Object <User: 0xa532cc0> (entity: User; id: 0xb426de0 <x-coredata://3336122B-7117-4D92-B0A1-DDBAF80DDBF7-1177-000006EEE046E326/User/piphone5> ; data: <fault>)
2013-08-18 11:07:13.314 Time[1177:c07] User <User: 0xa532cc0> (entity: User; id: 0xb426de0 <x-coredata://3336122B-7117-4D92-B0A1-DDBAF80DDBF7-1177-000006EEE046E326/User/piphone5> ; data: <fault>)

为什么这不起作用?用户仍然显示为故障?我在获取请求中有以下行:[fetchRequest setReturnsObjectsAsFaults:NO];

以下是我需要这样做的原因:

Notification *notificationObject = [NSEntityDescription insertNewObjectForEntityForName:@"Notification" inManagedObjectContext:self.managedObjectContext];

[notificationObject setValue:[NSNumber numberWithInt:1] forKey:@"appType"];
[notificationObject setValue:[notificationObject assignObjectId] forKey:[notificationObject primaryKeyField]];

NSError *error = nil;
if (![self.managedObjectContext saveAndWait:&error])

      NSLog(@"There was an error");

     else

     NSLog(@"Notification Object Created");

        //I need to Add the fetchedObject as UsersObject (which is a relationship) 
        [notificationObject addUsersObject:user];
        [self.managedObjectContext saveOnSuccess:^ ....

这是我的 CoreData 设置:

为什么这不起作用?用户仍然显示为故障?我在获取请求中有以下行:[fetchRequest setReturnsObjectsAsFaults:NO];

【问题讨论】:

核心数据“故障”是一个“占位符对象”并且完全没有错误。如有必要,从数据库中获取数据。尝试记录例如user.email,它应该可以工作。 是的,这是我可以通过访问其属性之一来触发故障的唯一方法。我希望 [fetchRequest setReturnsObjectsAsFaults:NO];会工作的。 糟糕,我忽略了你问题中的那一部分,抱歉。但我用[fetchRequest setReturnsObjectsAsFaults:NO] 做了一个小测试,它按预期工作。 - 将 User 对象作为相关对象添加到 Notification 对象中,添加的对象是否是错误也应该没有区别。 【参考方案1】:

这是 StackMob 限制。在https://developer.stackmob.com/ios-sdk/core-data-guide 明确指出returnObjectsAsFaults / setReturnObjectsAsFaults: (尚)不支持。

【讨论】:

好收获!我不会知道这一点。【参考方案2】:

在日志中显示为故障的托管对象很好。使用它或访问它的属性,Core Data 将以最有效的方式以最小的资源压力填补缺陷

最后一部分很重要,因为它是你不想改变 Core Data 的错误行为的原因。发送通知的必要性并没有改变这一点。

另外,参考Core Data Programming Guide中的故障部分:

批量错误

您可以通过使用带有 IN 运算符的谓词执行 fetch 请求来批处理对象集合,如下面的示例所示。 [...]

NSArray *array = [NSArray arrayWithObjects:fault1, fault2, ..., nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"self IN %@", array];

在 OS X v10.5 及更高版本中,当您创建获取请求时,您可以使用 NSFetchRequest 方法 setReturnsObjectsAsFaults: 确保托管对象不会作为错误返回。

因此,您会看到,特殊的获取请求快捷方式仅适用于 OS X。请继续阅读上述源代码以查看替代方法,预取

【讨论】:

但问题仍然是为什么即使明确设置了[fetchRequest setReturnsObjectsAsFaults:NO],对象也会作为错误返回。至少那是 OP 声称的。 setReturnsObjectsAsFaults: 也适用于 iOS 3.0 或更高版本。 不符合上述来源。 我已经对其进行了测试(使用 iOS 模拟器)并且[fetchRequest setReturnsObjectsAsFaults:NO] 有效。不幸的是,核心数据编程指南不是最新的。

以上是关于将获取的 NSManagedObject 分配给属性的主要内容,如果未能解决你的问题,请参考以下文章

如何更正错误“无法将 [NSManagedObject] 类型的值分配给 [String] 类型

在插入之前分配 NSManagedObject 属性不会坚持

创建新的 NSManagedObject 并将其分配给新的 NSManagedObject *有时*会失败

如何在 swift 中将子类 NSManagedObject 分配给 var(而不是常量)

获取 NSManagedObject 未保存

为 segue 中传递的新 nsmanagedobject 释放分配的上下文