如何将类型安全结构类型 Core Data 属性与 mogenerator 一起使用?

发布于 2025-01-06 09:53:29 字数 1053 浏览 0 评论 0原文

对于 NSKeyValueCoding 可以处理的结构类型的属性,我使用 Apple 文档中描述的 Core Data 访问器模式 此处

例如,可以在 Core Data 模型中将 NSRange 结构指定为 Transformable 类型,然后可以通过在 NSManagedObject 子类中提供以下形式的访问器来避免客户端使用 NSValue 胡言乱语:

Interface:

@property(assign, nonatomic) NSRange range;

实现;

- (NSRange) range {

    [self willAccessValueForKey:@"range"];
    NSRange retVal = range;
    [self didAccessValueForKey:@"range"];

    return retVal;
}

- (void)setRange:(NSRange)aRange {

    [self willChangeValueForKey:@"range"];
    range = aRange;
    [self didChangeValueForKey:@"range"];
}

然而,Mogenerator 生成的 NSManagedObject 子类将 Transformable 属性声明为 NSObject 属性,因此客户端需要获取/设置 NSValues。

使用 mogenerator 处理这种情况的最佳方法是什么,同时(1)保持简单的 Transformable 模式而不是弄乱瞬态支持属性,以及(2)避免对 Mogenerator 的“机器”类进行任何编辑?

For attributes of struct types that NSKeyValueCoding can handle, I use the Core Data accessor pattern described in Apple's docs here.

For example, an NSRange struct can be specified in the Core Data model as of type Transformable, then the NSValue rigmarole can be avoided for clients by providing accessors in an NSManagedObject subclass of the form:

Interface:

@property(assign, nonatomic) NSRange range;

Implementation;

- (NSRange) range {

    [self willAccessValueForKey:@"range"];
    NSRange retVal = range;
    [self didAccessValueForKey:@"range"];

    return retVal;
}

- (void)setRange:(NSRange)aRange {

    [self willChangeValueForKey:@"range"];
    range = aRange;
    [self didChangeValueForKey:@"range"];
}

Mogenerator's generated NSManagedObject subclasses, however, declare Transformable attributes as NSObject properties, so clients need to get/set NSValues.

What's the best way to handle this situation with mogenerator, whilst (1) keeping with the simple Transformable pattern rather than messing with transient backing attributes, and (2) avoiding any edits of Mogenerator's 'machine' classes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

゛时过境迁 2025-01-13 09:53:29

正如 scc 在之前接受的答案中建议的那样,处理此问题的最终方法是更改​​ mogenerator 模板文件。他们需要 (a) 将可转换属性的访问器更改为适当的类型(本例中为 NSRange),然后 (b) 使用适当的 KVO 方法调用添加访问器。

由于我现在没有时间弄清楚该怎么做,所以我的临时权宜之计如下:

  • 将 attributeValueClassName 键添加到属性的 userInfo 字典(在核心数据编辑器中),其值为 NSValue(只是为了确保生成器的访问器将是 NSValue 而不是 NSObject)。
  • 在人类可编辑的 mogenerator 输出中,添加与问题中类似的访问器,但使用新名称(例如 rangeValue 和 setRangeValue)除外。底层值仍然是持久的 NSValues,但我的访问器负责 KVO 和装箱/拆箱。

并不理想,但我确实获得了强类型访问器,而无需编辑 mogenerator 机器文件。

The ultimate way to deal with this would be, as scc suggested in the previously accepted answer, to change the mogenerator template files. They would need to (a) change the transformable attribute's accessor to be of the appropriate type (NSRange in this instance) and then (b) add the accessors with the appropriate KVO method calls.

As that's more than I have time right now to figure out how to do, my temporary expedient is as follows:

  • add an attributeValueClassName key to the attribute's userInfo dict (in the Core Data editor), with the value NSValue (just to make sure the generator's accessors will be NSValue rather than NSObject).
  • in the human-editable mogenerator output, add accessors like those in the question, except with a new name (eg. rangeValue and setRangeValue). The underlying values will still be the persisted NSValues, but my accessors take care of the KVO and boxing/unboxing.

Not ideal, but I do get strongly-typed accessors without having to edit the mogenerator machine files.

一生独一 2025-01-13 09:53:29

只需在模型对象生成器完成其工作后将类型从 NSObject 更改为您需要的任何类型即可。此后您不应该收到任何编译器警告。

顺便说一句,当我在定义可转换属性后运行托管对象模型生成器时,我没有得到 NSObject 而是 id 。没有警告。

Just change the type from NSObject to whatever type you need after the model object generator has finished its job. You should not have any compiler warnings after that.

BTW, when I run the managed object model generator after defining a transformable attribute I do not get NSObject but id. No warnings.

会发光的星星闪亮亮i 2025-01-13 09:53:29

您可以更改 mogenerator 使用的模板文件吗? (我认为)只要您远离标量值,您就可以安全地使用 NSObject * 而不是 id

Can you alter the template files that mogenerator uses? (I think) that provided you stay away from scalar values, you can safely use NSObject * instead of id.

十六岁半 2025-01-13 09:53:29

对于那些愿意编辑机器模板文件的人,请使用以下条件来处理可转换 NSRange 属性的特殊情况。

<$if Attribute.hasTransformableAttributeType && Attribute.objectAttributeClassName == "NSRange" 
gt;

以下是我更改机器模板头文件的方法。 https://gist.github.com/2414047

For those willing to edit the machine template file, use the following conditional to special case for the transformable NSRange attribute.

<$if Attribute.hasTransformableAttributeType && Attribute.objectAttributeClassName == "NSRange" 
gt;

Here's how I changed my machine template header file. https://gist.github.com/2414047

我ぃ本無心為│何有愛 2025-01-13 09:53:29

您正在阅读文档的错误部分。请查看此处

NSRange 不需要转换。所有这些基本结构都有一些方法,例如:

NSRangeFromString();
NSStringFromRange();

因此,您可以将影子属性定义为类似于 NSString 类型的“rangeAsString”。

在您的 MO 子类中,您将按照文档了解如何正确转换和存储该值,以便核心数据知道您的对象在执行以下操作时变脏:

myObject.range = NSMakeRange(0,5);

You are reading the wrong part of the documentation. Please look here:

NSRange doesn't need to be transformed. There are methods for all those basic structures, such as:

NSRangeFromString();
NSStringFromRange();

So you would define the shadow property as something like "rangeAsString" of type NSString.

In your MO subclass you would follow in the docs on how to properly convert and store the value so that core data knows your object became dirty when doing like:

myObject.range = NSMakeRange(0,5);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文