Ter*_*ium 13 iphone ios icloud-api nsubiquitouskeyvaluestore
我正在使用NSUbiquitousKeyValueStore来存储一些应用程序设置.我的逻辑是:当我在本地保存数据时,我还将其保存到NSUbiquitousKeyValueStore作为备份.当我需要设置时,我在本地阅读,如果没有在本地找到数据,我只使用iCloud键值存储(例如,在重新安装应用程序之后).如果用户有多个设备共享一个icloud id,他可以在一个设备上写设置并将其下载到另一个设备(我警告他重写).
我有一个奇怪的问题.脚步:
因此,似乎ios需要一些时间来为我的应用程序提供远程键值存储,以便在dataForKey:call中进行本地访问.如果我写了这样一个系统(实际上我做过 - 前一段时间,在另一个生命中),在询问和接收键值数据之前显然必须有一个延迟.所以我想要一些通知说:"我们在第一次启动时完成了下载/同步键值存储"或类似的东西.
据我所知,我可以同步在主线程中使用NSUbiquitousKeyValueStore(这对我来说很方便).但是[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]返回一个有效的url,然后我得到"key not found".所以我不能依赖它.有没有办法确保下载NSUbiquitousKeyValueStore的工作原理?这一点非常重要,特别是在网速较慢时.
添加[[NSUbiquitousKeyValueStore defaultStore] synchronize](如在apple docs中所写)到init和load有点帮助.iCloud还有很多问题.
昨天我已成功将数据保存到手机1上的键值存储区并在手机2上恢复.今天我已删除手机2上的应用程序并尝试恢复数据.但即使[[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil]返回有效的URL我调用[[NSUbiquitousKeyValueStore defaultStore] synchronize]我在调用dataForKey:MY_DATA_KEY时得到nil.
当我尝试从手机1上的icloud恢复数据(应用程序仍然安装)时,它成功,但是当我在此手机上重新安装时,应用程序恢复不再成功.
临时解决方案是:"关闭iCloud->文档和数据 - 关闭和打开网络 - 打开文档和数据",但是你应该等几分钟,然后它应该工作.
所以,问题:1.你对iCloud有这样的问题吗?2.有没有办法找出数据不可用或尚未下载?3. iCloud有任何已知的"延迟"吗?我听说大约7秒钟,但显然不是这样.4.似乎当应用程序没有未加载时,iCloud数据的更新速度非常快(秒),但是当您重新安装应用程序时,icloud需要几分钟才能实现键值存储.有没有办法强迫这个过程?
PS 下面是我的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;
}
Run Code Online (Sandbox Code Playgroud)
更新2
这是2016年.Android已经成为ios的邪恶双胞胎,人类已经发现了引力波,希格斯已经获得了他的诺贝尔奖,微软已经买下并杀死了诺基亚,大家分别看到了Amber Heard和Jennifer Lawrence.但是iCloud仍然像它一样愚蠢.
最后,我在几个VPS上制作了自己的网络服务堆栈.我拒绝使用第三方服务,因为大多数服务都不稳定且不可预测.然而我需要iCloud.因为另一个死于苹果的孩子不起作用.SecKeyChain.当我的游戏开始时它的服务就会消失 所以我决定将随机UUID存储在云中以区分用户(即使重新安装后也没有设备ID).但可能出现什么问题?一切!我花了两天时间让这个愚蠢的部署没有错误,现在它不时丢失我的数据!
谢谢Apple,谢谢,谢谢,谢谢!LA-LA-LA!太好啦!(马戏音乐的声音,逐渐消失)
结论
临时解决方案是: - 在从键值存储获取数据之前调用同步 - 确保它可以工作“关闭iCloud->文档和数据 - 关闭并再次打开网络 - 打开文档和数据”,但你也应该等待几分钟iCloud 下载所有需要的数据
注意:当应用程序安装并已经使用(保存/加载)iCloud 数据的键值存储更新时,速度非常快(7-15 秒),但是当您重新安装应用程序时,icloud 似乎需要几分钟才能实现密钥-价值存储。
我很高兴听到你的想法,因为 icloud 看起来几乎无法使用的功能。但我不想建立自己的服务器只是为了获得相同的功能。
| 归档时间: |
|
| 查看次数: |
5707 次 |
| 最近记录: |