🏆 151 курс за 1 подписку: хватит выбирать — бери все и сразу!

Один клик — 151 возможность. Подпишись на OTUS сейчас!
Техномир мчится вперед, а вместе с ними растут и требования к специалистам. OTUS придумал крутую штуку — подписку на 151 курс по всем ключевым направлениям IT!
-
Почему подписка OTUS меняет правила игры:
- Доступ к 151 курсу от практикующих экспертов
- В 3 раза выгоднее, чем покупать каждый курс отдельно
- До 3 курсов одновременно без дополнительных затрат
- Свобода выбора направления — меняй треки когда угодно
Изучай новое, развивайся в своем темпе, меняй направления — подпишись на OTUS и прокачивай скилы по полной!
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576. Erid 2VtzqupFnNL
Так или иначе, но в виджеты необходимо передавать информацию из основного приложения. Это может быть все что угодно: от выбранного пользователем формата времени до полученных писем в почтовом клиенте. В этой статье я расскажу об основных способах передачи данных между таргетами приложения.
AppGroup
Таргет виджетов не является чем-то уникальным и работает примерно так же, как и остальные таргеты других app extensions. И для передачи информации по разным таргетам сначала надо добавить в приложение AppGroup. Во вкладке Signing & Capabilities основного таргета вашего проекта нужно нажать на кнопку + Capability и в новом окно выбрать App Groups. Хорошей практикой является назвать AppGroup как “group.” + buindle id приложения.

После этого можно добавить id
вашей AppGroups в константы, добавить файл констант в таргет виджетов и иметь доступ к id
везде, где понадобится, например, так:
import Foundation
struct Constants {
static let appGroupID = "group.com.nadzeya.widgetsSandbox"
}

Теперь мы готовы передавать данные между таргетами, и начнем с самого простого – UserDefaults
.
UserDefaults
UserDefaults
в Swift – это класс, который предоставляет возможность сохранять пары ключ-значение в пользовательскую встроенную базу данных. В нее можно сохранять значения разных типов данных – String, Bool, Data, Date, Array, Dictionary и проч. В основном UserDefaults
используются для хранения некоторых настроек приложения и/или пользовательских предпочтений, таких как выбранный формат времени и даты, темная или светлая тема приложения, если, конечно, приложение поддерживает это. Также еще в UserDefaults
можно хранить что-то важное для аналитики или отображения некоторых экранов, например, дату первой сессии приложения. И для того, чтобы была возможность использовать в разных таргетах сохраненные в UserDefaults
значения, нам надо их сохранять в главном таргете не в UserDefaults.standard
:
UserDefaults.standard.set("my_value", forKey: "myValueKey")
а в наш контейнер AppGroup:
UserDefaults(suiteName: Constants.appGroupID)!.set("my_value", forKey: "myValueKey")
И мы тогда сможем читать сохраненные данные в таргете виджета таким образом. Допустим, мы сохранили что-то типом String:
let savedValue = UserDefaults(suiteName: Constants.appGroupID)!.string(forKey: "myValueKey")
Вот так просто меняется работа с UserDefaults
и теперь мы можем через них передавать нужные нам данные в таргет виджета.
File Container
UserDefaults
отлично справляются с хранением чего-то небольшого, но если есть задача передать в таргет виджетов нечто большее, чем пользовательские настройки, а базы данных в приложении нет, то можно использовать File Container и хранить необходимые данные, например в .plist
-файле или в .json
-файле. Для этого нам надо создать нужный нам файл в File Container для нашей App Group и записать в него информацию:
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.appGroupID)!
let fileURL = containerURL.appendingPathComponent("savedDataForWidgets.json")
do {
let encoded = try JSONEncoder().encode(myWidgetData)
try! encoded.write(to: fileURL)
} catch {
print( error)
}
И, соответственно, вот так можно читать эту информацию в таргете виджета:
var widgetData: [MyWidgetData] = []
guard let data = try? Data(contentsOf: url) else {
return widgetData
}
do {
widgetData = try JSONDecoder().decode([MyWidgetData].self, from: data)
} catch {
print(error)
}
CoreData
В большом количестве приложений используются CoreData для хранения данных, и для того, чтобы можно было ею пользоваться в таргете виджетов, надо создать общий CoreData контейнере в AppGroup:
let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.appGroupID)!
let storeURL = containerURL.appendingPathComponent("MyWidgetDataModel.sqlite")
let description = NSPersistentStoreDescription(url: storeURL)
let container = NSPersistentContainer(name: "MyWidgetDataModel")
container.persistentStoreDescriptions = [description]
container.loadPersistentStores { ... }
И теперь мы можем получать наши данные в таргете виджета вот так:
let managedObjectContext = CoreDataStack.shared.managedObjectContext
let predicate = NSPredicate(format: "id == %@", "widgetID")
let request = NSFetchRequest<SomeItem>(entityName: "MyWidget")
let result = try managedObjectContext.fetch(request)
Кроме CoreData, есть и другие базы данных, но принцип везде примерно одинаковый: можно добавить файлы базы данных в таргет виджета и уже в нем напрямую запрашивать необходимую информацию. Есть только одно но: виджеты ни в каком виде не поддерживают асинхронный код, то есть и запросы за данными надо будет делать синхронно.
Я постаралась подробно рассказать об основных способах передачи данных из основного таргета приложения в таргет виджетов. Надеюсь, что эта статья была полезной. Я буду рада фидбэку и комментариям. Спасибо!
Савицкая Надежда, iOS-разработчик.
Комментарии