首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iCloud NSUbiquitousKeyValueStore初始同步/访问延迟-如何处理?

iCloud NSUbiquitousKeyValueStore初始同步/访问延迟-如何处理?
EN

Stack Overflow用户
提问于 2012-09-21 23:11:45
回答 3查看 7K关注 0票数 20

我正在使用NSUbiquitousKeyValueStore存储一些应用程序设置。我的逻辑是:当我在本地保存数据时,我也将数据保存到NSUbiquitousKeyValueStore作为备份。当我需要设置时,我在本地读取,如果本地找不到数据,我只使用iCloud键值存储(例如,在重新安装app之后)。如果用户有几个设备共享一个icloud id,他可以在一个设备上编写设置并下载到另一个设备(我警告他要重写)。

我有个奇怪的问题。步骤:

  1. 安装了一个应用程序并将其数据保存到NSUbiquitousKeyValueStore。确保数据在那里。
  2. 删除应用程序(假设数据仍然保存在iCloud中)。
  3. 等了几分钟以防万一,然后从Xcode内部安装并启动了这个应用程序。
  4. 尝试使用[NSUbiquitousKeyValueStore defaultStore dataForKey:@"mykeyname"]读取设置键--有时可以,但有时找不到!
  5. 等了15秒再试一次。成功。迷惑了。

因此,ios似乎需要一些时间来为dataForKey: call在本地提供应用程序的远程键值存储。如果我写了这样一个系统(实际上我写了--一段时间以前,在另一个生命中),很明显,在询问和接收键值数据之前肯定会有延迟。因此,我希望得到一些通知:“我们在第一次启动时完成了下载/同步键值存储”或类似的内容。

据我所知,我可以在主线程中同步使用NSUbiquitousKeyValueStore (这对我来说很方便)。但是[NSFileManager defaultManager URLForUbiquityContainerIdentifier:nil]返回一个有效的url,然后得到“找不到密钥”。所以我不能依赖它。是否有办法确保下载了NSUbiquitousKeyValueStore?这一点很重要,尤其是在互联网发展缓慢的情况下。

更新

[NSUbiquitousKeyValueStore defaultStore]同步添加到init和load中有一点帮助。尽管如此,iCloud仍然有许多问题。

昨天,我成功地将数据保存到手机1上的键值商店,恢复了手机2上的数据。今天,我删除了手机2上的应用程序,并尝试恢复数据。但是即使是[NSFileManager defaultManager URLForUbiquityContainerIdentifier: nil ]也返回有效的URL,我调用[NSUbiquitousKeyValueStore defaultStore synchronize]当调用dataForKey: MY_DATA_KEY时得到零。

当我试图从电话1(应用程序还在安装)上恢复数据时,它成功了,但是当我在这款手机上重新安装时,应用程序恢复就不再成功了。

临时解决方案是:“关闭iCloud->文档和数据-关闭和打开网络-打开文档和数据”,但也需要等待几分钟,然后才能工作。

那么,问题是:

  1. 你对iCloud有这样的问题吗?
  2. 是否有任何方法来找出数据是不可用的,还是只是还没有下载?
  3. 是否存在已知的iCloud的“延迟”?我听说了7秒,但很明显这不是真的。
  4. 看起来,当应用程序不是孤立的时候,更新iCloud数据的速度相当快(秒),但是当您重新安装应用程序时,icloud需要几分钟才能实现键值存储。有什么办法强制这个过程吗?

下面的P.S.是我的CloudHelper,供您参考--非常简单的c++类可以将二进制数据写入/读取到iCloud键值存储区。它是不可编译的,我已经对它做了一些调整,以使我的引擎相关代码更加清晰。如果删除MySystem::.打电话说效果很好。除了我之前提到的。

代码语言:javascript
复制
class CloudHelper
{
public:
    static bool init();
    static void deInit();
    //save our data to iCloud with
    static int saveData(unsigned char* data, int from, int count);
    //get our data from iCloud
    static unsigned char * loadData(int *retsize, int * retint);
    //does iCloud work for us
    static bool isEnabled();
    //do we have our key in iCloud
    static int isAvailable();

    static const int RESULT_OK = 0;
    static const int RESULT_NO_CONNECTION = 1;
    static const int RESULT_NOT_FOUND = 2;
    static const int RESULT_SYNC_ERROR = 3;
private:
    static bool enabled;
    static NSURL *ubiq;
};



bool CloudHelper::enabled = false;

NSURL *CloudHelper::ubiq = NULL;

#define MY_DATA_KEY @"my_data_key"

int CloudHelper::saveData(unsigned char* data, int from, int count)
{
    if ([NSUbiquitousKeyValueStore defaultStore])
    {
        NSData *d = [[[NSData alloc] initWithBytes:(data + from) length:count] autorelease];
        [[NSUbiquitousKeyValueStore defaultStore] setData:d forKey: MY_DATA_KEY)];
        if ([[NSUbiquitousKeyValueStore defaultStore] synchronize] != TRUE)
            return RESULT_SYNC_ERROR;
        return RESULT_OK;
    }
    return RESULT_NO_CONNECTION;
}

unsigned char * CloudHelper::loadData(int *retsize, int * retint)
{
    if ([NSUbiquitousKeyValueStore defaultStore])
    {
        [[NSUbiquitousKeyValueStore defaultStore] synchronize];
        NSData *d = [[NSUbiquitousKeyValueStore defaultStore] dataForKey: MY_DATA_KEY];
        if (d != NULL)
        {
            if (retsize != NULL)
                *retsize = d.length;
            if (retint != NULL)
                *retint = RESULT_OK;
            return d.bytes;
        }
        else
        {
            if (retsize != NULL)
                *retsize = -1;
            if (retint != NULL)
                *retint = RESULT_NOT_FOUND;
        }
    }
    else
    {
        if (retsize != NULL)
            *retsize = -1;
        if (retint != NULL)
            *retint = RESULT_NO_CONNECTION;
    }
    return NULL;
}

int CloudHelper::isAvailable()
{
    int result = RESULT_NO_CONNECTION;

    if ([NSUbiquitousKeyValueStore defaultStore])
    {
        [[NSUbiquitousKeyValueStore defaultStore] synchronize];
        NSData *d = [[NSUbiquitousKeyValueStore defaultStore] dataForKey: MY_DATA_KEY];
        if (d != NULL)
            result = RESULT_OK;
        else
            result = RESULT_NOT_FOUND;
    }
    else
        result = RESULT_NO_CONNECTION;

    return result;
}

void CloudHelper::deInit()
{
    enabled = false;
    [ubiq release];
}

bool CloudHelper::init()
{
    enabled = false;
    NSURL *ubiq_ = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
    [[NSUbiquitousKeyValueStore defaultStore] synchronize];
    if (ubiq)
    {
        enabled = true;
        ubiq = [ubiq_ retain]; //save for further use
    }
    else
    {
        //is implemented elsewhere: this writes a local file with a counter, and if it is < REMINDER_COUNT allows us to show a warning to users
        bool allow = MySystem::isAllowToShowDialog();
        if (allow)
        {
            //determines network state with Apple's Reachability
            if (!MySystem::isNetworkAvailable())
                MySystem::showMessageBox(@"Network error"); //No network
            else
                MySystem::showMessageBox(@"You should log into your iCloud account to be able to backup your settings."); //No login
        }
    }
    return enabled;
}

更新2

现在是2016年。Android已经成为ios的邪恶双胞胎,人类发现了引力波,希格斯获得了诺贝尔奖,微软收购并杀死了诺基亚。但是iCloud仍然像以前一样愚蠢。

最后,我在几个VPS上建立了自己的网络服务堆栈。我拒绝使用第三方服务,因为大多数服务都是不稳定和不可预测的。但我需要iCloud。因为苹果的另一个死胎不起作用。SecKeyChain。当我的游戏开始的时候它的服务就死了。因此,我决定将UUID随机存储在云中,以便在重新安装后区分用户(不再有设备id )。但有什么会出错呢?所有的一切!我花了两天时间让这个愚蠢的s*它没有错误地部署,现在它不时地丢失我的数据!

谢谢苹果,谢谢!啦!嘻哈万岁!(马戏团音乐的声音,渐入哭泣)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-09-22 00:05:44

结论

临时解决方案是:-在从键值存储获取数据之前调用同步--以确保它能够“关闭iCloud ->文档和数据-关闭并再次关闭网络-打开文档和数据”,但您还应该等待几分钟,iCloud才会下载所有需要的数据。

注意:当iCloud数据的键值存储更新安装并已经运行(保存/加载)时,更新速度相当快(7-15秒),但是当您重新安装应用程序时,icloud似乎需要几分钟才能实现键值存储。

我很高兴听到您的想法,因为icloud看起来几乎无法使用。但我不想设置自己的服务器来获得相同的功能。

票数 4
EN

Stack Overflow用户

发布于 2013-02-28 06:09:10

我正在为NSUbiquitousKeyValueStore设置一个虚拟键,并在应用程序启动时调用synchronize。结果不是100%的解决方案,但稍微好一些。你可以试试这个。

票数 1
EN

Stack Overflow用户

发布于 2012-09-22 22:36:55

因为很明显,你的应用程序不应该挂在等待一个缓慢的netork。都在iCloud设计指南里。

注册NSUbiquitousKeyValueStoreDidChangeExternallyNotification,调用-synchronize,希望最终会收到通知。

如果数据已经是最新的,我不认为你会收到通知,而且我也不认为有一个很好的方法来知道这些数据有多老。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12539266

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档