2011-12-07 29 views
7

Tengo una aplicación sencilla relativley que persiste datos en un archivo plist ubicado en la carpeta de documentos. Los datos se cargan en un UITableView al inicio. El usuario puede editar, eliminar o agregar registros y los cambios se guardan en el archivo plist.Compartiendo un archivo plist utilizando iCloud

Ahora me gustaría compartir estos datos (el archivo plist) en todos los dispositivos usando iCloud. He revisado la documentación y tengo entendido que necesito crear un UIDocument para "administrar" el archivo plist.

He visto varios tutoriales de iCloud, pero todos almacenan una cadena simple dentro de una propiedad en la clase UIDocument, no un archivo completo (como un plist).

¿Cómo comparto mi archivo plist (o cualquier otro archivo, para el caso) a iCloud usando el objeto UIDocument?

¿Convertiría el contenido del archivo plist a NSData, y luego lo guardaría en una propiedad en el UIDocument? ¿Debería usar NsFileWrapper?

Parece que me está resultando difícil entender lo que ocurre con el arreglo UIDocument/iCloud. Probablemente estoy haciendo esto más complicado de lo que realmente es.

+0

¿Encontró una respuesta para esto? Estoy buscando hacer lo mismo y mi aplicación suena muy similar a la tuya. Por favor, avíseme si encontró un buen tutorial. – Jackson

+0

También estoy tratando de lograr esto.He estado modificando el tutorial con NSString, pero no puedo obtener el segundo dispositivo para ver los datos. – zambono

+0

ídem. +1 al poster – autodidakto

Respuesta

1

Para usar un plist con UIDocument, puede subclase UIDocument y anular los siguientes 2 métodos con self.myDictionary (su plist) declarado como NSMutableDictionary.

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError **)outError 
{  
    if ([contents length] > 0) 
    { 
     NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:(NSData *)contents]; 
     NSMutableDictionary *dataDictionary = [unarchiver decodeObjectForKey:@"data"]; 

     self.myDictionary = dataDictionary; 
     [unarchiver finishDecoding]; 
     [unarchiver release]; 
    } 
    else 
    { 
     self.myDictionary = [NSMutableDictionary dictionary]; 
    } 

    return YES;  
} 

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError 
{ 
    NSMutableData *data = [[[NSMutableData alloc] init] autorelease]; 
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 
    if(!self.myDictionary) 
    { 
     self.myDictionary = [NSMutableDictionary dictionary]; 
    } 
    [archiver encodeObject:self.myDictionary forKey:@"data"]; 

    [archiver finishEncoding]; 
    [archiver release]; 
    return data; 
} 
+0

Esto no crea una lista de diccionario, crea una lista de archivos, pero está lo suficientemente cerca. Para crear un plist real, use NSPropertyListSerialization y puede elegir entre xml o salida binaria. – malhal

+0

También las listas de archivos no son compatibles entre Mac e iOS. – malhal

7

No estoy seguro de si alguien todavía necesita una solución para eso, pero encontré una buena manera de hacer que esto funcione.

Dado que UIDocument solo acepta datos como NSData o NSFilewrapper, primero creé una Categoría para la clase NSDictionary que devuelve un NSDictionary de NSData. Aquí están los dos archivos para la categoría:

NSDictionary + DictFromData.h:

#import <Foundation/Foundation.h> 

@interface NSDictionary (DictFromData) 
+ (id)dictionaryWithData:(NSData *)data; 
- (id)initWithData:(NSData *)data; 
@end 

y la NSDictionary + DictFromData.m

#import "NSDictionary+DictFromData.h" 
@implementation NSDictionary (DictFromData) 

+ (id)dictionaryWithData:(NSData *)data { 
    return [[[NSDictionary alloc] initWithData:data] autorelease]; 
} 

- (id)initWithData:(NSData *)data { 
    NSString *tmp = nil; 

    self = (NSDictionary *)[NSPropertyListSerialization 
          propertyListFromData:data 
          mutabilityOption:NSPropertyListImmutable 
          format:NULL 
          errorDescription:&tmp]; 

    NSAssert1(tmp == nil,@"Error in plist: %@",tmp); 
    return [self retain]; 
} 
@end 

(source)

Si ahora la importación esta categoría en su subclase UIDocument, puede cargar y guardar fácilmente su archivo Plist en su contenedor de iCloud.

para cargar el Plist de iCloud añadir esto a su subclase UIDocument (Los contenidos propiedad es un NSDictionary):

- (BOOL)loadFromContents:(id)contents 
        ofType:(NSString *) 
     typeName error:(NSError **)outError { 

    if ([contents length] > 0){ 
     self.contents = [NSDictionary dictionaryWithData:contents]; 
    } else { 
     self.contents = nil; 
    } 

    // call some Methods to handle the incoming NSDictionary 
    // maybe overwrite the old Plist file with the new NSDictionary 

    return YES; 
} 

Para guardar los datos de nuevo a la icloud añadir lo siguiente:

- (id)contentsForType:(NSString *)typeName error:(NSError **)outError { 
    NSData * plistData = [[[NSData alloc]initWithContentsOfFile:YOUR_PLIST_FILE]autorelease]; 
    return plistData; 
} 

Si ahora llama:

[myUIDocument updateChangeCount:UIDocumentChangeDone]; 

YOUR_PLIST_FILE se está sincronizando. Recuerde que se tarda aproximadamente 10-15 segundos en actualizar su contenedor de iCloud.

Cuestiones relacionadas