2009-08-07 14 views
12

Chcę przechowywać w NSMutableDictionary niektóre wartości null przy użyciu NSNull, a następnie serializować te dane za pomocą listy właściwości. Problem jest NSNull jest niedozwolony i pojawia się komunikat "Lista właściwości jest w nieprawidłowym formacie". Czy istnieje obejście tego problemu? Wydaje się bardzo zaskakujące, że nie umieścili NSNull na liście poprawnych obiektów plist.Jak serializować NSDictionary/NSArray/Property List (plist), która zawiera NSNull

+0

Odpowiedź udzielana przez Saurabh Wadhwa działa tak świetnie, po prostu używał go sam, szkoda, że ​​nie jest oryginalny plakat wokół to zaakceptować ... –

Odpowiedz

5

Nie, nie ma możliwości umieszczenia NSNull na liście właściwości. (Ciekawostka: format listy właściwości binarnych faktycznie obsługuje wartości null, ale program piszący nie obsługuje obsługi.)

W przypadku słownika najłatwiejszym rozwiązaniem jest po prostu odfiltrowanie wartości pustych, więc {foo = "bar"; baz = null; } staje się {foo = "bar"; }.

+0

To nie dokładnie to samo ponieważ potrzebuję wartości null, aby wskazać, że klucz istnieje, ale nie ma odpowiednich wartości (tj. już wiem, że istnieje klucz bez danych, w przeciwieństwie do nowego klucza, o którym nie wiem). –

+0

Być może możesz serializować zarówno A) słownik z tylko kluczami, które mają odpowiednią wartość, jak i B) tablicę wszystkich znanych kluczy, niezależnie od tego, czy mają one dołączone dane. Ostatecznie nie ma możliwości umieszczenia NSNull bezpośrednio w plist, więc musisz znaleźć obejście. –

3

Z dokumentacji NSPropertyListSerializationClass:

Lista właściwość obiektu. plist musi być rodzaj obiektu NSData, NSString, NSNumber, NSDate, NSArray lub NSDictionary . Obiekty kontenerów muszą również zawierać tylko te rodzaje obiektów.

Musisz mieć jedno z nich. W zależności od typu danych można wstawić symbol zastępczy zamiast NSNull, a następnie wykonać proces przed/po załadowaniu .plist (jak na przykład użycie obiektu NSData o zerowej długości do reprezentowania NSNull w plist). Dokładnie jaki rodzaj elementu zastępczego będzie zależny od rodzaju danych, które przechowujesz, i wyboru czegoś, czego chcesz uniknąć. Następnie, po załadowaniu, przetłumacz pustą NSData z powrotem na NSNull.

+0

Poważnie, co jest nie tak z programistami Apple? Nienawidzę pisać takiego kodu. –

+3

DD, jeśli chcesz serializacji ogólnej, użyj NSCoder. Listy właściwości mają ustalony zestaw typów, więc niezależnie od tego, jak daleko zostanie rozwinięty, zawsze będzie potrzeba przekonwertowania czegoś. –

+1

Jeśli nie lubisz ograniczeń list właściwości (które nie obsługują NSNull, jak wskazuje dokumentacja), nie używaj list właściwości. Jak sugeruje inny komentator, użyj własnego formatu serializacji. Wsparcie dla NSPropertyList! = Serializacja. – AlBlue

9

Zamiast korzystać z listy właściwości, należy rozważyć użycie NSKeyedArchiver i NSKeyedUnarchiver. Listy właściwości mają ustalony zestaw typów, który nie obejmuje NSNull i nie ma być rozszerzony.

Oto linki do odpowiedniej dokumentacji: NSCoding, NSKeyedArchiver i NSKeyedUnarchiver.

14

Konwertuję NSArray lub NSDictionary na NSData przed serializacją. Poniżej znajduje się kategoria nsarray do serializacji i deserializacji. Ten comfortableby obsługuje niektóre dane są 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

Bardzo dobrze! Zadziwiające jest to, że to działa (które właśnie zweryfikowaliśmy), gdy bardziej popularne metody w archiwizowanych archiwach nie działają. –

Powiązane problemy