Обмен и сохранение данных между приложениями с помощью групп приложений

85

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

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

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

стрим
источник

Ответы:

81

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

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

Цель-C:

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

Swift:

NSUserDefaults(suiteName: "<group identifier>")

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

В документации также приведен правильный пример (начиная с Beta 3).

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

[yourDefaults synchronize];
Санта Клаус
источник
2
Работает только на симуляторе (XCode 6 beta 5, iOS 8 beta 5)
iOS Dev
8
ПРИМЕЧАНИЕ. Если вы используете это с расширением iOS 8 (например, с клавиатурой), вам необходимо убедиться, что ваше расширение имеет RequestsOpenAccess = YES в файле Info.plist.
Киран Панесар
1
Я сделал RequestsOpenAccess = YES и следую инструкциям, но он не работает для меня на устройстве и отлично работает на эмуляторе, что-то особенное для устройства?
MAC
Та же проблема со мной, я интегрировал расширение общего доступа в свое приложение, оно работает на симуляторе, но не работает на реальном устройстве, я добавил RequestOpenAccess = YES, но он не работает, мой вопрос - stackoverflow.com/questions/30489894/ …
Рави Оджа
3
@MikeRichards не уверен, но если я правильно помню, группы приложений имеют префикс с идентификатором команды
Санта-Клаус
74

Обмен данными NSUserDefaults между несколькими приложениями

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

  1. В навигаторе проекта щелкните файл * .xcodeproj (должен быть вверху).
  2. Справа от Project Navigator найдите Project и Targets. В разделе "Цели" нажмите на свою основную цель (она должна быть первой в разделе "Цели").
  3. Вверху щелкните вкладку Возможности.
  4. В разделе «Группы приложений» щелкните переключатель справа, чтобы включить группы приложений.
  5. Нажмите кнопку + и добавьте группу приложений с именем group.com.company.myApp .
  6. Перейдите в то же место в других ваших приложениях, и теперь эта группа должна быть доступна для выбора. Включите эту группу для каждого приложения, которое будет использовать эти общие данные.

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

Для хранения данных:

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)")
}
TenaciousJay
источник
2
Благодарность! Чтобы понять, как это сделать, потребовался небольшой поиск в документации, и я подумал, что другие оценят мои шаги.
TenaciousJay
Спасибо за подробное описание ...! нужно ли нам создавать какой-либо сертификат из Apple Developer Portal (веб-сайт Apple, на котором показаны все ваши сертификаты, идентификаторы, устройства и профили обеспечения), чтобы включить эту группу? такое же, как Push-уведомление.?
Arbaz Shaikh
Когда вы выполняете шаг 5, он должен добавить группу приложений на портал разработчика Apple, вам не нужно переходить непосредственно на портал разработчика, чтобы добавить ее. После выполнения шага 5 вы можете перейти на портал и увидеть, что он должен был создать его за вас.
TenaciousJay
@TenaciousJay Превосходный ответ. Просто хочу добавить, если вы хотите запустить приложение из приложения func (app: UIApplication, openURL url: NSURL, options: [String: AnyObject]) -> Bool
Таймур Аджмал
отличный ответ. спасибо @TenaciousJay. Я пытаюсь получить переменную и ее значение из AppB в AppA, как мне это сделать? Например, если riderCancelledRequest = true в AppB, как мне получить это в AppA?
LizG
37

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

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

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

NSURL *containerURL = [[NSFileManager defaultManager] 
           containerURLForSecurityApplicationGroupIdentifier:@"group.com.company.app"];
Уэйн Хартман
источник
Спасибо, я считаю, что вы правы насчет расширяемости. Я немного сомневаюсь в этом методе iOS 7, мне он кажется довольно статичным, iOS 8 представила реальное взаимодействие и связь между приложениями.
streem 04
@Justafinger Этот метод iOS 7 предназначен только для создания URL-адреса для записи и чтения данных между общими приложениями. Этот конкретный метод действительно полезен (насколько я знаю) только для виджетов, но не для других расширений.
Wayne Hartman
Что ж, я считаю, что Apple хотела упростить это в iOS 8 без необходимости создавать контейнер программно и делиться пользовательскими файлами. В документации указано, что вы должны иметь возможность обмениваться данными с помощью NSUserDefault. Думаю, я что-то упускаю, потому что это не работает для меня.
streem 04
@Justafinger Я тоже не могу приступить NSUserDefaultsк работе. Я считаю, что это ошибка Beta 1.
Уэйн Хартман
@WayneHartman Есть обходной путь для NSUserDefaultsбазы данных. Смотрите мой ответ.
Санта-Клаус
6

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

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

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

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

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

  1. Представьте, что вы установили ДА для клавиши, когда пользователю был показан специальный вводный экран приложения. Другое приложение теперь также будет читать ДА и не показывать вступление.
  2. Да, некоторые приложения также хранят токены 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
блэкджек
источник
8
Ваши проблемы существуют, потому что вы смешиваете все свои данные в общих UserDefaults. Вы должны использовать NSUserDefaults.standardUserDefaults()для данных, которые не должны передаваться.
Daniel
2

Хранить

let shared: NSUserDefaults = NSUserDefaults(suiteName: "group.abcapp")!
shared.setObject("abc.png", forKey: "favEmoji")
shared.synchronize()
Хардик Таккар
источник