2011-10-31 2 views
0

Мое приложение использует Core Data и имеет атрибут «wasSeen». Когда пользователь обновляет приложение, все значения «wasSeen» 1 меняются на 0. На iPod Touch второго поколения с более чем 2000 объектами обновление занимает более минуты. Мой код выглядит следующим образом:Как эффективно сбрасывать атрибуты в объекте Core Data

for (Deck *deck in self.deckArray) { 
     if ([deck.beenSeen isEqualToNumber:[NSNumber numberWithInt:1]]) { 
      [deck setBeenSeen:[NSNumber numberWithInt:0]]; 
      [self.managedObjectContext save:&error];   
     } 
    } 

Я также рассматриваю возможность удаления SQLite файла и имеющее предупреждение попросить пользователь перезапустить приложение самостоятельно. Выполнение этой уверенности происходит намного быстрее, чем у меня сейчас. Есть ли более быстрый способ обновления объекта? Могу ли я создать резервную копию и скопировать ее? Спасибо за любую помощь.

ответ

1

Hm. Первая оптимизацией я бы предложил бы

for (Deck *deck in self.deckArray) { 
    if ([deck.beenSeen isEqualToNumber:[NSNumber numberWithInt:1]]) { 
     [deck setBeenSeen:[NSNumber numberWithInt:0]]; 
    } 
} 
[self.managedObjectContext save:&error];   

Я подозреваю, что это может ускорить процесс, чтобы сделать один большой контекст сохранить, а не 2000 маленьких.

Второе предложение - попытаться избавиться от теста if - если большинство ваших значений beenSeen меняются от 1 до 0, а остальные уже равно 0, тогда вы можете просто установить все из них на 0 и сохранить время проверки каждого из них отдельно. (С другой стороны, если есть 10000 объектов, и вы сбросить 2000 из них, а затем избавиться от теста не может быть оптимальным.)

for (Deck *deck in self.deckArray) { 
    [deck setBeenSeen:[NSNumber numberWithInt:0]]; 
    } 
    [self.managedObjectContext save:&error];   
} 

Третье предложение было бы подумать о реализации этого другого путь - например, ваш объект колоды мог реализовать атрибут lastSeen, сохраняя дату и время, когда последний раз видел колоду, а затем вместо массового сброса (и записи 2 000 строк основных данных) вы могли просто проверить дату колоды lastSeen и время против отметки времени последнего обновления пользователя.

+0

У вас все еще есть sav e внутри цикла. Думаю, ты собирался это выразить. –

+0

Исправлено - мое плохое. –

+0

Спасибо за легкое изменение. Время сократилось с 55 секунд до 6! – shohaku

1

Попробуйте, Во-первых, фильтровать массив, используя предикат:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"beenSeen == %@", 
          [NSNumber numberWithInt:1]]; 

NSArray* filtered = [self.deckArray filteredArrayUsingPredicate:predicate]; 

Теперь установите новое значение:

[filtered setValue:[NSNumber numberWithInt:0] forKeyPath:@"beenSeen"]; 

Наконец сохранить контекст:

[self.managedObjectContext save:&error]; 

Надежда это помогает :)

+0

Спасибо, это сработало отлично! Но я пойду с другим, потому что это было на 1 секунду быстрее. ;-) – shohaku

+0

Конечно, привет! вы попробовали [self.deckArray setValue: [NSNumber numberWithInt: 0] forKeyPath: @ "wasSeen"]; ?? – D33pN16h7

+0

Ха, это еще быстрее на 5.741 сек. Благодаря! Ваше первое решение было: 5.902 сек. Решение пользователя Scott: 5.785 sec. – shohaku

Смежные вопросы