开发者

NSManagedObject outside of a managedObjectContext

开发者 https://www.devze.com 2023-02-20 12:09 出处:网络
I\'ve seen others asking about how to use an NSManagedObject outside of the managedObjectContext. Seems like everyone says you should not do this, but I can\'t find information on what to do instead.

I've seen others asking about how to use an NSManagedObject outside of the managedObjectContext. Seems like everyone says you should not do this, but I can't find information on what to do instead.

I'm essentially trying to do two different things with the data that is set on my NSManagedObject. I want to save it to the persistentStore, and I want to send it to a remote server. My idea was to alloc/init an instance of my NSManagedObject, populate it's properties, then pass that to an function where those properties would be transferred to a properly instantiated NSManagedObject, and then to pass it to another function that would be responsible for sending the data to a server.

In code: (Event is a subclass of NSManagedObject)

// in my view controller
Event *event = [Event alloc] init];
event.propertyA = @"foo";
event.propertyB = @"bar";

[self logEvent:event];
[self sendEvent:event];

-----------------------------------

// method in view controller 
- (void)logEvent(Event *)event {
    // my thought was to take the event that I manually created, and use it to
    // set the properties on the Event object in the managedObjectContext.

    Event *eventEntity = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:self.managedObjectContext];

    eventEntity.propertyA = event.propertyA;
    eventEntity.propertyB = event.propertyB;
    ...
    [self.managedObjectContext save:&error];
}

- (void) sendEvent:(Event *)event {
    // send exact same event properties to remote server
}

As you'd expect, this is failing on the second line, where I try to set propertyA.

What should I do instead? Should I create a vanilla subclass of NSObject that has the exact same attributes/properties as my NSManagedObject object? The proposed solution in the question I linked to talks about NSInMemoryStoreType, but that ju开发者_JS百科st seems overkill when all I really want is a convenient way to pass around an object. It's just that in this case, my object is an NSManagedObject, so I'm limited in what I can do with it.


I wrote a category on NSManagedObject a while ago that creates an NSDictionary representation of the managed object. You can use the NSDictionary outside of the managed object context. Disclaimer: this code hasn't been thoroughly tested, and also note that it only handles the attributes of the managed object and does not handle relationships.

NSManagedObject+CLDAdditions.h
------------------------------

@interface NSManagedObject (CLDAdditions)
- (NSDictionary*)cld_dictionaryRepresentation;
@end

NSManagedObject+CLDAdditions.m
------------------------------

@implementation NSManagedObject (CLDAdditions)

- (NSDictionary*)cld_dictionaryRepresentation
{
    // Create empty dictionary
    NSMutableDictionary *objectDictionary = [NSMutableDictionary dictionary];
    // Set the entity
    [objectDictionary setObject:[[self entity] name] forKey:@"entity"];
    NSDictionary *attributeKeys = [[self entity] attributesByName];
    // Go through each of the attributes and add them to the dictionary
    for (NSString *attributeKey in attributeKeys) {
        id attributeValue = [self valueForKey:attributeKey];
        if (attributeValue) {
            // Supported objects
            if ([attributeValue isKindOfClass:[NSNumber class]] || [attributeValue isKindOfClass:[NSString class]] || [attributeValue isKindOfClass:[NSNull class]] || [attributeValue isKindOfClass:[NSDate class]] || [attributeValue isKindOfClass:[NSData class]] || [attributeValue isKindOfClass:[NSURL class]]) {
                [objectDictionary setObject:attributeValue forKey:attributeKey];
            // Unsupported objects
            } else if ([attributeValue isKindOfClass:[NSDictionary class]] || [attributeValue isKindOfClass:[NSArray class]]) {
                [NSException raise:NSGenericException format:@"Objects of type \"%@\" are not supported as Core Data attributes.", [attributeValue class]];
            // Transformable objects (conforming to NSCoding)
            // TODO: Add support for custom value transformers
            } else if (([[attributeKeys objectForKey:attributeKey] attributeType] == NSTransformableAttributeType) && [attributeValue conformsToProtocol:@protocol(NSCoding)]) {
                NSData *attributeData = [NSKeyedArchiver archivedDataWithRootObject:attributeValue];
                [objectDictionary setObject:attributeData forKey:attributeKey];
            // Otherwise raise an exception
            } else {
                [NSException raise:NSGenericException format:@"Unsupported object type \"%@\". Objects must conform to the NSCoding protocol.", [attributeValue class]];
            }
        }
    }
    return objectDictionary;
}

@end
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号