iCloud NSUbiquitousKeyValueStore начальная задержка синхронизации / доступа - как справиться?

Я использую NSUbiquitousKeyValueStore для хранения некоторых настроек приложения. Моя логика такова: когда я сохраняю данные локально, я сохраняю их в NSUbiquitousKeyValueStore также в качестве резервной копии. Когда мне нужны настройки, я читаю локально и использую хранилище ключей iCloud только в том случае, если данные не найдены локально (например, после переустановки приложения). Если у пользователя есть несколько устройств, использующих один идентификатор icloud, он может записать настройки на одном устройстве и загрузить их на другое (я предупреждаю его о перезаписи).

У меня странная проблема. шаги:

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

Таким образом, похоже, что ios нужно некоторое время, чтобы сделать хранилище значений ключей для моего приложения доступным локально для dataForKey: call. Если бы я написал такую систему (на самом деле я это сделал - некоторое время назад, в другой жизни), очевидно, должна быть задержка, прежде чем запрашивать и получать данные значения ключа. Поэтому я хотел бы получить уведомление о том, что «мы закончили загрузку / синхронизацию хранилища значений ключей при первом запуске»; или что-то подобное.

Насколько я понимаю, я могу работать с NSUbiquitousKeyValueStore в основном потоке синхронно (что мне удобно). Но [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: nil] возвращает действительный URL-адрес, и тогда я получаю "ключ не найден". Поэтому я не могу полагаться на это. Есть ли способ убедиться, что NSUbiquitousKeyValueStore работает и загружен? Это особенно важно при медленном интернете.

UPDATE

Добавление [[NSUbiquitousKeyValueStore defaultStore] синхронизации] (как написано в Apple Docs) для инициализации и загрузки помогло немного. Тем не менее, есть много вопросов к iCloud.

Вчера я успешно сохранил данные в хранилище значений ключей на телефоне 1 и восстановил на телефоне 2. Сегодня я удалил приложение на телефоне 2 и попытался восстановить данные. Но даже [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier: nil] возвратил действительный URL, и я вызвал [[NSUbiquitousKeyValueStore defaultStore] синхронизация] Я получаю ноль при вызове dataForKey: MY_DATA_KEY.

Когда я пытался восстановить данные из icloud на телефоне 1 (приложение все еще установлено), это было успешно, но после переустановки на этом телефоне восстановление приложения больше не выполнялось.

Временное решение: «выключить iCloud-> Документы и данные» - выключить и включить сеть - включить «Документы и данные», но также следует подождать несколько минут, после чего оно должно работать.

Итак, вопросы: 1. у вас есть такие проблемы с iCloud? 2. Есть ли способ узнать, данные недоступны или просто еще не загружены? 3. Есть ли известная «задержка»? из iCloud? Я слышал около 7 секунд, но это, очевидно, не соответствует действительности. 4. Похоже, что когда приложение не может обновлять данные iCloud достаточно быстро (в секундах), но при переустановке приложения icloud требуется несколько минут для актуализации хранилища значений ключей. Есть ли способ форсировать этот процесс?

P.S. Ниже для справки мой CloudHelper - довольно простой класс c ++ для записи / чтения двоичных данных в / из хранилища значений ключей iCloud. Он не компилируется, я несколько адаптировал его для SO, чтобы сделать его более понятным - удалил код, связанный с движком. Тем не менее, если вы удалите 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;
}

UPDATE 2

Это 2016 год. Android стал злым двойником ios, человечество обнаружило гравитационные волны, Хиггс получил свой нобель, Microsoft купила и убила Nokia, все видели Голых Эмбер Херд и Дженнифер Лоуренс по отдельности. Но iCloud по-прежнему так же глуп, как и был.

Наконец, я создал свой собственный стек сетевых служб на нескольких VPS. Я отказался от использования сторонних сервисов, потому что большинство из них нестабильны и непредсказуемы. И все же мне нужен iCloud. Потому что другой умирающий от яблока ребенок не работает. SecKeyChain. Его служба умирает, когда начинается моя игра. Поэтому я решил хранить случайный UUID в облаке, чтобы различать пользователей (идентификатор устройства больше не существует) даже после переустановки. Но что может пойти не так? Все! Я потратил два дня, чтобы сделать это глупым для развертывания без ошибок, и теперь он время от времени теряет мои данные!

Thank you Apple, thank, thank, thank! La-la-la! Hip-hip hooray! (sounds of circus music, fading into weeping)

Ответы на вопрос(3)

Ваш ответ на вопрос