2009-10-30 6 views
8

Ho cercato di ottenere il NSKeyedArchiver di scrivere i miei dati in un formato leggibile (cioè non come un file binario) ho capito che posso usare ...NSKeyedArchiver scrive XML (o altri documenti leggibili dall'uomo)?

setOutputFormat: NSPropertyListXMLFormat_v1_0 

Ma ... Ho appena non riesco a trovare la sintassi giusta, qualcuno può indicarmi la giusta direzione?

NSData *artistData; 

NSLog(@"(*) - Save All"); 
artistData = [NSKeyedArchiver archivedDataWithRootObject:artistCollection ]; 
[artistData writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES]; 

EDIT

I setOutputFormat aggiunto (vedi sotto), ma ho ricevuto un avviso in fase di compilazione, cosa mi manca?

warning: NSData may not respond to 'setOutputFormat:' 

Ecco il codice che ho usato.

NSLog(@"(*) - Save All"); 
artistData = [NSKeyedArchiver archivedDataWithRootObject:artistCollection ]; 
[artistData setOutputFormat: NSPropertyListXMLFormat_v1_0]; 
[artistData writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES]; 

Gary

risposta

17

Questo è ciò che devi fare:

NSMutableData *data = [NSMutableData data]; 
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 
[archiver setOutputFormat:NSPropertyListXMLFormat_v1_0]; 
[archiver encodeObject:artistCollection forKey:@"root"]; 
[archiver finishEncoding]; 
[data writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES]; 
[archiver release]; 

Si noti che è must uso [archiver encodeObject:artistCollection forKey:@"root"] invece di [archiver encodeRootObject:artistCollection]; come suggerito da Sean. Questo perché NSKeyedArchiver non sovrascrive il metodo encodeRootObject: NSCoder. Considero questo un bug e lo segnalerò ad Apple.

Ora, la vera domanda è perché vuoi scrivere XML invece del formato binario predefinito? Se è per scopi di debug, ti suggerisco di utilizzare TextWrangler che ti consentirà di modificare in modo trasparente i file plist binari come se fossero XML.

+0

Ah è così, sia tu che Sean, sottolineo che stavo usando il metodo di classe piuttosto che creare un'istanza, questo è sicuramente il posto dove stavo sbagliando. Anche il tuo diritto, la mia ragione principale era di aiutare a eseguire il debug di ciò che stava effettivamente accadendo nel file, la visualizzazione con BBEdit o TextWrangler è perfetta per quello di cui ho bisogno. Molto apprezzato. – fuzzygoat

+0

+1 per suggerire TextWrangler. Non sapevo che potesse leggere il formato binario! –

+0

La parte TextWrangler di questa risposta è fantastica. Sicuramente ho risparmiato un sacco di sforzi - non avevo idea che potesse farlo! – savvyx4

0
[artistData setOutputFormat: NSPropertyListXMLFormat_v1_0]; 
+2

'setOutputFormat:' è un metodo NSKeyedArchiver. L'invio di un messaggio di questo tipo a un oggetto NSData non funzionerà. –

+0

quindi dovrei guardare qualcosa come [NSKeyedArchiver setOutputFormat: NSPropertyListXMLFormat_v1_0]; Non sono al mio computer in questo momento, avrò un aspetto migliore stasera. – fuzzygoat

+0

fuzzygoat: No, perché 'setOutputFormat:' è un metodo di istanza, quindi non sarà possibile inviarlo alla classe NSKeyedArchiver. È necessario creare un'istanza di NSKeyedArchiver e inviare il messaggio a questo. –

1

'archivedDataWithRootObject:' è un metodo di classe, che 'setOutputFormat' è un metodo di istanza. Dalla documentazione di 'archivedDataWithRootObject:':

Un oggetto NSData contenente la forma codificata del grafico oggetto il cui oggetto radice è rootObject. Il formato dell'archivio è NSPropertyListBinaryFormat_v1_0.

Quello che dovete fare è creare un NSKeyedArchiver e codificare l'oggetto radice. Inoltre, assicurati che tutti i contenuti della tua raccolta implementino 'encodeWithCoder' e 'initWithCoder'. Vedi Encoding and Decoding Objects

Il problema con questo approccio è che devi assegnare manualmente le chiavi per ogni oggetto che codifichi, che non suona come quello che vuoi, dal momento che hai già una collezione. Sia gli array che i dizionari contengono metodi per scrivere in un file xml, che è un approccio molto più semplice.

[artistCollection writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES]; 

discussione su questo metodo (per entrambi NSDictionary e NSArray):

Se il contenuto del ricevitore sono tutti oggetti lista proprietà (NSString, NSData, NSArray, o oggetti NSDictionary), il file scritto da questo metodo può essere utilizzato per inizializzare un nuovo array con il metodo di classe arrayWithContentsOfFile: o il metodo di istanza initWithContentsOfFile :. Questo metodo convalida in modo ricorsivo che tutti gli oggetti contenuti sono oggetti di elenchi di proprietà prima di scrivere il file e restituisce NO se tutti gli oggetti non sono oggetti di elenco di proprietà, poiché il file risultante non sarebbe un elenco di proprietà valido. Blockquote

+0

Le classi di elenchi di proprietà sono tutte codificabili e puoi codificare una raccolta che contiene oggetti non di proprietà, mentre non puoi creare dati di elenchi di proprietà da una sola. –

2

devi prima creare un'istanza di NSKeyedArchiver invece di utilizzare il metodo di classe a portata di mano che restituirà solo NSData.

NSMutableData *data = [NSMutableData new]; 
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 

// set the one property you specifically wanted 
[archiver setOutputFormat:NSPropertyListXMLFormat_v1_0]; 

// now encode (and finalize) the actual object - note that encodeRootObject: is inherited 
// from NSCoder. I assume this works :) 
[archiver encodeRootObject:artistCollection]; 
[archiver finishEncoding]; 

// now finally write it out - the resulting encoded stuff should be waiting in the data object 
[data writeToFile:@"/Users/fgx/Desktop/stuff" atomically:YES]; 

// cleanup after ourselves 
[archiver release]; 
[data release]; 

Disclaimer: Ho scritto questo codice nella casella di input qui e in realtà non provarlo.

+0

Non usare '[archiver encodeRootObject: artistCollection];' Per favore, leggi la mia risposta per capire perché. – 0xced

Problemi correlati