Совместное использование значений UserDefaults между расширениями

Создавая виджет «Сегодня», я использую UserDefaults(suiteName:) для сохранения некоторых данных. В основном приложении я использую UserDefaults.standard(). Это не может быть прочитано (или может?) Расширением, поэтому я использую конструктор suiteName:.

Данные, которые пользователь сохраняет UserDefaults.standard() в основном приложении, должны быть доступны в расширении.

В настоящее время я настаиваю на обоих, чтобы можно было поделиться ценностями.

 UserDefaults.standard().set:...forKey:...
 UserDefaults(suiteName:...)().set:...forKey:...
 ...

Вопрос в том, следует ли мне отбросить UserDefaults.standard() все вместе и просто использовать UserDefaults(suiteName:) в своем приложении, или это плохая практика, и если да, то почему?

Изменить: я использую контейнер группы приложений. Для пояснения я спрашиваю, следует ли мне просто заменить standard() на suiteName: в моем проекте?


person RyanTCB    schedule 10.08.2017    source источник
comment
если вы хотите разделить ресурсы между расширением и приложением, лучший способ - создать группу приложений и использовать только общий UserDefault (по -suiteName:) или FileManager по умолчанию (по -forSecurityApplicationGroupIdentifier:) - вы можете больше не нужны стандартные пользовательские настройки по умолчанию или файловый менеджер (но если вам нужно быть уверенным, что вы хотите изолировать данные от расширения, вы все равно можете использовать эти песочницы).   -  person holex    schedule 10.08.2017


Ответы (6)


Вы не можете использовать UserDefaults.standard для обмена данными между основным приложением и его расширением. Вместо этого вам нужно создать общий контейнер с UserDefaults(suiteName:) для обмена данными.

Несмотря на то, что пакет расширения приложения вложен в пакет приложения, в котором оно находится, у запущенного расширения приложения и содержащего приложение нет прямого доступа к контейнерам друг друга.

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

После включения групп приложений расширение приложения и содержащее его приложение могут использовать NSUserDefaults API для совместного доступа к пользовательским настройкам. Чтобы включить это совместное использование, используйте метод initWithSuiteName: для создания экземпляра нового объекта NSUserDefaults, передав идентификатор общей группы.

Для получения дополнительной информации см .: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1.

Как использовать группы приложений: https://github.com/pgpt10/Today-Widget

Стандартный или SuiteName?

Используйте стандартный для данных, предназначенных только для хост-приложения. Используйте suiteName для данных, которые вы хотите передать между расширением и хост-приложением. Только не сохраняйте одни и те же данные в них обоих. Избегайте избыточности данных. Используйте их оба в зависимости от контекста.

person PGDev    schedule 10.08.2017
comment
Приносим свои извинения. Я предположил, что, когда я использовал initSuiteName:, это уже создавало впечатление, что я использую группу приложений. Какая я. Обновлен OQ, чтобы прояснить это. Спасибо - person RyanTCB; 10.08.2017
comment
Итак, с какой проблемой вы столкнулись? - person PGDev; 10.08.2017
comment
В настоящее время я сохраняю одни и те же данные как для стандартных конструкторов, так и для конструкторов suiteName. Должен ли я просто отказаться от standard () и использовать suiteName. - person RyanTCB; 10.08.2017
comment
Используйте стандартный для данных, предназначенных только для хост-приложения. Используйте suiteName для данных, которые вы хотите передать между расширением и хост-приложением. Только не сохраняйте одни и те же данные в них обоих. Избегайте избыточности данных. Используйте их оба в зависимости от контекста. - person PGDev; 10.08.2017

Простой пример, в котором я создаю общий пакет:

if let userDefaults = UserDefaults(suiteName: "group.your.bundle.here") {
    userDefaults.set("test 1" as AnyObject, forKey: "key1")
    userDefaults.set("test 2" as AnyObject, forKey: "key2")
    userDefaults.synchronize()
}

Вот как вы можете прочитать это позже:

if let userDefaults = UserDefaults(suiteName: "group.your.bundle.here") {
    let value1 = userDefaults.string(forKey: "key1")
    let value2 = userDefaults.string(forKey: "key2")
    ...
}
person oskarko    schedule 09.03.2018
comment
Вам не нужно звонить synchroniz - person BilalReffas; 21.06.2019
comment
На самом деле это не отвечает на вопрос, какой из них использовать. Если вы сделаете то, что написали, это не сработает, если данные были сохранены из хост-приложения с помощью UserDefaults.standard (). - person Anuran Barman; 08.08.2019
comment
Благодарю. это помогло. Мне нравится отвечать с поддержкой кода. - person N J; 18.09.2019

Убедитесь, что App Groups включен для ВСЕ ВАШИ ЦЕЛИ (цели вашего приложения и расширений) на вкладке Возможности.

введите описание изображения здесь

А затем используйте указанный выше идентификатор группы в качестве имени набора при создании UserDefaults:

let userDefaults = UserDefaults(suiteName: "group.com.YourCompany.YourApp")
person Tai Le    schedule 10.03.2019
comment
Этот шаг ОЧЕНЬ важен. - person P. Ent; 19.11.2020

Также убедитесь, что вы добавляете группы приложений в правильную конфигурацию (отладка, выпуск). Если вы добавите группы приложений в отладку для целевого приложения и попытаетесь использовать их в конфигурации выпуска для своего расширения, это не сработает.

Если вы добавляете конфигурацию отладки (для цели приложения), используйте ее в конфигурации отладки (для цели расширения)

person Rahul Chhetri    schedule 04.03.2020
comment
Это было так просто, и я теряю час. Спасибо что подметил это - person Swift Sharp; 10.03.2020
comment
Мне жаль, что я не прочитал этот пост, прежде чем потратить 3 часа ... Моя группа расширений была только в профиле ... - person mrj; 11.03.2021

PGDev: увеличение:

вы не можете избежать избыточности при перетаскивании настроек (предпочтений) https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html к расширению: они содержатся в частном пакете приложения и должны быть реплицированы в пакет с именем, чтобы стать доступным для расширения приложения

person Anton Tropashko    schedule 05.03.2020

Кроме того, убедитесь, что вы очистили и перестроили все приложение после добавления группы приложений.

person Sacha.R    schedule 19.03.2021