11

有人有关于如何在 CoreData 中建模和编码瞬态一对一关系的示例吗?例如,我有 2 个具有一对多关系的实体。医生和预约。现在我想在医生实体上建立一个名为 mostRecentAppointment 的临时关系。在 xcode 设计器中建模很简单,但我不确定实现方面。我还应该实施逆向吗?看起来很傻。

4

4 回答 4

4

看看我最近写的这段代码,将图像缓存在 NSManagedObject 中:

首先,您在模型中定义一个瞬态属性(请注意,如果您的瞬态属性指向的对象类型不是 CoreData 支持的对象类型,您将Undefined在模型中保留为“”)

在此处输入图像描述

然后,为该实体重新生成 NSManagedObject 子类,或者手动添加新属性,头文件应如下所示:

@interface Card : NSManagedObject

@property (nonatomic, retain) NSString * imagePath;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSNumber * order;
@property (nonatomic, retain) NSString * displayName;
@property (nonatomic, retain) UIImage *displayImage;

@end

这里我们将瞬态属性的类改成实际的类类型

例如displayImage这里的类型是UIImage.

在实现文件(或扩展类)中,您为瞬态属性实现 getter/setter:

-(UIImage*)displayImage{

  //Get Value
  [self willAccessValueForKey:@"displayImage"];
  UIImage *img = (UIImage*)[self primitiveValueForKey:@"displayImage"];
  [self didAccessValueForKey:@"displayImage"];

   if (img == nil) {
    if ([self imagePath]) { //That is a non-transient property on the object
      img = [UIImage imageWithContentsOfFile:self.imagePath];
      //Set Value
      [self setPrimitiveValue:img forKey:@"displayImage"];
    }
  }
  return img;
}

希望对您有所帮助。

于 2013-04-29T15:27:17.847 回答
2

您需要做的是添加一个名为 newAppointment 的 Appointment 类型的实体,并在每次为给定医生创建新约会时设置它。就这么简单。

正如苹果推荐的那样,始终实施逆向验证和核心数据效率。

或者,您可以为约会添加时间戳并使用 NSPredicates 在给定的医生链接约会中搜索最新约会。

于 2013-04-29T14:00:04.637 回答
1

在这种情况下,要覆盖的适当方法是-awakeFromFetchDoctor实体中,例如:

- (void)awakeFromFetch {
    [super awakeFromFetch];// important: call this first!
    self.mostRecentAppointment = <something>; // normal  relationship
    self.mostRecentAppointment.doctor = self; // inverse relationship
}

在模型设计器中,将正常和反向关系都标记为瞬态。应该是这样的。

于 2019-05-31T23:20:24.637 回答
0

好吧,您只需要在您自己的示例程序中进行尝试,正确设置的时间不会超过一个小时。

我的猜测是——不需要额外的编码。如果 Apple 关于 CoreData 的文档是正确的,则普通属性/关系和“瞬态”之间的唯一区别是后者不会持久化,这意味着当您“保存”时它不会更新持久性存储。

我猜想否则它的所有方面都是完整的,包括 KVO/KVC 合规性、撤消支持、验证和通过删除规则自动更新。唯一的问题是,在重新获取实体之后——瞬态关系将始终为零。

为此 --- 我当然不建议将临时关系设置为“非可选”,因为对于大多数实体来说,它在大多数情况下很可能为空。

我会建立一个反向关系(瞬态以及明智地命名),并将两个删除规则都设置为“Nullify”。

到目前为止是暂时的关系。

但这是我想出的一个替代方案,试图解决几乎相同的问题。我的“约会”是相关的约会之一,但不仅仅是“最新的”,而是第一个“未完成”的约会。非常相似的逻辑。

我没有使用临时关系,而是将一个新的计算属性添加到我的“Doctor”实体生成的 NSManagedObject 子类中,在一个类别中,如下所示:

@interface XXDoctor (XXExtensions)
/**
 @brief Needs manual KVO triggering as it is dependent on a collection. 
        Alternatively, you can observe insertions and deletions of the appointments, and trigger KVO on this propertyOtherwise it can be auto-
 @return the latest of the to-many appointments relation.
 **/
@property (readonly) XXAppointment *latestAppointment;    // defined as the
@end

执行:

#import "XXDoctor".h"
#import "XXAppointment.h"
@implementation XXDoctor (XXExtensions)
// this won't work because "appointments" is a to-many relation.
//+ (NSSet *)keyPathsForValuesAffectingLatestAppointment {
//  return [NSSet setWithObjects:@"appointments", nil];
//}
- (XXAppointment *) latestAppointment {
    NSInteger latestAppointmentIndex = [self.appointments indexOfObjectPassingTest:^BOOL(XXAppointment *appointment, NSUInteger idx, BOOL *stop) {
        *stop =  (appointment.dateFinished == nil);
        return *stop;
    }];
    return (latestAppointmentIndex == NSNotFound) ? nil : [self.appointments objectAtIndex: latestAppointmentIndex];
}
@end
于 2014-09-28T12:13:14.410 回答