草庐IT

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

coder 2023-07-27 原文

我正在使用NSUbiquitousKeyValueStore存储一些应用程序设置。我的逻辑是:当我在本地保存数据时,我也将其保存为NSUbiquitousKeyValueStore作为备份。当我需要设置时,我会在本地阅读,并且仅在本地未找到数据的情况下才使用iCloud键值存储(例如,在重新安装应用程序之后)。如果用户有多台设备共享一个icloud id,则他可以在一个设备上写入设置并将其下载到另一台设备(我警告他重写)。
我有一个奇怪的问题。脚步:

  • 安装了一个应用程序,并将其数据保存到NSUbiquitousKeyValueStore。确保数据在那里。
  • 删除了该应用程序(假设数据仍然存在于iCloud中)。
  • 等待了几分钟,以防万一,然后从Xcode内部安装并启动了该应用程序。
  • 尝试使用[[NSUbiquitousKeyValueStore defaultStore] dataForKey:@“mykeyname”]读取设置键-有时还可以,但是有时找不到键!
  • 等待15秒,然后重试。成功。使困惑。

  • 因此,似乎ios需要一些时间来使我的应用程序的远程键值存储在本地可用于dataForKey:调用。
    如果我写了一个这样的系统(实际上,我确实是在一段时间之前写的,就是另一种生活),那么在询问和接收键值数据之前显然必须有一个延迟。因此,我希望收到一些通知:“我们在第一次启动时就完成了键/值存储的下载/同步”或类似的操作。
    据我了解,我可以在主线程中同步使用NSUbiquitousKeyValueStore(这对我来说很方便)。但是[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]返回一个有效的url,然后我得到“找不到 key ”。所以我不能依靠它。有没有一种方法可以确保NSUbiquitousKeyValueStore可以正常下载?这一点很重要,尤其是在互联网速度较慢的情况下。
    更新
    将[[NSUbiquitousKeyValueStore defaultStore]同步](如Apple文档中所写)添加到init和加载中有所帮助。 iCloud仍然有很多问题。
    昨天,我已经成功地将数据保存到电话1上的键值存储中,并在电话2上还原了。
    今天,我已经删除了手机2上的应用程序,并试图恢复数据。但是,即使[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]也返回了有效的URL,并且我调用了[[NSUbiquitousKeyValueStore defaultStore] sync],当我调用dataForKey:MY_DATA_KEY时我也得到了nil。
    当我尝试从手机1上的icloud还原数据(仍安装了应用程序)时,它会成功,但是当我在此手机上重新安装时,应用程序还原不会再成功。
    临时解决方案是:“关闭iCloud-> Documents&Data-关闭并打开网络-开启Documents&Data”,但是您还应该等待几分钟,然后它才能工作。
    因此,问题:
  • 您是否对iCloud有此类问题?
  • 是否有任何方法可以找出数据不可用或尚未下载?
  • iCloud是否存在任何已知的“延迟”?我已经听说了大约7秒钟,但这显然不是事实。
  • 似乎,当应用程序运行异常时,iCloud数据的更新速度很快(几秒钟),但是当您重新安装应用程序时,icloud需要几分钟来实现键值存储。有什么方法可以强制执行此过程吗?

  • P.S.
    以下是我的CloudHelper供您引用-非常简单的c++类,用于向/从iCloud键值存储中写入/读取二进制数据。它不是可编译的,我已经对其进行了某种修改以使其更加清晰-删除了与引擎相关的代码。如果您删除MySystem::...,它仍然可以正常工作。除了我之前提到的。
    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。因为苹果的另一个死胎 child 不工作。安全 key 链。当我的游戏开始时,它的服务终止。因此,即使重新安装后,我还是决定将随机UUID存储在云中以区分用户(不再有设备ID)。但是可能出什么问题了?一切!我花了两天时间使这个愚蠢的s * it能够正确部署,现在却不时丢失我的数据!
    谢谢苹果,谢谢,谢谢,谢谢!啦啦啦!太好啦! (马戏音乐声,渐渐哭泣)

    最佳答案

    结论

    临时解决方案是:
    -在从键值存储中获取数据之前调用同步
    -确保它可以正常工作“关闭iCloud-> Documents&Data-关闭并再次在网络上-开启Documents&Data”,但是您还应该等待几分钟,然后iCloud才下载所有需要的数据

    注意:在安装应用程序并已将其与键值存储一起使用(保存/加载)时,iCloud数据更新非常快(7-15秒),但是重新安装该应用程序时,icloud似乎需要几分钟才能实现 key -值存储。

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

    关于iphone - iCloud NSUbiquitousKeyValueStore初始同步/访问延迟-如何处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12539266/

    有关iphone - iCloud NSUbiquitousKeyValueStore初始同步/访问延迟-如何处理?的更多相关文章

    随机推荐