2009-08-07 3 views
12

Я хочу сохранить в NSMutableDictionary несколько нулевых значений, используя NSNull, а затем сериализуем эти данные, используя список свойств. Проблема NSNull не разрешена, и я получаю ошибку «Список свойств в недопустимом формате». Есть ли обходной путь для этого? Кажется очень удивительным, что они не положили NSNull в список действительных объектов plist.Как сериализовать NSDictionary/NSArray/Список свойств (plist), который содержит NSNull

+0

Ответ предоставляется Saurabh Wadhwa работает просто замечательно, я просто использовал это сам, слишком плохо оригинального плаката не вокруг, чтобы принять его ... –

ответ

5

Нет, не существует способа разместить NSNull в списке объектов. (Trivia: формат списка бинарных свойств фактически поддерживает нули, но писатель не реализует поддержку.)

Для словаря самым простым обходным путем является простое отбрасывание нулевых значений, поэтому {foo = "bar"; baz = null; } становится {foo = "bar"; }.

+0

Это не одно и то же так как мне нужны нулевые значения, чтобы указать, что ключ существует, но не имеет соответствующих значений (т. е. я уже знаю, что есть ключ без данных, а не его новый ключ, о котором я не знаю). – 2009-08-07 12:54:57

+0

Возможно, вы могли бы сериализовать как A) словарь с помощью только ключей, имеющих соответствующее значение, так и B) массив всех известных ключей, независимо от того, имеют ли они данные. В конечном счете, невозможно напрямую установить NSNull в plist, поэтому вам нужно найти обходной путь. –

3

Из документации NSPropertyListSerializationClass:

Объект списка свойств. plist должен быть вид NSData, NSString, NSNumber, NSDate, NSArray или NSDictionary объект. Контейнерные объекты также должны содержать только такие объекты.

Поэтому у вас должен быть один из них. В зависимости от типа данных вы можете помещать заполнитель вместо NSNull, а затем выполнять процесс до/после загрузки .plist (например, используя объект NSData с нулевой длиной для представления вашего NSNull в plist). Именно то, что заполнитель будет зависеть от того, какие данные вы храните, и выбирая что-то, чего следует избегать. Затем, после загрузки, переведите пустой NSData обратно в NSNull.

+0

Серьезно, что не так с программистами Apple ??? Мне не нравится писать такой код. – 2009-08-07 12:53:22

+3

DD, если вам нужна общая сериализация, используйте NSCoder. Списки свойств имеют фиксированный набор типов, поэтому независимо от того, насколько далеко он расширен, всегда будет необходимо что-то конвертировать. –

+1

Если вам не нравятся ограничения списков свойств (которые не могут поддерживать NSNull, как указано в документации), не используйте списки свойств. Как предлагает другой комментатор, используйте свой собственный формат сериализации. Поддержка NSPropertyList! = Сериализация. – AlBlue

9

Вместо использования списка свойств рассмотрите использование NSKeyedArchiver и NSKeyedUnarchiver. Списки свойств имеют фиксированный набор типов, и это не включает NSNull, и он не предназначен для расширения.

Здесь приведены ссылки на соответствующую документацию: NSCoding, NSKeyedArchiver и NSKeyedUnarchiver.

14

Я конвертирую NSArray или NSDictionary в NSData перед сериализацией. Ниже приведена категория nsarray для сериализации и десериализации. Это comfortableby обрабатывает некоторые данные будучи nsnull

@implementation NSArray(Plist) 

-(BOOL)writeToPlistFile:(NSString*)filename{ 
    NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self]; 
    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString * documentsDirectory = [paths objectAtIndex:0]; 
    NSString * path = [documentsDirectory stringByAppendingPathComponent:filename]; 
    BOOL didWriteSuccessfull = [data writeToFile:path atomically:YES]; 
    return didWriteSuccessfull; 
} 

+(NSArray*)readFromPlistFile:(NSString*)filename{ 
    NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
    NSString * documentsDirectory = [paths objectAtIndex:0]; 
    NSString * path = [documentsDirectory stringByAppendingPathComponent:filename]; 
    NSData * data = [NSData dataWithContentsOfFile:path]; 
    return [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
} 
+0

Очень хорошо! Удивительно, что это работает (что я только что проверил), когда более распространенные методы в ключах нет. –

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