NSUserDefaults funktioniert nicht mit Xcode Beta mit Watch OS2

Ich habe gerade die neueste Beta von Xcode installiert, um Swift 2 zu testen und die Verbesserungen, die im Entwicklungsteil der Apple Watch gemacht wurden.

Es fällt mir wirklich schwer herauszufinden, warum diese grundlegende NSUserDefaults Methode, um Informationen zwischen iOS und Watch OS2 NSUserDefaults , nicht funktioniert.

Ich folgte dieser Schritt-für-Schritt- Anleitung , um zu prüfen, ob ich etwas verpasst habe, wie zum Beispiel die gleiche Gruppe für die Telefonanwendung und die Nebenstelle einzuschalten , aber hier ist, was ich bekam: NICHTS .

Hier ist, was ich für den ViewController in der iPhone App geschrieben habe:

 import UIKit class ViewController: UIViewController { @IBOutlet weak var lb_testo: UITextField! let shared_defaults:NSUserDefaults = NSUserDefaults(suiteName: "group.saracanducci.test")! var name_data:NSString? = "" override func viewDidLoad() { super.viewDidLoad() name_data = shared_defaults.stringForKey("shared") lb_testo.text = name_data as? String } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } @IBAction func upgrade_name(sender: AnyObject) { name_data = lb_testo.text shared_defaults.setObject(name_data, forKey: "shared") lb_testo.resignFirstResponder() shared_defaults.synchronize() } } 

Und hier ist, was ich im InterfaceController für WatchKit habe:

 import WatchKit import Foundation class InterfaceController: WKInterfaceController { @IBOutlet var lb_nome: WKInterfaceLabel! let shared_defaults:NSUserDefaults = NSUserDefaults(suiteName: "group.saracanducci.test")! var name_data:NSString? = "" override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) } override func willActivate() { super.willActivate() if (shared_defaults.stringForKey("shared") != ""){ name_data = shared_defaults.stringForKey("shared") lb_nome.setText(name_data as? String) }else{ lb_nome.setText("No Value") } } override func didDeactivate() { super.didDeactivate() } } 

Ich habe einige Tests gemacht und es scheint, als ob die iOS App und das Watch OS die Vorteile verschiedener Gruppen nutzen … sie teilen keine Informationen , sie speichern sie lokal.

Hat jemand das gleiche Problem? Irgendeine Idee, wie man es repariert?

    Mit Watch OS2 können Sie keine gemeinsamen Gruppencontainer mehr verwenden. Apple-Dokumente:

    Sehen Sie sich Apps an, die mit ihren iOS-Apps Daten über einen gemeinsamen Gruppencontainer gemeinsam nutzen, um die Daten anders zu behandeln. In watchOS 2 muss jeder process eine eigene Kopie aller freigegebenen Daten im lokalen Containerverzeichnis verwalten. Für Daten, die tatsächlich von beiden Apps freigegeben und aktualisiert werden, muss das Watch Connectivity-Framework verwendet werden, um diese Daten zwischen ihnen zu verschieben.

    NSUserDefaults (auch mit App-Gruppen) synchronisieren nicht zwischen dem iPhone und der Watch in watchOS 2. Wenn Sie die Einstellungen entweder von Ihrer iPhone-App oder dem Settings-Watch.bundle synchronisieren möchten, müssen Sie die Synchronisierung selbst vornehmen.

    Ich habe festgestellt, dass die Verwendung von WatchConnectivity-Benutzerinformationen in diesem Fall sehr gut funktioniert. Im Folgenden finden Sie ein Beispiel, wie Sie dies umsetzen können. Der Code behandelt nur die unidirektionale Synchronisierung vom Telefon zur Uhr, aber die andere Methode funktioniert genauso.

    In der iPhone App :
    1) Bereiten Sie das Wörterbuch der Einstellungen vor, die synchronisiert werden müssen

     - (NSDictionary *)exportedSettingsForWatchApp { NSUserDefaults *userDefaults = [self userDefaults]; // the user defaults to sync NSSet *keys = [self userDefaultKeysForWatchApp]; // set of keys that need to be synced NSMutableDictionary *exportedSettings = [[NSMutableDictionary alloc] initWithCapacity:keys.count]; for (NSString *key in keys) { id object = [userDefaults objectForKey:key]; if (object != nil) { [exportedSettings setObject:object forKey:key]; } } return [exportedSettings copy]; } 

    2) Bestimmen Sie, wann die Einstellungen an die Uhr übertragen werden müssen
    (hier nicht gezeigt)

    3) Drücken Sie die Einstellungen auf die Uhr

     - (void)pushSettingsToWatchApp { // Cancel current transfer [self.outstandingSettingsTransfer cancel]; self.outstandingSettingsTransfer = nil; // Cancel outstanding transfers that might have been started before the app was launched for (WCSessionUserInfoTransfer *userInfoTransfer in self.session.outstandingUserInfoTransfers) { BOOL isSettingsTransfer = ([userInfoTransfer.userInfo objectForKey:@"settings"] != nil); if (isSettingsTransfer) { [userInfoTransfer cancel]; } } // Mark the Watch as requiring an update self.watchAppHasSettings = NO; // Only start a transfer when the watch app is installed if (self.session.isWatchAppInstalled) { NSDictionary *exportedSettings = [self exportedSettingsForWatchApp]; if (exportedSettings == nil) { exportedSettings = @{ }; } NSDictionary *userInfo = @{ @"settings": exportedSettings }; self.outstandingSettingsTransfer = [self.session transferUserInfo:userInfo]; } } 

    In der Watch-Erweiterung :
    4) Empfangen Sie die Benutzerinfoübertragung

     - (void)session:(WCSession *)session didReceiveUserInfo:(NSDictionary *)userInfo { NSDictionary *settings = [userInfo objectForKey:@"settings"]; if (settings != nil) { // Import the settings [self importSettingsFromCompanionApp:settings]; } } 

    5) Speichern Sie die empfangenen Einstellungen in den Benutzereinstellungen auf der Uhr

     - (void)importSettingsFromCompanionApp:(NSDictionary *)settings { NSUserDefaults *userDefaults = [self userDefaults]; // the user defaults to sync NSSet *keys = [self userDefaultKeysForWatchApp]; // set of keys that need to be synced for (NSString *key in keys) { id object = [settings objectForKey:key]; if (object != nil) { [userDefaults setObject:object forKey:key]; } else { [userDefaults removeObjectForKey:key]; } } [userDefaults synchronize]; } 

    Es gibt eine einfache Möglichkeit, die alte functionalität zu reproduzieren, ich exportiere die alten Gruppenbenutzerstandards in ein Wörterbuch, sende das über das WatchConnectivity-Framework und importiere sie dann auf der anderen Seite in Benutzerstandardwerte:

    In beiden Telefon- und Uhr-Apps:

    1. Fügen Sie das WatchConnectivity-Framework hinzu
    2. #import und als WCSessionDelegate deklarieren
    3. Fügen Sie Code zum Starten der Sitzung hinzu, nachdem die App gestartet wurde:

       if ([WCSession isSupported]) { WCSession* session = [WCSession defaultSession]; session.delegate = self; [session activateSession]; } 
    4. Verwenden Sie diese Option, um die aktualisierten Standardeinstellungen an das andere Gerät zu senden (rufen Sie nach dem aktuellen [defaults synchronize] ):

    [[WCSession defaultSession] updateApplicationContext:[[[NSUserDefaults alloc] initWithSuiteName:@"group.com.company.myapp"] dictionaryRepresentation] error:nil];

    1. Empfangen und speichern Sie die Einstellungen wieder auf den Standard – fügen Sie dies dem WCDelegate hinzu:

       -(void)session:(WCSession *)session didReceiveApplicationContext:(NSDictionary *)applicationContext { NSLog(@"New Session Context: %@", applicationContext); NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.company.myapp"]; for (NSString *key in applicationContext.allKeys) { [defaults setObject:[applicationContext objectForKey:key] forKey:key]; } [defaults synchronize]; } 

    Achten Sie darauf, die Unterstützung für Nicht-WC-Geräte aufrechtzuerhalten. Umschließen Sie Ihre updateApplicationContext-Aufrufe mit if ([WCSession isSupported])

    Wie bereits erwähnt, funktioniert shared NSUserDefaults nicht mehr auf WatchOS2.

    Hier ist die schnelle Version von @ RichAbles Antwort mit ein paar weiteren Notizen.

    Gehen Sie in Ihrer iPhone App folgendermaßen vor:

    Wählen Sie den View-Controller aus, von dem Sie Daten an die Apple Watch übertragen möchten, und fügen Sie das Framework oben hinzu.

     import WatchConnectivity 

    Stellen Sie jetzt eine WatchConnectivity-Sitzung mit der Uhr her und senden Sie einige Daten.

     if WCSession.isSupported() { //makes sure it's not an iPad or iPod let watchSession = WCSession.defaultSession() watchSession.delegate = self watchSession.activateSession() if watchSession.paired && watchSession.watchAppInstalled { do { try watchSession.updateApplicationContext(["foo": "bar"]) } catch let error as NSError { print(error.description) } } } 

    Bitte beachten Sie, dass dies NICHT funktioniert, wenn Sie den Delegaten überspringen. Selbst wenn Sie ihn nie benutzen, müssen Sie ihn setzen und diese Erweiterung hinzufügen:

     extension MyViewController: WCSessionDelegate { } 

    Nun, in Ihrer Watch-App (dieser genaue Code funktioniert auch für Glances und andere App-Typen für Watchkits) fügen Sie das Framework hinzu:

     import WatchConnectivity 

    Dann richten Sie die Verbindungssitzung ein:

     override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) let watchSession = WCSession.defaultSession() watchSession.delegate = self watchSession.activateSession() } 

    und Sie hören einfach zu und bearbeiten die Nachrichten von der iOS App:

     extension InterfaceController: WCSessionDelegate { func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) { print("\(applicationContext)") dispatch_async(dispatch_get_main_queue(), { //update UI here }) } } 

    Das ist alles dazu.

    Punkte der Anmerkung:

    1. Sie können einen neuen Anwendungskontext beliebig oft senden und es spielt keine Rolle, ob die Uhr in der Nähe und verbunden ist oder ob die Überwachungs-App ausgeführt wird. Dadurch werden die Daten intelligent im Hintergrund übertragen und die Daten warten beim Start der Watch-App.
    2. Wenn Ihre Überwachungs-App tatsächlich aktiv ist und ausgeführt wird, sollte sie die Nachricht in den meisten Fällen sofort erhalten.
    3. Sie können diesen Code umkehren, damit die Uhr auf dieselbe Weise Nachrichten an die iPhone App sendet.
    4. Anwendungsbericht, den Ihre Überwachungs-App beim Anzeigen empfängt, ist NUR die letzte Nachricht, die Sie gesendet haben. Wenn Sie 20 Nachrichten gesendet haben, bevor die Watch-App angezeigt wird, werden die ersten 19 ignoriert und die 20. behandelt.
    5. Um eine direkte / harte Verbindung zwischen den beiden Apps herzustellen oder um Dateien im Hintergrund zu übertragen oder Nachrichten in Warteschlangen einzureihen, schauen Sie sich die WWDC-Videowiedergabe an .

    Ich brauchte Stunden und Stunden, um das zu erreichen. Schau dir dieses sehr nützliche Video an! Es gibt Ihnen die Grundidee, WatchConnectivity zu verwenden, um NSUserDefault zwischen der iPhone App und wacth!

    https://www.youtube.com/watch?v=VblFPEomUtQ