我正在使用NSUbiquitousKeyValueStore存储一些应用程序设置。我的逻辑是:当我在本地保存数据时,我也将数据保存到NSUbiquitousKeyValueStore作为备份。当我需要设置时,我在本地读取,如果本地找不到数据,我只使用iCloud键值存储(例如,在重新安装app之后)。如果用户有几个设备共享一个icloud id,他可以在一个设备上编写设置并下载到另一个设备(我警告他要重写)。
我有个奇怪的问题。步骤:
因此,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->文档和数据-关闭和打开网络-打开文档和数据”,但也需要等待几分钟,然后才能工作。
那么,问题是:
下面的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。因为苹果的另一个死胎不起作用。SecKeyChain。当我的游戏开始的时候它的服务就死了。因此,我决定将UUID随机存储在云中,以便在重新安装后区分用户(不再有设备id )。但有什么会出错呢?所有的一切!我花了两天时间让这个愚蠢的s*它没有错误地部署,现在它不时地丢失我的数据!
谢谢苹果,谢谢!啦!嘻哈万岁!(马戏团音乐的声音,渐入哭泣)
发布于 2012-09-22 00:05:44
结论
临时解决方案是:-在从键值存储获取数据之前调用同步--以确保它能够“关闭iCloud ->文档和数据-关闭并再次关闭网络-打开文档和数据”,但您还应该等待几分钟,iCloud才会下载所有需要的数据。
注意:当iCloud数据的键值存储更新安装并已经运行(保存/加载)时,更新速度相当快(7-15秒),但是当您重新安装应用程序时,icloud似乎需要几分钟才能实现键值存储。
我很高兴听到您的想法,因为icloud看起来几乎无法使用。但我不想设置自己的服务器来获得相同的功能。
发布于 2013-02-28 06:09:10
我正在为NSUbiquitousKeyValueStore设置一个虚拟键,并在应用程序启动时调用synchronize。结果不是100%的解决方案,但稍微好一些。你可以试试这个。
发布于 2012-09-22 22:36:55
因为很明显,你的应用程序不应该挂在等待一个缓慢的netork。都在iCloud设计指南里。
注册NSUbiquitousKeyValueStoreDidChangeExternallyNotification,调用-synchronize,希望最终会收到通知。
如果数据已经是最新的,我不认为你会收到通知,而且我也不认为有一个很好的方法来知道这些数据有多老。
https://stackoverflow.com/questions/12539266
复制相似问题