2017-05-14 6 views
0

ich Teile einer App Umschreiben und fand diesen Code:Wie verwendet man KVO für UserDefaults in Swift?

fileprivate let defaults = UserDefaults.standard 

func storeValue(_ value: AnyObject, forKey key:String) { 
    defaults.set(value, forKey: key) 
    defaults.synchronize() 

    NotificationCenter.default.post(name: Notification.Name(rawValue: "persistanceServiceValueChangedNotification"), object: key) 
} 
func getValueForKey(_ key:String, defaultValue:AnyObject? = nil) -> AnyObject? { 
    return defaults.object(forKey: key) as AnyObject? ?? defaultValue 
} 

Wenn CMD-Klick auf die Linie defaults.synchronize() ich sehe, dass synchronize veraltet ist geplant. Dies wird in dem Code geschrieben:

/*! 
    -synchronize is deprecated and will be marked with the NS_DEPRECATED macro in a future release. 

    -synchronize blocks the calling thread until all in-progress set operations have completed. This is no longer necessary. Replacements for previous uses of -synchronize depend on what the intent of calling synchronize was. If you synchronized... 
    - ...before reading in order to fetch updated values: remove the synchronize call 
    - ...after writing in order to notify another program to read: the other program can use KVO to observe the default without needing to notify 
    - ...before exiting in a non-app (command line tool, agent, or daemon) process: call CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication) 
    - ...for any other reason: remove the synchronize call 
    */ 

Soweit ich interpretieren kann, die Verwendung in meinem Fall paßt die zweite Beschreibung: nach Schreiben synchronisieren, um andere zu informieren.

Es schlägt vor KVO zu verwenden, aber wie? Wenn ich danach suche, finde ich ein paar etwas ältere Objective-C-Beispiele. Was ist die beste Vorgehensweise zum Beobachten von UserDefaults?

+0

http://Stackoverflow.com/a/28744491/1419216 vielleicht, was Sie suchen. –

+0

können Sie einen Beobachter für 'UserDefaults.didChangeNotification' hinzufügen –

Antwort

0

Aus dem Blog von David Smith http://dscoder.com/defaults.html https://twitter.com/catfish_man/status/674727133017587712

Wenn ein Prozess einen gemeinsamen Standard setzt, meldet dann ein anderer Prozess zu es lesen, dann können Sie in einer der sehr wenigen verbleibenden Situationen dass es nützlich ist, die Methode -synchronize in: -synchronize acts als "Barriere" aufzurufen, da sie eine Garantie bietet, dass, sobald sie zurückgegeben hat, jeder andere Prozess, der diese Vorgabe liest, den neuen Wert sieht alter Wert.

Für Anwendungen auf iOS 9.3 und später/macOS Sierra und später wird -synchronize nicht erforderlich (oder empfohlen) auch in dieser Situation, da Schlüsselwert Beobachtung von Vorgaben arbeitet zwischen Prozessen nun, so die Leseprozess kann nur direkt für den Wert zu ändern. Als Ergebnis davon sollten Anwendungen, die auf diesen Betriebssystemen ausgeführt werden, im Allgemeinen niemals aufrufsynchronisieren.

Also in den meisten Fällen müssen Sie nicht auf Anruf synchronisieren einstellen. Es wird automatisch von KVO behandelt.

Um dies zu tun, müssen Sie Beobachter hinzufügen in Ihren Klassen, wo Sie persistanceServiceValueChangedNotification Benachrichtigung behandeln. Lassen Sie sagen, Sie einen Schlüssel mit dem Namen "myKey" in der Klasse

hinzufügen Beobachter setzen können viewDidLoad etc

UserDefaults.standard.addObserver(self, forKeyPath: "myKey", options: NSKeyValueObservingOptions.new, context: nil) 

Behandeln Sie den Beobachter

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { 

    //do your changes with for key 
} 

Auch in deinit Ihre Beobachter entfernen

2

Ab iOS 11 + Swift 4 wird die blockbasierte KVO-API (gemäß SwiftLint) empfohlen.

Beispiel:

Lassen Sie sich sagen, ich habe einen Wert integer in meinen Benutzereinstellungen gespeichert und es greetingsCount genannt.

Zuerst muss ich UserDefaults verlängern:

extension UserDefaults { 
    @objc dynamic var greetingsCount: Int { 
     return integer(forKey: "greetingsCount") 
    } 
} 

Dies ermöglicht es uns später auf den Schlüsselpfad für die Beobachtung, wie folgt zu definieren:

var observer: NSKeyValueObservation? 

init() { 
    observer = UserDefaults.standard.observe(\.greetingsCount, options: [.initial, .new], changeHandler: { (defaults, change) in 
     // your change logic here 
    }) 
} 

Und nie vergessen, bis zu reinigen:

deinit { 
    observer?.invalidate() 
} 
Verwandte Themen