iPhone - Запись NSMutableDictionary в файл - PullRequest
0 голосов
/ 19 марта 2011

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

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
self.favSaveFilePath = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:@"Favorites.plist"]];
if([fm fileExistsAtPath:favSaveFilePath])
{
    favoriteJokesDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:self.favSaveFilePath];
    favoriteJokes = [[NSMutableArray alloc] initWithArray:[self.favoriteJokesDictionary objectForKey:@"FavoriteJokes"]];
    return;
}

Я добавляю новый словарь в массив, как показано ниже:

-(BOOL)addJokeToFavorite:(NSDictionary*)joke
{
    BOOL success = NO;
    [self.favoriteJokes addObject:joke];
    success = [self.favoriteJokesDictionary writeToFile:self.favSaveFilePath atomically:YES];
    return success;
}

Я не знаю, почему не выжимать словарь в файл.Может ли кто-нибудь указать мне на ошибку, которую я делаю?

Ответы [ 4 ]

9 голосов
/ 19 марта 2011

API Какао очень точно определяет, какие значения могут быть юридически в словаре, когда они записаны в файл. Одно конкретное ограничение, которое, как известно, вызывает проблемы и которое подробно не обсуждается в официальной документации API, состоит в том, что все ключи в вашем словаре должны иметь тип NSString (и ваши значения должны быть одним из NSData, NSDate, NSNumber, NSString , NSArray или NSDictionary), хотя сам словарь поддерживает ключи и значения любого типа объекта.

Причина этого ограничения связана с тем фактом, что словарь по умолчанию хранится в виде XML-документа (или «список свойств» на языке Apple). Поэтому я бы порекомендовал проверить, соответствует ли ваш словарь требованиям для сохранения в файл, и реструктурировать его, если это не так.

Или, если реструктуризация вашего словаря неосуществима, вы можете вместо этого взглянуть на класс NSKeyedArchiver .

1 голос
/ 19 марта 2011

Я просто печатал это, когда Ульрих отправил правильный ответ. Остальное я добавлю сюда для дополнительного разъяснения.

Как указал Ульрих, когда у вас нет файла, ваш код просто пропускает инициализацию favoriteJokesDictionary и favoriteJokes. Когда вы пытаетесь выписать объект позже, favoriteJokesDictionary равен нулю, и поэтому метод ничего не делает.

Вы можете просто создать пустой NSMutableDictionary, если файл еще не существует, и, поскольку вы также сохраняете часть словаря в отдельном иваре, вы должны создать его одновременно. Примерно так будет работать:

NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
self.favSaveFilePath = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:@"Favorites.plist"]];
if([fm fileExistsAtPath:favSaveFilePath])
{
    favoriteJokesDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:self.favSaveFilePath];
    favoriteJokes = [[NSMutableArray alloc] initWithArray:[self.favoriteJokesDictionary objectForKey:@"FavoriteJokes"]];
} else {
    favoriteJokesDictionary = [[NSMutableDictionary alloc] init];
    favoriteJokes = [[NSMutableArray alloc] init];
    [favoriteJokesDictionary setObject:favoriteJokes forKey:@"JokesArrayKey"];
}

Тем не менее, я думаю, что вы, возможно, могли бы немного упростить свою модель данных там (если не будет происходить намного больше того, что вы не показываете). Если вам нужен словарь, потому что вы храните больше, чем просто шутки, то у вас все в порядке. Однако я бы не стал сохранять массив jokes, потому что если вы позже установите новый объект в массиве для вашего JokesArrayKey, ваш ivar-файл favourite Jokes все равно будет указывать на старый массив.

Я бы просто взял объект из словаря, когда бы он вам не понадобился:

NSMutableArray *jokes = [favoriteJokesDictionary objectForKey:@"JokesArrayKey"];

Еще лучше, если вы немного работаете с массивом jokes, просто извлеките его в свой собственный файл. Вы можете написать NSArray как список, как вы можете с NSDictionary. Если вы используете NSDictionary только как оболочку для записи .plist, вы можете полностью его пропустить.

Еще одна вещь: если ваше свойство favSaveFilePath помечено как «сохранить», в первом разделе вы обнаружите небольшую утечку памяти. Вы создаете новую сохраненную строку с [[NSString alloc] initWithString:...], а затем сохраняете ее снова, присваивая ее свойству. Вы, вероятно, просто хотите:

self.favSaveFilePath = [documentsDirectory stringByAppendingPathComponent:@"Favorites.plist"];
1 голос
/ 19 марта 2011

Похоже, ваш favoriteJokesDictionary вообще не существует, если нет файла сохранения, из которого его можно инициализировать. Следовательно, попытка создать этот файл сохранения из несуществующего словаря в addJokeToFavorite: тоже ничего не делает. Вам нужно создать пустой словарь, если для начала файла сохранения нет.

0 голосов
/ 22 февраля 2012

Ссылаясь на полученный ответ, объекты не-ns в вашем словаре могут быть более тонкими, чем вы думаете.Например: у меня было NSArray из NSDictionary объектов, которые я превращал в NSObject подклассы и добавлял их к NSMutableDictionary.Хотя подкласс содержит только объекты, строки и т. Д .;NSMutableDictionary сам не сохранит.

Решением было сохранить NSArray из NSDictionary элементов и превратить их в мой пользовательский подкласс после загрузки файла.

...