7

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

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

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

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

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

我似乎很难理解 UIDocument/iCloud 的安排。我可能让这件事变得更复杂了。

4

2 回答 2

7

不确定是否有人仍然需要解决方案,但我找到了一个很好的方法来让它工作。

由于 UIDocument 只接受作为 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

来源

如果你现在在你的 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 秒。

于 2012-10-06T12:50:40.033 回答
1

要将 plist 与 UIDocument 一起使用,您可以继承 UIDocument 并使用声明为 NSMutableDictionary 的 self.myDictionary(您的 plist)覆盖以下 2 个方法。

- (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;
}
于 2012-03-08T04:30:26.110 回答