Совместное использование файла plist с помощью iCloud - PullRequest
7 голосов
/ 07 декабря 2011

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

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

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

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

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

Мне кажется, мне трудно оборачиваться вокруг расположения UIDocument / iCloud.Я, наверное, все усложняю, чем на самом деле.

Ответы [ 2 ]

7 голосов
/ 06 октября 2012

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

Поскольку 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

( источник)

Если вы теперь импортируете эту категорию в свой подкласс 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 требуется около 10-15 секунд.

1 голос
/ 08 марта 2012

Чтобы использовать 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;
}
...