Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UserDefaults is not saved with Swift

I'm trying to use the UserDefaults to persistently save a boolean value. This is my code :

public static var isOffline = UserDefaults.standard.bool(forKey: "isOffline") {
    didSet {
        print("Saving isOffline flag which is now \(isOffline)")
        UserDefaults.standard.set(isOffline, forKey: "isOffline")
        UserDefaults.standard.synchronize()
    }
}

Why doesn't work? What is the problem in this code?

The problem is that when I try to retrieve "isOffline" key from UserDefaults I always get a false.

I set the isOffline in the .onChange method of the row (I'm using Eureka as framework to create forms). The flag keep the right value during the lifecycle of the app, but when I close it that value is probably removed in some way.

like image 603
Andrea Mario Lufino Avatar asked Dec 23 '16 13:12

Andrea Mario Lufino


People also ask

How do you save UIImage in UserDefaults Swift?

We add an import statement for the UIKit framework and load an image with name landscape. This is just an example to illustrate the concept. We then convert the UIImage instance to a Data object by invoking the pngData() method on the UIImage instance.

Where is UserDefaults saved?

Storing Data in User Defaults The user's defaults database is stored on disk as a property list or plist. A property list or plist is an XML file. At runtime, the UserDefaults class keeps the contents of the property list in memory to improve performance.

How data is stored in UserDefaults?

Updating the Prospects initializer so that it loads its data from UserDefaults where possible. Adding a save() method to the same class, writing the current data to UserDefaults . Calling save() when adding a prospect or toggling its isContacted property.

How do I use UserDefaults in swift 5?

Writing or Setting Values To User Defaults You simply invoke the set(_:forKey:) method on the UserDefaults instance. In this example, we set the value of myKey to true by invoking the set(_:forKey:) method on the shared defaults object.


3 Answers

try to change

UserDefaults.standard.set(isOffline, forKey: "isOffline")

to

UserDefaults.standard.setValue(isOffline, forKey: "isOffline")

without the dispatch code

like image 43
Omar N Shamali Avatar answered Oct 13 '22 23:10

Omar N Shamali


I had the same problem and the issue was in the "didSet" block itself. I don't know why, but it does not work with userDefaults - it does not persist it properly and after killing the application all changes were gone.

Synchronize() does not help. I found out, this method is no longer necessary and it will be deprecated in future (this is comment in UserDefaults class):

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

By trial and error I found out, that it works, if I call it from main thread:

public static var isOffline = UserDefaults.standard.bool(forKey: "isOffline") {
    didSet {
        print("Saving isOffline flag which is now \(isOffline)")
        DispatchQueue.main.async {
            UserDefaults.standard.set(isOffline, forKey: "isOffline")
        }
    }
}

If anyone can explain, why it works on main thread and no other, I would be glad to hear it.

like image 53
Vojtech Kubat Avatar answered Oct 14 '22 00:10

Vojtech Kubat


Do Like this,

public static var isOffline:Bool {
    get {
       return UserDefaults.standard.bool(forKey: "isOffline")
    }
    set(newValue) {
        print("Saving isOffline flag which is now \(isOffline)")
        UserDefaults.standard.set(newValue, forKey: "isOffline")
        UserDefaults.standard.synchronize()
    }
}
like image 34
Venk Avatar answered Oct 13 '22 22:10

Venk