Этот вопрос возникает постоянно.
Одно из предложений - создать одноэлементный контейнер данных: объект, который создается один раз и только один раз в жизни вашего приложения и сохраняется на протяжении всего срока службы вашего приложения.
Этот подход хорошо подходит для ситуации, когда у вас есть глобальные данные приложения, которые должны быть доступны / изменены в разных классах вашего приложения.
Другие подходы, такие как установка односторонних или двусторонних связей между контроллерами представления, лучше подходят для ситуаций, когда вы передаете информацию / сообщения напрямую между контроллерами представления.
(См. Ответ nhgrif ниже для других альтернатив.)
Используя синглтон контейнера данных, вы добавляете свойство в свой класс, в котором хранится ссылка на ваш синглтон, а затем используете это свойство в любое время, когда вам нужен доступ.
Вы можете настроить свой синглтон так, чтобы он сохранял его содержимое на диск, чтобы состояние вашего приложения сохранялось между запусками.
Я создал демонстрационный проект на GitHub, демонстрирующий, как это можно сделать. Вот ссылка:
Проект SwiftDataContainerSingleton на GitHub
Вот README из этого проекта:
SwiftDataContainerSingleton
Демонстрация использования синглтона контейнера данных для сохранения состояния приложения и совместного использования его между объектами.
В DataContainerSingletonКласс является фактическим синглтоном.
Он использует статическую константу sharedDataContainer для сохранения ссылки на синглтон.
Для доступа к синглтону используйте синтаксис
DataContainerSingleton.sharedDataContainer
Пример проекта определяет 3 свойства в контейнере данных:
var someString: String?
var someOtherString: String?
var someInt: Int?
Чтобы загрузить someIntсвойство из контейнера данных, вы должны использовать следующий код:
let theInt = DataContainerSingleton.sharedDataContainer.someInt
Чтобы сохранить значение в someInt, вы должны использовать синтаксис:
DataContainerSingleton.sharedDataContainer.someInt = 3
Метод DataContainerSingleton initдобавляет наблюдателя для UIApplicationDidEnterBackgroundNotification. Этот код выглядит так:
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
UIApplicationDidEnterBackgroundNotification,
object: nil,
queue: nil)
{
(note: NSNotification!) -> Void in
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
defaults.synchronize()
}
В коде наблюдателя он сохраняет свойства контейнера данных в NSUserDefaults. Вы также можете использоватьNSCoding Core Data или различные другие методы для сохранения данных о состоянии.
Метод DataContainerSingleton initтакже пытается загрузить сохраненные значения для своих свойств.
Эта часть метода инициализации выглядит так:
let defaults = NSUserDefaults.standardUserDefaults()
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
Ключи для загрузки и сохранения значений в NSUserDefaults хранятся как строковые константы, которые являются частью структуры DefaultsKeys, определенной следующим образом:
struct DefaultsKeys
{
static let someString = "someString"
static let someOtherString = "someOtherString"
static let someInt = "someInt"
}
Вы ссылаетесь на одну из этих констант следующим образом:
DefaultsKeys.someInt
Использование синглтона контейнера данных:
В этом примере приложения трижды используется одноэлементный контейнер данных.
Есть два контроллера представления. Первый - это настраиваемый подкласс UIViewController ViewController, а второй - настраиваемый подкласс UIViewController SecondVC.
На обоих контроллерах представления есть текстовое поле, и оба загружают значение из someIntсвойства singlelton контейнера данных в текстовое поле своегоviewWillAppear метода, и оба сохраняют текущее значение из текстового поля обратно в someInt контейнера данных.
Код для загрузки значения в текстовое поле находится в viewWillAppear:методе:
override func viewWillAppear(animated: Bool)
{
let value = DataContainerSingleton.sharedDataContainer.someInt ?? 0
textField.text = "\(value)"
}
Код для сохранения отредактированного пользователем значения обратно в контейнер данных находится в textFieldShouldEndEditingметодах контроллеров представления :
func textFieldShouldEndEditing(textField: UITextField) -> Bool
{
DataContainerSingleton.sharedDataContainer.someInt = textField.text!.toInt()
return true
}
Вы должны загружать значения в свой пользовательский интерфейс в viewWillAppear, а не viewDidLoad, чтобы ваш пользовательский интерфейс обновлялся каждый раз, когда отображается контроллер представления.