Коммуникация и сохранение данных между приложениями с группами приложений

iOS 8 вчера опубликовал новый API относительно групп приложений. Раньше было беспорядочно делиться данными и общаться между приложениями, и я считаю, что именно то, что намерены использовать в приложениях.

В моем приложении я включил группы приложений и добавил новую группу, но я просто не могу найти документацию о том, как ее использовать. Ссылки на документацию и API указывают только, как добавить группу.

Итак, что на самом деле предназначено для групп приложений? Есть ли какая-либо документация где-нибудь о том, как ее использовать?

Ответ 1

Другим преимуществом для групп приложений является возможность совместного использования базы данных NSUserDefaults. Это также работает для расширений приложений (виджеты центра уведомлений, пользовательские клавиатуры и т.д.).

Инициализируйте свой объект NSUserDefaults, как это, во всех приложениях в группе приложений, и они будут совместно использовать базу данных:

Objective-C:

[[NSUserDefaults alloc] initWithSuiteName:@"<group identifier>"];

Swift:

NSUserDefaults(suiteName: "<group identifier>")

Помните, что все из базы данных [NSUserDefaults standardUserDefaults] для каждого приложения не будет переноситься в эту базу данных.

documentation также дает правильный пример (как из бета-версии 3).

И не забудьте синхронизировать базу данных:

[yourDefaults synchronize];

Ответ 2

Совместное использование данных NSUserDefaults между несколькими приложениями

Чтобы иметь общие настройки по умолчанию между приложением и добавлением или между двумя приложениями, вам необходимо добавить группу приложений в свои настройки, выполнив следующие шаги:

  • В Навигаторе проектов щелкните файл *.xcodeproj(должен быть наверху).
  • Справа от Project Navigator найдите проект и целевые объекты. Под целевыми объектами нажмите на свою основную цель (должно быть, первое, что нужно для целей).
  • Наверху щелкните вкладку "Возможности".
  • В разделе "Группы приложений" щелкните переключатель вправо, чтобы включить группы приложений.
  • Нажмите кнопку + и добавьте группу приложений с именем group.com.company.myApp.
  • Перейдите в то же место в других приложениях, и теперь эта группа должна быть доступна для выбора. Включите эту группу для каждого приложения, которое будет использовать эти общие данные.

Примечание. Если вы перейдете на Портал разработчиков Apple (веб-сайт Apple, на котором отображаются все ваши сертификаты, идентификаторы, устройства и профили Provisioning Profiles) и перейдите в "Идентификаторы" > "Группы приложений", вы увидите эту новую группу приложений.

Чтобы сохранить данные:

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
userDefaults!.setObject("user12345", forKey: "userId")
userDefaults!.synchronize()

Чтобы получить данные:

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
if let testUserId = userDefaults?.objectForKey("userId") as? String {
  print("User Id: \(testUserId)")
}

Ответ 3

Группы приложений, согласно моей интерпретации существующей документации, в первую очередь предназначены для расширений, а точнее для виджетов. Виджеты - это их собственный пакет приложений, который сосуществует с вашим приложением. Поскольку они представляют собой отдельное приложение и поэтому имеют собственную песочницу, вам нужно будет использовать группы приложений для обмена файлами.

После некоторого заголовка grep'ing, я думаю, что я нашел необходимый API, но фактически был включен как часть iOS 7.

NSFileManager имеет на нем метод containerURLForSecurityApplicationGroupIdentifier:, где вы можете передать идентификатор, созданный при включении групп приложений для своих приложений:

NSURL *containerURL = [[NSFileManager defaultManager] 
           containerURLForSecurityApplicationGroupIdentifier:@"group.com.company.app"];

Ответ 4

Одной из важных ловушек, которые я сегодня использовал, является следующее:

Во многих проектах я видел единственную цель приложения и с различными идентификаторами пакетов, установленными для каждой конфигурации этой цели. Здесь все становится беспорядочным. То, что разработчики планировали, заключалось в создании отладочного приложения для конфигурации debug и производственного приложения для цели релиза.

Если вы это сделаете, оба приложения будут совместно использовать одни и те же NSUserDefaults, когда они будут настроены так

var userDefaults = NSUserDefaults(suiteName: "group.com.company.myApp")
userDefaults!.setObject("user12345", forKey: "userId")
userDefaults!.synchronize()

Это вызывает проблемы во многих местах:

  • Представьте, что вы установили YES для ключа, когда пользователю был показан специальный экран ввода-вступления. Другое приложение теперь также прочитает "ДА" и не покажет ввод.
  • Да, некоторые приложения также хранят токены OAuth в своих настройках по умолчанию. В любом случае... В зависимости от реализации приложение распознает, что есть токен и начинает извлекать данные, используя неправильный токен. Вероятность высока, что это приведет к ошибкам со странными ошибками.

Решение этой проблемы в общем случае - это префикс ключей по умолчанию с построенной текущей конфигурацией. Вы можете легко определить конфигурацию во время выполнения, установив разные идентификаторы пакетов для ваших конфигураций. Затем просто прочитайте идентификатор пакета из NSBundle.mainBundle(). Если у вас одинаковые идентификаторы пакетов, вам нужно установить разные макросы препроцессора, например

#ifdef DEBUG
  NSString* configuration = @"debug";
#elif RELEASE
  NSString* configuration = @"release";
#endif

В Swift он будет выглядеть почти так же:

#if DEBUG
  let configuration = "debug"
#elseif RELEASE
  let configuration = "release"
#endif

Ответ 5

Чтобы сохранить

let shared: NSUserDefaults = NSUserDefaults(suiteName: "group.abcapp")!
shared.setObject("abc.png", forKey: "favEmoji")
shared.synchronize()