Функциональность для обновления сущностей с использованием NSXMLParser и Core Data - PullRequest
0 голосов
/ 13 декабря 2011

Я использую 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];
    }  
  }
}

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

Моя проблема в том, что сохранение информации об обновлении кажется огромной работой, а также всегда создает новую запись, а не просто обновляет текущую запись.

В любом случае можно ли упростить этот процесс и избежать необходимости создавать новый объект и удалять старый при обновлении?

Любой совет был бы великолепен.

Спасибо Рич

1 Ответ

1 голос
/ 02 ноября 2012

Я понимаю, что это старый пост, но я все равно отвечу.

Вы обязательно должны проверить MagicRecord Саула Моры.Он сделал его простым в использовании в любом проекте, автоматически работает с ARC / non-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];
}

На самом деле главное, что вы можете сделать из этого, это то, что вы можете создать массив словарей, которые содержат значения, которые выхотите перенести в ваши управляемые объекты.Парень по имени Том Харрингтон написал на cimgf.com демо-версию о присвоении имен свойствам вашего объекта так же, как возвращенные xml или json, и затем вы можете просто перебирать свои свойства, пока они не будут соответствовать возвращенному элементу xml.Прелесть здесь в том, что где-то внизу строки вы хотите сохранить больше возвращенного XML-кода в ваши объекты, просто добавьте свойство к вашему объекту, и парсер автоматически синхронизирует его.

В конце анализа вы будетеобратите внимание на метод класса, который называется, это из среды MagicalRecord.Пока вы устанавливаете 'relatedByAttribute' в информационной части пользователя вашей модели данных, он будет автоматически синхронизировать словари с вашими управляемыми объектами.Поэтому, если ваши объекты имеют уникальное идентифицирующее свойство, называемое «MyEntityId», то в пользовательском информационном словаре вашего набора сущностей «relatedByAttribute» - «MyEntityId» и MagicalRecord позаботится об этом.

Дайте мне знать, если вам нужноуточнение.

...