2011-12-07 3 views
7

У меня есть простое приложение для релятиви, которое сохраняет данные в файле plist, расположенном в папке с документами. Данные загружаются в UITableView при запуске. Затем пользователь может редактировать, удалять или добавлять записи, а любые изменения сохраняются обратно в файл plist.Совместное использование файла plist с использованием iCloud

Теперь я хотел бы поделиться этими данными (файл plist) на устройствах с использованием iCloud. Я просмотрел документацию, и я понимаю, что мне нужно создать UIDocument для «управления» файлом plist.

Я просмотрел несколько руководств iCloud, но все они хранят простую строку в свойстве класса UIDocument, а не весь файл (например, plist).

Как поделиться своим файлом plist (или любым другим файлом, если на то пошло) с iCloud с помощью объекта UIDocument?

Могу ли я преобразовать содержимое файла plist в NSData, а затем сохранить его в свойстве в UIDocument? Должен ли я использовать NsFileWrapper вместо этого?

Кажется, у меня тяжелое время, обворачивающее мою голову вокруг расположения UIDocument/iCloud. Вероятно, я делаю это более сложным, чем есть.

+0

Вы нашли ответ для этого? Я смотрю на то, что делаю то же самое, и мое приложение звучит очень похоже на ваше. Пожалуйста, дайте мне знать, если вы нашли хороший учебник. – Jackson

+0

Я также пытаюсь это сделать.Я модифицировал учебник с помощью NSString, но я не могу заставить второе устройство видеть данные. – zambono

+0

так же. +1 к плакату – autodidakto

ответ

1

Чтобы использовать plist с UIDocument, вы можете подклассифицировать UIDocument и переопределить следующие 2 метода с self.myDictionary (ваш plist), объявленный как 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

Это не создает словарь plist, он создает архивный слой, но достаточно близко. Чтобы создать реальный plist, используйте NSPropertyListSerialization, и вы можете выбрать либо xml, либо двоичный вывод. – malhal

+0

Также архивные plists не совместимы между Mac и iOS. – malhal

7

Не уверен, что для кого-то еще требуется решение, но я нашел хороший способ заставить это работать.

Поскольку UIDocument принимает данные только как NSData или NSFilewrapper, я сначала создал категорию для класса NSDictionary, которая возвращает NSDictionary из NSData. Вот эти два файла для Категория:

NSDictionary + DictFromData.h:

#import <Foundation/Foundation.h> 

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

и 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)

Если теперь импорт этой категории в вашем подклассе UIDocument, вы можете легко загрузить и сохранить свой Plist-файл в свой контейнер iCloud.

Чтобы загрузить Plist из ICloud добавить к вашему UIDocument подклассу (Содержание недвижимости является 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; 
} 

для сохранения данных обратно в ICloud добавить:

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

Если вы сейчас звоните:

[myUIDocument updateChangeCount:UIDocumentChangeDone]; 

YOUR_PLIST_FILE синхронизируется. Помните, что для обновления iCloud Container требуется около 10-15 секунд.

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