【问题标题】:Functionality for Updating Entities Using NSXMLParser and Core Data使用 NSXMLParser 和核心数据更新实体的功能
【发布时间】:2012-01-18 22:37:45
【问题描述】:

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

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

  1. 创建一个新实体
  2. 使用 NSXMLParser 填充实体属性
  3. 在 didEndElement 中,获取系统中已有的实体,其中 myEntityId 等于我们解析的实体。
  4. 如果实体超过 1 个,则删除旧实体,因为提要向我们传递了新数据。
  5. 保存实体

我的问题是保存更新信息似乎需要做很多工作,而且代码也总是会创建新记录,而不仅仅是更新当前记录。

无论如何,这个过程是否可以变得更简单,避免在更新时创建新实体并删除旧实体?

我的缩写代码如下:

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

DidEnd元素

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

我的问题是,保存更新信息似乎需要做很多工作,而且它总是会创建一条新记录,而不仅仅是更新当前记录。

无论如何,这个过程是否可以变得更简单,避免在更新时创建新实体并删除旧实体?

任何建议都会很棒。

谢谢 丰富

【问题讨论】:

    标签: objective-c ios xcode core-data nsxmlparser


    【解决方案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 会处理它。

    如果您需要任何说明,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      • 1970-01-01
      相关资源
      最近更新 更多