iCloud NSUbiquitousKeyValueStore初始同步/访问延迟 - 如何处理? [英] iCloud NSUbiquitousKeyValueStore initial sync/access delay - how to handle?

查看:138
本文介绍了iCloud NSUbiquitousKeyValueStore初始同步/访问延迟 - 如何处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using NSUbiquitousKeyValueStore to store some app settings. My logic is: when I save data locally, I save it to NSUbiquitousKeyValueStore also as a backup. When I need settings, I read locally and I only use iCloud key-value store if no data is found locally (after app is reinstalled, for example). If user has several devices sharing one icloud id, he can write settings on one device and download them to another (I warn him about rewrite).

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

I have a strange issue. Steps:


  1. 安装应用程序并将其数据保存到NSUbiquitousKeyValueStore。确保数据存在。

  2. 删除应用程序(假设数据仍然存在于iCloud中)。

  3. 等待几分钟以防万一,然后安装并从Xcode内部启动了应用程序。

  4. 尝试使用[[NSUbiquitousKeyValueStore defaultStore] dataForKey:@mykeyname读取设置键 - 有时它没问题,但有时候找不到密钥!

  5. 等了15秒,再试一次。成功。困惑。

  1. Installed an app and save its data to NSUbiquitousKeyValueStore. Made sure data is there.
  2. Removed the app (assuming data is still persists in iCloud).
  3. Waited several minutes just in case, then installed and launched the app from inside Xcode.
  4. Tried to read a settings key using [[NSUbiquitousKeyValueStore defaultStore] dataForKey: @"mykeyname"] - sometimes it's ok, but sometimes key is not found!
  5. Waited for 15 seconds, tried again. Success. Confused.

因此,似乎ios需要一些时间来为我的应用程序提供远程键值存储,以便在dataForKey:call中本地使用。
如果我写了这样一个系统(实际上我曾经做过 - 不久前,在另一个生命中),在询问和接收键值数据之前显然必须有一个延迟。所以我想要一些通知说:我们在第一次启动时完成了下载/同步键值存储或类似的东西。

So it seems like ios needs some time to make remote key-value storage for my app available locally for dataForKey: call. If I'd wrote such a system (actually I did - some time ago, in another life) there obviously must be a delay before asking and receiving a key-value data. So I'd like to have some notification saying: "we finished downloading/syncing key-value storage on first start" or something similar.

据我所知,我可以在主线程中同步使用NSUbiquitousKeyValueStore(对我来说很方便)。但是[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]返回一个有效的url,然后我得到key not found。所以我不能依赖它。有没有办法确保下载NSUbiquitousKeyValueStore的工作原理?这一点非常重要,特别是在网速较慢时。

As far as I understand I can work with NSUbiquitousKeyValueStore in main thread synchronously (which is convenient for me). But [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] returns a valid url, and then I get "key isn't found". So I can't rely on it. Is there a way to be sure NSUbiquitousKeyValueStore works an is downloaded? It's important especially with slow internet.

添加[[NSUbiquitousKeyValueStore defaultStore] synchronize](如苹果docs)初始化和加载有点帮助。 iCloud还有很多问题。

Adding [[NSUbiquitousKeyValueStore defaultStore] synchronize] (as written in apple docs) to init and load was helped a little. Still there are many questions to iCloud.

昨天我已成功将数据保存到手机1上的键值存储区并在手机2上恢复。
今天我已删除手机2上的应用并尝试恢复数据。但即使[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]返回有效的URL我调用[[NSUbiquitousKeyValueStore defaultStore] synchronize]我在调用dataForKey:MY_DATA_KEY时得到nil。

Yesterday I've successfully saved data to the key-value store on phone 1 and restored on phone 2. Today I've deleted app on phone 2 and tried to restore the data. But even [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil] returned valid URL and I called [[NSUbiquitousKeyValueStore defaultStore] synchronize] I get nil when call dataForKey: MY_DATA_KEY.

当我尝试从手机1上的icloud恢复数据(应用程序仍然安装)时,它成功了,但是当我在这款手机上重新安装时,应用程序恢复不会成功更多。

When I tried to restore data from icloud on phone 1 (app is still installed) it succeeds, but when I reinstalled on this phone the app restore doesn't succeed any more.

临时解决方案是:关闭iCloud->文档和数据 - 关闭和打开网络 - 打开文档和数据,你也应该等待几个分钟,然后它应该工作。

Temporary solution is: "turn off iCloud->Documents&Data - turn off and on network - turn on Documents&Data", but also you should wait several minutes, and then it should work.

所以,问题:
1.你对iCloud有这样的问题吗?
2.有没有办法找出数据不可用或尚未下载?
3. iCloud有任何已知的延迟吗?我听说大约7秒钟,但显然不是这样。
4.似乎当app不是unistalled时,iCloud数据的更新速度非常快(秒),但是当你重新安装应用程序时,icloud需要几分钟才能实现键值存储。有没有办法强制这个过程?

So, questions: 1. do you have such problems with iCloud? 2. Is there any way to find out is data not available or just not downloaded yet? 3. Is there any known "latency" of iCloud? I've heard about 7 seconds, but it's obviously not true. 4. It seems that when app isn't unistalled updates of iCloud data are pretty fast (seconds), but when you reinstall the app icloud needs several minutes to actualize key-value store. Is there any way to force this process?

PS
以下是我的CloudHelper供您参考 - 非常简单的c ++类,用于向/从iCloud键值存储写入/读取二进制数据。这是不可编译的,我已经适应它有点更清楚 - 删除我的引擎相关的代码。如果你删除MySystem :: ...调用它仍然很好。除了我之前提到的。

P.S. Below is my CloudHelper for your reference - pretty simple c++ class to write/read binary data to/from iCloud key-value store. It is not compilable, I've adapted it for SO somewhat to make more clear - removed my engine related code. Still if you remove MySystem::... calls it works pretty well. Except that I mentioned before.

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年。安卓已成为ios的邪恶双胞胎,人类已经发现了引力波,希格斯已经获得了他的诺贝尔奖,微软已经买下并杀死了诺基亚,所有人看到Amber Heard和Jennifer Lawrence分别裸体。但是iCloud仍然像现在一样愚蠢。

It's 2016. Android has become ios's evil twin, the humanity has discovered gravitational waves, Higgs have received his nobel, Microsoft has bought and killed Nokia, everybody saw Amber Heard and Jennifer Lawrence naked, separately. But iCloud is still as stupid as it was.

最后,我在几个VPS上制作了自己的网络服务堆栈。我拒绝使用第三方服务,因为大多数服务都不稳定且不可预测。然而我需要iCloud。因为另一个死于苹果的孩子不起作用。 SecKeyChain。当我的游戏开始时它的服务就会消失所以我决定在云中存储随机UUID以区分用户(即使重新安装后也没有设备ID)。但可能出现什么问题?一切!我花了两天时间让这个愚蠢的部署没有错误,现在它不时丢失我的数据!

Finally I've made my own stack of network services on several VPS. I refused to use third-party services, because most of them are unstable and unpredictable. And yet I need iCloud. Because another die-born child of apple does not work. SecKeyChain. Its service dies when my game starts. So I decided to store random UUID in cloud to distinguish users (there is no device id anymore) even after reinstall. But what could go wrong? Everything! I've spend two days to make this stupid s*it to deploy without errors, and now it loses my data from time to time!

谢谢Apple,谢谢,谢谢,谢谢! LA-LA-LA!太好啦! (马戏音乐的声音,渐渐变成哭泣)

推荐答案

结论

临时解决方案是:
- 在从键值存储区获取数据之前调用同步
- 确保它可以正常工作关闭iCloud-> Documents&数据 - 关闭并再次在网络上打开 - 打开文档和数据,但是在iCloud下载所有需要的数据之前你应该等几分钟

Temporary solution is: - call synchronize before get data from key-value store - to be sure it would work "turn off iCloud->Documents&Data - turn off and again on network - turn on Documents&Data", but also you should wait several minutes before iCloud downloads all needed data

注意:安装应用程序时已经工作(保存/加载)与iCloud数据的键值存储更新相当快(7-15秒),但当你重新安装应用程序时,似乎icloud需要几分钟来实现键值存储。

Note: when app is installed and already worked (saved/loaded) with key-value store updates of iCloud data are pretty fast (7-15 sec), but when you reinstall the app it seems that icloud needs several minutes to actualize key-value store.

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

I'd be glad to hear your thoughts, because icloud looks like almost unusable feature. But I don't want to set up my own server to merely get the same functionality.

这篇关于iCloud NSUbiquitousKeyValueStore初始同步/访问延迟 - 如何处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆