Как сохранить строку в виде массива в списке свойств Cocoa?

Я пытаюсь сохранить две строки. Одна строка должна быть сохранена как тип ARRAY в pList, а вторая строка должна быть сохранена как String в массиве.

Я могу использовать код:

[словарь setObject:(id)anObject forKey:(id)aKey>]

но он не сохраняет его правильно. Я могу преобразовать одну из строк в массив, но она все равно работает неправильно.

Каков правильный метод сохранения массива в pList?

Вот как выглядит мой pList:

<dict>
<key>Test One</key>
<array>
    <string>A13#</string>
</array>
<key>Another Test</key>
<array>
    <string>1111111111</string>
</array>
<key>Test Three</key>
<array>
    <string>2222222222</string>
</array>
<key>Final Test</key>
<array>
    <string>3333333333</string>
</array>
</dict>

вот метод, который я использую, чтобы попытаться

-(void)writeToFile:(NSString *)s1{
    NSBundle *bundle = [NSBundle mainBundle];
NSString *plistPath = [bundle pathForResource:@"saved" ofType:@"plist"];

NSMutableDictionary *dictionary = [[[NSDictionary alloc] initWithContentsOfFile:plistPath] mutableCopy];
NSString *tempString = [NSString stringWithFormat:@"1234567"];
[dictionary setObject:tempString forKey:s1];

[dictionary writeToFile:plistPath atomically:YES];
}

person Community    schedule 09.06.2009    source источник
comment
Что вы подразумеваете под сохранением строки в виде массива?   -  person dreamlax    schedule 10.06.2009


Ответы (3)


Вы не можете привести или иным образом преобразовать строку в массив; это отдельные, отличные объекты. Это то же самое, как если бы в реальной жизни вы попытались превратить свою собаку в универсал, этого не происходит.

Вместо этого поместите свою собаку внутрь универсала (или поместите свою веревку(и) внутрь массива). Вы можете создать массив с помощью [NSArray arrayWithObjects:@"string1", @"string2", nil];. Вставьте это в свой словарь для данного ключа вместе с вашей окончательной строкой для другого ключа, сохраните ее, и у вас будет plist с массивом из одной или нескольких строк.

Кроме того, в вашем примере кода в вашем словаре происходит утечка памяти. Прочитайте об управлении памятью в Objective-C, вы столкнетесь с множеством сбоев и проблем с производительностью, пока не поймете это хорошо.

person Marc Charbonneau    schedule 09.06.2009
comment
Фактически, вы не можете преобразовать ЛЮБОЙ объект из одного класса в другой. - person Chuck; 10.06.2009
comment
Неправда, вы можете, если объект, который вы приводите, действительно может вести себя как класс, к которому он приводится. Например, предположим, что у вас есть объект NSMutableArray, хранящийся в указателе NSArray* array. Если вы попытаетесь вызвать для него -removeLastObject, компилятор будет использовать статическую типизацию и сообщит вам, что NSArray не будет отвечать на это сообщение. Однако вы можете сделать так, чтобы [(NSMutableArray*)array removeLastObject] just fine. You'll run into problems if array` на самом деле был NSArray, или если вы приводите объект, хранящийся в переменной id, к несовместимому классу, например строки к массивам. - person Quinn Taylor; 11.06.2009

Вы конвертируете строку в массив из одного элемента с помощью

[NSArray arrayWithObject:str];

Итак, если вы хотите, чтобы ваш plist содержал записи в виде массивов строк, и вам нужна только одна строка в качестве элемента, вы делаете что-то вроде:

[dictionary setObject:[NSArray arrayWithObject:tempString] forKey:s1];

На самом деле я не понимаю, почему вам это нужно, если вы не хотите разрешить несколько строк для каждого ключа в другое время.

Кроме того, как упоминал Марк, вы пропускаете исходный (неизменяемый) словарь, который вы создаете. Ознакомьтесь с правилами управления памятью на странице http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html.

Кроме того, вы никогда не должны писать внутри пакета вашего приложения. Во-первых, ваше приложение может находиться на томе, защищенном от записи, или у текущего пользователя может не быть прав на его изменение. Во-вторых, файл будет доступен всем пользователям. И в-третьих, это нарушит подписывание кода. Вместо этого запишите файл либо в папку «Настройки», либо в папку «Поддержка приложений».

И, наконец, если они предназначены для каких-то пользовательских настроек, то вам следует использовать систему настроек, которая позволяет настраивать значения по умолчанию и сохранять настройки в папке настроек для вас. См. http://developer.apple.com/documentation/Cocoa/Conceptual/UserDefaults/UserDefaults.html для получения дополнительной информации.

person Peter N Lewis    schedule 10.06.2009

Правильный способ сохранить NSArray (сам по себе) в файл plist выглядит следующим образом:

NSArray* anArray = ...;
[anArray writeToFile:@"/path/to/file.plist" atomically:YES];

Однако вы не можете сохранить NSString как массив. Учитывая предоставленный вами список XML, если вы хотите добавить записи в том же формате, вы можете использовать этот гораздо более простой код:

- (void) writeToFile:(NSString *)string {
  NSString *plistPath = [[NSBundle mainBundle] pathForResource:@"saved" ofType:@"plist"];
  NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
  [dictionary setObject:[NSArray arrayWithObject:@"1234567"] forKey:string];
  [dictionary writeToFile:plistPath atomically:YES];
}

Это также предотвращает утечку памяти в вашем коде, когда получатель -mutableCopy убегает со счетчиком сохранения, равным 1. (Это не проблема в GC, но все же это плохая практика.) Вам не нужно использовать +[NSString stringWithFormat:], просто используйте строковый литерал. Если вы хотите использовать другую строку в качестве строки в массиве, вы можете либо передать ее в качестве дополнительного параметра, либо получить ее из другого метода и т. д.

Этот метод по-прежнему ненадежен в том смысле, что он хранит в массиве только одну строку, совпадающую с заданным ключом. Кроме того, имя метода было бы лучше, если бы оно более точно указывало на то, что он делает. Кроме того, если для каждого ключа всегда будет только одно строковое значение, вы можете рассмотреть возможность пересмотра plist, чтобы полностью исключить массивы, поскольку это только занимает место и усложняет код.

person Quinn Taylor    schedule 11.06.2009
comment
Обратите внимание, что в этом случае, хотя +dictionaryWithContentsOfFile является удобным конструктором в NSDictionary, он наследуется NSMutableDictionary и возвращает экземпляр класса-приемника. Это работает для других изменяемых/неизменяемых классов в Foundation, таких как NS(Mutable)String, NS(Mutable)Array и т. д. - person Quinn Taylor; 11.06.2009