【问题标题】:iCloud: Is it possible to use KVS for custom objects?iCloud:是否可以将 KVS 用于自定义对象?
【发布时间】:2014-05-13 01:31:33
【问题描述】:

我正试图将注意力集中在 iCloud 存储上。我已经阅读了iCloud Design Guide 和一些关于 SO 的问题。这是我的场景:

我有一个只有NSMutableArray 的类...该集合包含我的自定义对象,这些对象都遵守NSCoding,并且在本地保存非常有效。该课程是 MasterList 并且具有属性 masterList,非常棒 - 我知道 :-p。当我研究如何开始实施 iCloud 时,我认为 KVS 会很棒,因为我的数据占用空间非常小。当我尝试这样做时,我不断得到:

[NSUbiquitousKeyValueStore setObject:forKey:]: Attempt to insert non-property value <my custom objects>...

在了解原因之后,您似乎只能使用 KVS 存储标量和 P-List 类型。所以我转而使用UIDocument 并为此苦苦挣扎。

底线 -

对于自定义对象,是一定要用UIDocument,还是可以用KVS?

如果我必须使用UIDocument,你们中是否有人读过本质上很简单的教程(可能存储了一些道具并将它们加载回来,可能在一个示例项目中?)让您点击了吗?

如果有帮助的话,下面是我使用 KVS 的代码。不是生产或任何东西,只是想让它工作:

//Load it
+(MasterList *)decodeMasterList:(MasterList *)objectToDecode
{

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    NSURL *dataFile = [self pathForDocumentsFile:kFilePathAllLists];
    NSString *filePath = [dataFile path];

    objectToDecode = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

    //First time runnign the app :-)
    if (!objectToDecode) objectToDecode = [[MasterList alloc] init];

    if ([defaults boolForKey:kIsUsingiCloud])
    {
        objectToDecode.masterList = [[[NSUbiquitousKeyValueStore defaultStore] arrayForKey:kiCloudPath] mutableCopy];

        //If we just started and nothing is there
        if (!objectToDecode.masterList)
        {
            objectToDecode.masterList  = [[NSMutableArray alloc] initWithObjects:[CustomList new], nil];
        }
    }

    return objectToDecode;
}

//Save it
+(BOOL)encodeMasterList:(MasterList *)objectToEncode
{
    @try
    {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        if ([defaults boolForKey:kIsUsingiCloud])
        {
            [[NSUbiquitousKeyValueStore defaultStore] setArray:objectToEncode.masterList forKey:kiCloudPath];
            [[NSUbiquitousKeyValueStore defaultStore] synchronize];
        }

        NSURL *dataFile = [FileSystemHelper pathForDocumentsFile:kFilePathAllLists];
        NSString *filePath = [dataFile path];
        [NSKeyedArchiver archiveRootObject:objectToEncode toFile:filePath];

    }
    @catch (NSException *exception)
    {
        return NO;
    }

    return YES;
}

【问题讨论】:

    标签: ios objective-c icloud uidocument


    【解决方案1】:

    键值存储确实只能保存属性列表类型。但是你提到你的数组中的对象都符合NSCoding,所以这不是一个主要问题。您只需要应用NSCoding 将您的对象转换为NSData 或从NSData 转换,并存储它。

    使用编码

    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:myObject];
    

    使用解码

    NSData *data = // from key-value store
    MyClass *myObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
    

    然而如果您使用UIDocument,键值存储可能不是最好的方法。您还可以通过NSFileManagerNSMetadataQuery 在 iCloud 中直接存储和同步文档。 Apple 在这方面提供了很好的文档,它会就地同步文档,而不是要求您来回转换它。当然,键值存储的总大小限制非常低,而文档仅受用户 iCloud 帐户容量的限制。

    【讨论】:

    • 谢谢汤姆,我确实通过使用 NSData 让它工作了。如果你不能,没问题,但你有一篇文章/示例解决方案的推荐,展示如何正确子类化 UIDocument 并使用它在 iCloud 中存储数据?
    • Apple 的Document-Based App Programming Guide for iOS 是两者的良好起点。有关更多信息,请参阅该文档中的链接和iCloud for Developers
    • Apple 不建议在 KVS 中存储大型数据块 - 这是一种糟糕的同步模式。您应该将对象图解构为更细粒度,然后将其保存为存储中的基本数据类型。
    • @Ryan 我不相信这个问题提到了大数据块。
    • @TomHarrington 我的观点是整个数据树的单个二进制表示是不恰当地使用 KVS,UIDocument 同步是这种情况下更好的 iCloud 候选。
    猜你喜欢
    • 2017-08-26
    • 2022-08-08
    • 2014-09-19
    • 1970-01-01
    • 1970-01-01
    • 2011-04-09
    • 1970-01-01
    • 2017-12-18
    • 1970-01-01
    相关资源
    最近更新 更多