1

I have a framework that needs to save values locally, for that I chose UserDefaults.

However, the values are never saved, and the following read function always return "" after restarting the app

class Preferences {
    let preferences : UserDefaults

    init (preferences : UserDefaults) {
        self.preferences = preferences
    }

    // Private Key
    func savePrivateKey(key : String) {
        writeString(value: key, key: privateKeyKey)
    }

    func readPrivateKey() -> String! {
        return readString(key: privateKeyKey)
    }

    private func readString(key : String) -> String? {
        if preferences.object(forKey: key) == nil {
            return "bananas"
        } else {
            return preferences.string(forKey: key)
        }
    }

    private func writeString(value : String, key : String) {
        preferences.set(value, forKey: key)
    }

    fileprivate let privateKeyKey = "privateKey"
}

Initialized with:

let preferences = Preferences(preferences: UserDefaults.standard)

I have tried:

  • Simulator and physical Device
  • Debug and Release
  • UserDefaults and SwiftyUserDefaults

The strange thing is that this is saving the Bool values, but not the string ones.

I thought that this might be from not using correctly UserDefaults, but SwiftyUserDefaults gets the same result.

Vanethos
  • 691
  • 1
  • 8
  • 20
  • Have you tried to explicitly synchronize? (i.e. call `preferences.synchronize()` after writing? You should give it a try. – Lutz Oct 01 '19 at 07:41
  • Yes, and that is deprecated, `-synchronize is deprecated and will be marked with the NS_DEPRECATED macro in a future release.` – Vanethos Oct 01 '19 at 07:42
  • Have a look here : https://stackoverflow.com/questions/30087085/nsuserdefaults-and-ios-framework-library – CZ54 Oct 01 '19 at 07:47
  • @CZ54 I have seen that before, but isn't that to be used in the case that I want default values for the SDK? In my case, when the SDK starts we have no values stored and no default values, so I thought that this wasn't the approach – Vanethos Oct 01 '19 at 07:53
  • @Vanethos You want share value across you app and the framework ? – CZ54 Oct 01 '19 at 08:04
  • also @CZ54 what is mentioned in that answer is already deprecated (`UserDefaults.register`) – Vanethos Oct 01 '19 at 08:04
  • @CZ54, no, I just want the framework to be able to store and read values. If the app needs to access those values, it will be by a method from the framework – Vanethos Oct 01 '19 at 08:05

1 Answers1

1
import Foundation

public class AppDefaults {
    private let defaultStringKey = "DefaultString"
}

public extension AppDefaults {

    var defaultString: String? {
        get { return UserDefaults.standard.string(forKey: defaultStringKey) }
        set { UserDefaults.standard.set(newValue?.description, forKey: defaultStringKey) }
    }

}

I suggest you make a separate file called something like AppDefaults etc. You can then access each default as such

var text = AppDefaults().defaultString

You can then overwrite it and it will save automatically using

AppDefaults().defaultString = "Bananas"
HJDavies
  • 138
  • 7
  • that is not the issue, the issue is that the preferences are not being saved correctly, so every time I use `UserDefaults.standard.string` it always gives out `""` as the value, even if I set the default as `bananas` – Vanethos Oct 01 '19 at 09:25
  • @Vanethos have you tried setting and trying to read UserDefaults using the method I've shown above? From what you've shown the preferences isn't being initialised. You might need to show the full code to see what's going on. What's above looks like a much cleaner implementation. – HJDavies Oct 01 '19 at 09:31
  • 1
    @Vanethos I tested your updated code and did a print(Preferences(preferences: UserDefaults.standard).readPrivateKey()) and i got Optional("bananas") There must be something else affecting this.. – HJDavies Oct 01 '19 at 09:44
  • as stated in the question, this code is used in a Framework. Is that an issue? @HJDavies – Vanethos Oct 01 '19 at 09:45
  • The framework defaults to using "bananas"? haha. What framework is this out of curiosity. I'd suggest using your own implementation to handle user defaults if this isn't working unless it's required to use the framework. – HJDavies Oct 01 '19 at 09:53
  • "There must be something else affecting this.." THANK YOU SO MUCH! This was just some stupid wrapper code that I was using and neglected to check. THANK YOU! @HJDavies – Vanethos Oct 01 '19 at 09:56
  • Haha glad to hear. It's always the smallest bits that mess up and cause hours of pain! – HJDavies Oct 01 '19 at 10:07