Objective c 使用NSXMLParser和核心数据更新实体的功能

Objective c 使用NSXMLParser和核心数据更新实体的功能,objective-c,ios,xcode,core-data,nsxmlparser,Objective C,Ios,Xcode,Core Data,Nsxmlparser,我正在使用NSXMLParser和Core数据解析提要,并在我的IPhone应用程序中使用核心数据添加/更新实体 问题在于提要包含新的和更新的数据,因此一旦我解析提要,就会发生以下情况: 创建一个新实体 使用NSXMLParser填充实体属性 在DiEndElement中,获取系统中已经存在的myEntityId等于我们解析的实体的实体 如果有多个实体,那么在提要向我们传递新数据时删除旧实体 保存实体 我的问题是,保存更新信息似乎需要做很多工作,代码也总是创建一个新记录,而不仅仅是更新当前记录

我正在使用NSXMLParser和Core数据解析提要,并在我的IPhone应用程序中使用核心数据添加/更新实体

问题在于提要包含新的和更新的数据,因此一旦我解析提要,就会发生以下情况:

  • 创建一个新实体
  • 使用NSXMLParser填充实体属性
  • 在DiEndElement中,获取系统中已经存在的myEntityId等于我们解析的实体的实体
  • 如果有多个实体,那么在提要向我们传递新数据时删除旧实体
  • 保存实体
  • 我的问题是,保存更新信息似乎需要做很多工作,代码也总是创建一个新记录,而不仅仅是更新当前记录

    是否可以简化此过程,避免在执行更新时创建新实体和删除旧实体

    我的缩写代码如下:

    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];
        }  
      }
    }
    
    双端元素

    - (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;
        }
      }
    }
    
    我的问题是,保存更新信息似乎需要做很多工作,而且它总是创建一个新记录,而不仅仅是更新当前记录

    是否可以简化此过程,避免在执行更新时创建新实体和删除旧实体

    任何建议都很好

    谢谢
    Rich

    我意识到这是一篇老文章,但无论如何我都会回答

    你绝对应该看看索尔·莫拉的。他使其在任何项目中都非常容易使用,可以自动使用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会处理它

    如果您需要任何澄清,请告诉我

    - (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];
    }