Swift 3 / iOS 10 / TodayExtension - UserDefaults a

2019-05-21 00:23发布

问题:

This is my first Question on this site. I have a problem that I cannot fix.

I'm working on an easy note application with today extension. I have had no problem in Swift 2.2 and iOS 9. Problem just appears in Swift 2.3 and Swift 3, on iOS 10. The problem I have is the following :

User can write a note (saved in UserDefaults) and open Notification Center and watch his notes in a TodayExtension.

I have these methods to save notes in UserDefaults and retrieve it from UserDefaults (I'm using groups, so in Capabilities of my application and my extension, everything is set well - Furthermore, my objects have required NSCoding methods, of course) :

open class NoteManager: NSObject {

    private static let kKEY: String! = "Notes"
    private static let kSUITENAME: String! = "Team.group.bundleIdentifier"

    open static func saveNotes(_ notes: [Note]) {
        let notesData = NSKeyedArchiver.archivedData(withRootObject: notes)

        let defaults = UserDefaults(suiteName: kSUITENAME)!
        defaults.set(notesData, forKey: kKEY)
        defaults.synchronize()
    }

    open static func retrieveNotes() -> [Note] {
        let notesFromDefault = UserDefaults(suiteName: kSUITENAME)!.object(forKey: kKEY)
        var returnedNotes: [Note]! = [Note]()

        if notesFromDefault != nil {
            if let notesData: Data? = notesFromDefault as! Data! {
                NSKeyedUnarchiver.setClass(Note.self, forClassName: "Application_Name.Note")
                NSKeyedUnarchiver.setClass(Preference.self, forClassName: "Application_Name.Preferences")
                let unarchivedNotes = NSKeyedUnarchiver.unarchiveObject(with: notesData!) as? [Note]

                if let notes: [Note] = unarchivedNotes! as [Note]! {
                    returnedNotes = notes
                }
            }
        }

        return returnedNotes
    }
}

In the iOS Application I have NO problems. UserDefaults works well with this code. But when I open the TodayExtension the following line (in retrieveNotes()) always returns nil :

let notesFromDefault = UserDefaults(suiteName: kSUITENAME)!.object(forKey: kKEY)

So my TodayExtension always says that I have no notes. Do you have any ideas why this problem happens ?

Thank you for your help ! :)

回答1:

I had what i think is a similar issue (my issue specifically was that the defaults that were saved by a user under ios 9.x swift 2.x were not being retrieved in the new xcode8/swift3; the defaults were nil so i thought the data had been lost) and i traced this back to the simulator. Xcode8 introduced new simulators which are really just new "devices". I reverted my Xcode8 simulator back to an iOS 9.x version and the defaults were there as expected.

To add a simulator, scroll to the bottom of your iOS simulators list and click the 'Add Additional Simulator' and following prompts to get back to an iOS 9.x simulator.

Hopefully this helps!



回答2:

I partially solved my problem.

I have completely remove Xcode and all the settings (caches files etc...), then I have removed the "Team" part in the suite name.

Now I have like a warning in the Xcode console but I can retrieve my notes in my TodayExtension. Piouf !

I still have the problem for WatchKit Extension. I'm not sure but I think that I have read that UserDefaults even with App Groups are not shared with Apple Watch Extensions.

But Apple write in their documentation "Also, iOS automatically forwards a read-only copy of your iOS app’s preferences to Apple Watch. Your WatchKit extension can read those preferences using an NSUserDefaults object, but it cannot make changes directly to the defaults database."

So I don't know why I cannot retrieve my notes from my Apple Watch.

At least I have solved my first problem. If anybody has the same.