我正在使用 NSXMLParser 和 Core Data 来解析提要,并使用 iPhone 应用程序中的核心数据添加/更新实体。
问题是提要包含新数据和更新数据,因此一旦我解析提要,就会发生以下情况:
- 创建一个新实体
- 使用 NSXMLParser 填充实体属性
- 在 didEndElement 中,获取系统中已有的实体,其 myEntityId 等于我们解析的实体。
- 如果实体超过 1 个,则在 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;
}
}
}
发现角色
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if (self.currentProperty)
{
[currentProperty appendString:string];
}
}
我的问题是,保存更新信息似乎需要做很多工作,而且它总是创建一条新记录,而不仅仅是更新当前记录。
有没有办法让这个过程变得更简单,并避免在更新时创建新实体并删除旧实体?
任何建议都会很棒。
谢谢 丰富
最佳答案
我知道这是一篇旧帖子,但无论如何我都会回答。
您绝对应该查看 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 框架。只要您在数据模型的用户信息部分设置“latedByAttribute”,它就会自动将字典同步到您的托管对象。因此,如果您的对象有一个名为“MyEntityId”的唯一标识属性,则在实体集的用户信息字典中设置“latedByAttribute”-“MyEntityId”,MagicalRecord 会处理它。
如果您需要任何说明,请告诉我。
关于objective-c - 使用 NSXMLParser 和核心数据更新实体的功能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8482717/