使用iCloud共享plist文件

时间:2011-12-07 01:01:19

标签: persistence plist icloud nsfilewrapper uidocument

我有一个relativley简单应用程序,它将数据保存到位于文档文件夹中的plist文件中。数据在启动时加载到UITableView中。然后,用户可以编辑,删除或添加记录,任何更改都会保存回plist文件。

现在我想使用iCloud跨设备共享此数据(plist文件)。我查看了文档,我的理解是我需要创建一个UIDocument来“管理”plist文件。

我查看了几个iCloud教程,但是它们都在UIDocument类的属性中存储了一个简单的字符串,而不是整个文件(如plist)。

如何使用UIDocument对象将我的plist文件(或任何其他文件)与iCloud共享?

我会将plist文件内容转换为NSData,然后将其保存在UIDocument的属性中吗?我应该使用NsFileWrapper吗?

我似乎很难绕着UIDocument / iCloud安排我的脑袋。我可能会让它变得更加复杂,然而它确实如此。

2 个答案:

答案 0 :(得分:7)

不确定是否有人仍需要解决方案,但我找到了一种很好的方法让它发挥作用。

由于UIDocument只接受Data作为NSData或NSFilewrapper,我首先为NSDictionary类创建了一个Category,它从NSData返回一个NSDictionary。这是类别的两个文件:

的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容器中。

要从iCloud加载您的Plist,请将其添加到您的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 :(得分:1)

要使用带有UIDocument的plist,您可以继承UIDocument并使用声明为NSMutableDictionary的self.myDictionary(您的plist)覆盖以下两个方法。

- (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;
}