user445929
user445929

Reputation:

How to use type-safe struct type Core Data attributes with 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?

Upvotes: 2

Views: 1235

Answers (5)

Lee Hericks
Lee Hericks

Reputation: 93

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

Upvotes: 0

yood
yood

Reputation: 6719

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" $>

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

Upvotes: 0

user445929
user445929

Reputation:

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.

Upvotes: 1

Scott Corscadden
Scott Corscadden

Reputation: 2860

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.

Upvotes: 0

Mundi
Mundi

Reputation: 80273

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.

Upvotes: 0

Related Questions