我正在使用NSXMLParser和Core Data解析Feed并使用我的iPhone应用中的核心数据添加/更新实体。
问题是Feed包含新数据和更新数据,因此在解析Feed后会发生以下情况:
我的问题是保存更新信息似乎需要做很多工作,而且代码也总是创建一个新记录,而不仅仅是更新当前记录。
无论如何,这个过程可以变得更简单,并且在进行更新时无需创建新实体并删除旧实体吗?
我的缩写代码如下:
DidStartElement
- (void)parser:(NSXMLParser *)parser didStartElement...
{
if ([elementName isEqualToString:@"AnEntity"])
{
NSManagedObject *newEntity = [NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:_context];
self.currentEntityObject = newEntity;
} else
{
if ([elementName isEqualToString:@"Title"] || [elementName isEqualToString:@"MyEntityId"])
{
self.currentProperty = [NSMutableString string];
}
}
}
DidEndElement
- (void)parser:(NSXMLParser *)parser didEndElement...
{
if (self.currentEntityObject)
{
if ([elementName isEqualToString:@"Title"])
{
[self.currentEntityObject setValue:self.currentProperty forKey:@"title"];
} else if ([elementName isEqualToString:@"MyEntityId"])
{
[self.currentEntityObject setValue:self.currentProperty forKey:@"myEntityId"];
} else if ([elementName isEqualToString:@"AnEntity"])
{
[self.currentEntityObject setValue:[NSDate date] forKey:@"lastUpdated"];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"MyEntity" inManagedObjectContext:_context];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(myEntityId = %@)", [self.currentEntityObject valueForKey:@"myEntityId"]];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *array = [_context executeFetchRequest:request error:&error];
int countOfEntityId = array.count;
if (array != nil && countOfEntityId > 1)
{
// This is an update so remove old versions
for(int i=0; i < countOfEntityId; i++)
{
if(self.currentEntityObject != [array objectAtIndex:i])
{
[_context deleteObject:[array objectAtIndex:i]];
}
}
}
error = nil;
[_context save:&error];
self.currentEntityObject = nil;
}
}
}
FoundCharacters
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.currentProperty)
{
[currentProperty appendString:string];
}
}
我的问题是保存更新信息似乎需要做很多工作,而且它总是会创建一条新记录,而不仅仅是更新当前记录。
无论如何,这个过程可以变得更简单,并且在进行更新时无需创建新实体并删除旧实体吗?
任何建议都会很棒。
由于 富
答案 0 :(得分:1)
我意识到这是一个很老的帖子,但无论如何我都会回答。
你一定要查看Saul Mora的MagicRecord。他在任何项目中都很容易使用它,自动与ARC /非ARC一起使用,而CoreData的设置是一个单行程。
首先,我将向您展示我如何解析和更新。
- (void)setUpBeforeParsing
{
self.currentAttributes = [NSMutableDictionary dictionary];
self.currentParsedCharacterData = [NSMutableString string];
self.currentParsedBatch = [NSMutableArray array];
self.attributesDictionary = myManagedObjectObject.entity.attributesByName;
}
- (void)parser:(NSXMLParser *)parser didStartElement...
{
for (NSString *attribute in self.attributesDictionary)
{
if ([elementName isEqualToString:attribute])
{
accumulatingParsedCharacterData = YES;
[self.currentParsedCharacterData setString:@""];
}
}
}
- (void)parser:(NSXMLParser *)parser didEndElement...
{
if ([elementName isEqualToString:@"myIdentifierThatObjectIsDone"])
{
[self.currentParsedBatch addObject:[self.currentAttributes copy]];
[self.currentAttributes removeAllObjects];
accumulatingParsedCharacterData = NO;
}
for (NSString *attribute in self.attributesDictionary)
{
if ([elementName isEqualToString:attribute])
{
accumulatingParsedCharacterData = NO;
[self.currentAttributes setObject:[self.currentParsedCharacterData copy] forKey:attribute];
}
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.accumulatingParsedCharacterData) [self.currentParsedCharacterData appendString:string];
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
[MyCoreDataClass MR_importFromArray:self.currentParsedBatch];
}
最重要的是,您可以构建一个字典数组,其中包含您要传输到托管对象的值。一个名叫Tom Harrington的人在cimgf.com上写了一个关于命名对象属性的演示,就像返回的xml或json一样,然后你可以简单地遍历你的属性,直到它与返回的xml元素匹配。这里的美妙之处在于您想要将更多返回的xml保存到对象中,只需向对象添加属性,解析器就会自动同步它。
在解析结束时,您会注意到一个名为的类方法,它来自MagicalRecord框架。只要在数据模型的用户信息部分中设置“relatedByAttribute”,它就会自动将字典同步到您的托管对象。因此,如果您的对象具有名为“MyEntityId”的唯一标识属性,则在您的实体集'relatedByAttribute'的用户信息字典中 - 'MyEntityId'和MagicalRecord负责处理它。
如果您需要任何澄清,请告诉我。