Коллекция изменяемых строк в .plist, альтернативы?

Я создаю приложение, которое должно работать с категориями. будет базовый набор категорий, который я хочу предоставить с приложением, но пользователь может редактировать его (удалять, добавлять категории). базовый .plist не будет изменен, а будет прочитан только один раз, а затем сохранен как изменяемый в другом месте.

вот мой подход:

Категории по умолчанию поставляются в categoryCollection.plist с приложением. defaultCategories.plist будет новым файлом .plist, которым будут манипулировать

Стиль словаря по умолчаниюcategoryCollection.plist

чтобы прочитать категории в NSMutableSet я использую:

    NSString *mainBundlePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *dictPath = [mainBundlePath stringByAppendingPathComponent:@"defaultCategories"];
    NSDictionary * dict = [[NSDictionary alloc]initWithContentsOfFile:dictPath];

    // testing if the file has values, if not load from categoryCollection.plist
    if (dict.count == 0) {
        NSString *tempPath = [[NSBundle mainBundle] pathForResource:@"categoryCollection" ofType:@"plist"];
        dict = [NSMutableDictionary dictionaryWithContentsOfFile:tempPath];
        [dict writeToFile:dictPath atomically:YES];
    }

    // load into NSMutableSet
    [self.stringsCollection addObjectsFromArray:[[dict objectForKey:@"categories"]objectForKey:@"default"]];

чтобы добавить категорию, я вызываю эту функцию:

-(void)addCategoryWithName:(NSString *)name{

    NSString *mainBundlePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *dictPath = [mainBundlePath stringByAppendingPathComponent:@"defaultCategories"];
    NSMutableDictionary * dict = [[NSMutableDictionary alloc]initWithContentsOfFile:dictPath];
    [[[dict objectForKey:@"categories"]objectForKey:@"default"]addObject:name];

    [dict writeToFile:dictPath atomically:YES];

    self.needsToUpdateCategoryCollection = YES;
}

и чтобы удалить строку, которую я использую:

-(void)removeCategoryWithName:(NSString *)name{

    NSString *mainBundlePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    NSString *dictPath = [mainBundlePath stringByAppendingPathComponent:@"defaultCategories"];
    NSDictionary * dict = [[NSDictionary alloc]initWithContentsOfFile:dictPath];

    NSMutableArray *temp = [NSMutableArray arrayWithArray:[[dict objectForKey:@"categories"]objectForKey:@"default"]] ;

    for (NSString *string in temp) {
        if ([string isEqualToString:name]) {
            [temp removeObject:string];
            break;
        }
    }
    [[dict objectForKey:@"categories"]removeObjectForKey:@"default"];
    [[dict objectForKey:@"categories"] setValue:temp forKey:@"default"];


    [dict writeToFile:dictPath atomically:YES];
    self.needsToUpdateCategoryCollection = YES;
}

код на самом деле работает довольно хорошо, но мне интересно, действительно ли необходимы эти огромные накладные расходы на несколько операций ввода-вывода, тестов и т. д., или есть более элегантное решение для хранения набора строк и предоставления им возможности манипулировать?

или если вы видите какой-либо ускоритель, который может улучшить скорость (потому что я получаю небольшие задержки с этим кодом при наличии большого количества категорий)

Есть предположения? Себастьян


person Sebastian Flückiger    schedule 26.04.2012    source источник


Ответы (1)


Ваш подход работает нормально, но он выполняет больше работы, чем необходимо, записывая результаты каждый раз, когда коллекция изменяется. Запись файла является самой затратной частью ваших методов add и remove.

Одним из способов решения этой проблемы может быть чтение категорий при запуске приложения, кэширование NSMutableDictionary в объекте singleton и обращение к нему во время работы приложения. Когда конечные пользователи вносят изменения, вы обновляете словарь только в памяти; не записывайте данные в файл сразу.

В своем делегате приложения прослушайте событие applicationDidEnterBackground: и запишите данные в файл в этом обработчике. Также прослушайте событие applicationDidEnterForeground: и прочитайте свой файл в NSMutableDictionary. Это сэкономит вам много циклов ЦП и обеспечит более плавную работу конечного пользователя.

person Sergey Kalinichenko    schedule 26.04.2012
comment
работает просто отлично =) теперь производительность намного выше. Благодарность :) - person Sebastian Flückiger; 28.04.2012