Cette question revient tout le temps.
Une suggestion consiste à créer un singleton de conteneur de données: un objet qui est créé une et une seule fois dans la vie de votre application et qui persiste pendant toute la durée de vie de votre application.
Cette approche est bien adaptée à une situation où vous avez des données d'application globales qui doivent être disponibles / modifiables dans différentes classes de votre application.
D'autres approches, telles que la mise en place de liens unidirectionnels ou bidirectionnels entre les contrôleurs de vue, sont mieux adaptées aux situations où vous transmettez des informations / messages directement entre les contrôleurs de vue.
(Voir la réponse de nhgrif, ci-dessous, pour d'autres alternatives.)
Avec un singleton de conteneur de données, vous ajoutez une propriété à votre classe qui stocke une référence à votre singleton, puis utilisez cette propriété chaque fois que vous en avez besoin.
Vous pouvez configurer votre singleton pour qu'il enregistre son contenu sur le disque afin que l'état de votre application persiste entre les lancements.
J'ai créé un projet de démonstration sur GitHub montrant comment vous pouvez le faire. Voici le lien:
Projet SwiftDataContainerSingleton sur GitHub
Voici le README de ce projet:
SwiftDataContainerSingleton
Une démonstration de l'utilisation d'un singleton de conteneur de données pour enregistrer l'état de l'application et le partager entre les objets.
La DataContainerSingleton
classe est le singleton réel.
Il utilise une constante statique sharedDataContainer
pour enregistrer une référence au singleton.
Pour accéder au singleton, utilisez la syntaxe
DataContainerSingleton.sharedDataContainer
L'exemple de projet définit 3 propriétés dans le conteneur de données:
var someString: String?
var someOtherString: String?
var someInt: Int?
Pour charger la someInt
propriété à partir du conteneur de données, vous utiliserez un code comme celui-ci:
let theInt = DataContainerSingleton.sharedDataContainer.someInt
Pour enregistrer une valeur dans someInt, vous utiliserez la syntaxe:
DataContainerSingleton.sharedDataContainer.someInt = 3
La init
méthode de DataContainerSingleton ajoute un observateur pour le UIApplicationDidEnterBackgroundNotification
. Ce code ressemble à ceci:
goToBackgroundObserver = NSNotificationCenter.defaultCenter().addObserverForName(
UIApplicationDidEnterBackgroundNotification,
object: nil,
queue: nil)
{
(note: NSNotification!) -> Void in
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code saves the singleton's properties to NSUserDefaults.
//edit this code to save your custom properties
defaults.setObject( self.someString, forKey: DefaultsKeys.someString)
defaults.setObject( self.someOtherString, forKey: DefaultsKeys.someOtherString)
defaults.setObject( self.someInt, forKey: DefaultsKeys.someInt)
//-----------------------------------------------------------------------------
//Tell NSUserDefaults to save to disk now.
defaults.synchronize()
}
Dans le code de l'observateur, il enregistre les propriétés du conteneur de données dans NSUserDefaults
. Vous pouvez également utiliser NSCoding
, Core Data ou diverses autres méthodes pour enregistrer les données d'état.
La init
méthode de DataContainerSingleton tente également de charger les valeurs enregistrées pour ses propriétés.
Cette partie de la méthode init ressemble à ceci:
let defaults = NSUserDefaults.standardUserDefaults()
//-----------------------------------------------------------------------------
//This code reads the singleton's properties from NSUserDefaults.
//edit this code to load your custom properties
someString = defaults.objectForKey(DefaultsKeys.someString) as! String?
someOtherString = defaults.objectForKey(DefaultsKeys.someOtherString) as! String?
someInt = defaults.objectForKey(DefaultsKeys.someInt) as! Int?
//-----------------------------------------------------------------------------
Les clés de chargement et d'enregistrement des valeurs dans NSUserDefaults sont stockées sous forme de constantes de chaîne faisant partie d'une structure DefaultsKeys
, définie comme ceci:
struct DefaultsKeys
{
static let someString = "someString"
static let someOtherString = "someOtherString"
static let someInt = "someInt"
}
Vous référencez l'une de ces constantes comme ceci:
DefaultsKeys.someInt
Utilisation du singleton du conteneur de données:
Cet exemple d'application fait un usage trival du singleton du conteneur de données.
Il existe deux contrôleurs de vue. Le premier est une sous-classe personnalisée de UIViewController ViewController
et le second est une sous-classe personnalisée de UIViewController SecondVC
.
Les deux contrôleurs de vue ont un champ de texte sur eux, et tous deux chargent une valeur de la someInt
propriété du conteneur de données singlelton dans le champ de texte de leur viewWillAppear
méthode, et tous deux enregistrent la valeur actuelle du champ de texte dans le `someInt 'du conteneur de données.
Le code pour charger la valeur dans le champ de texte est dans la viewWillAppear:
méthode:
override func viewWillAppear(animated: Bool)
{
//Load the value "someInt" from our shared ata container singleton
let value = DataContainerSingleton.sharedDataContainer.someInt ?? 0
//Install the value into the text field.
textField.text = "\(value)"
}
Le code pour enregistrer la valeur modifiée par l'utilisateur dans le conteneur de données se trouve dans les textFieldShouldEndEditing
méthodes des contrôleurs de vue :
func textFieldShouldEndEditing(textField: UITextField) -> Bool
{
//Save the changed value back to our data container singleton
DataContainerSingleton.sharedDataContainer.someInt = textField.text!.toInt()
return true
}
Vous devez charger des valeurs dans votre interface utilisateur dans viewWillAppear plutôt que viewDidLoad afin que votre interface utilisateur se mette à jour chaque fois que le contrôleur de vue est affiché.