I have been working on an app in which I user NSUserDefaults to persist a Dictionary for use elsewhere in the program. This been working perfectly since Beta 1. Now with the latest update (beta 5) this no longer works. It appears they have removed the ability to persist a swift Dictionary in this manner. However, I can persist an NSDictionary. Here is a code snippet that worked 2 days ago and now is broken.
var userDefaults = NSUserDefaults.standardUserDefaults()
userDefaults.setObject(allPlayersDict, forKey: "playerDict")
userDefaults.synchronize()
This code does not write anything to the NSUserDefaults, not even the key, when checked using:
var testDict = NSUserDefaults.standardUserDefaults().dictionaryRepresentation()
println(testDict)
Has anyone else experienced this or have a solution?
Related
I have a framework that is generating a device UUID once and saving it using UserDefaults. The app has access to the UserDefaults and everything works as expected. However, the framework is not accessing UserDefaults in some cases.
I sorted this out on an iPhone 8 using the synchronize() method:
func getDeviceID() -> String {
if let device = UserDefaults.standard.object(forKey: "DeviceID") as? String {
return device
} else {
let device = UUID().uuidString
UserDefaults.standard.set(device, forKey: "DeviceID")
UserDefaults.standard.synchronize() // this line helped with an iPhone 8
return device
}
}
However, on an older iPhone SE 1st generation the issue comes back.
First, why is this happening at all, and why is the synchronize() method seemingly helping in a newer device? (Both phones are running iOS 13)
Are there any known limitations when accessing UserDefaults from within a framework?
If it is failing when you're reading data right after writing the deviceId to UserDefaults
Then it could be related to how UserDefaults actually stores the data to disk.
The actual write to disk is asynchronous and batched automatically by NSUserDefaults.
Check this
So there's a chance that it is slower for older devices running new iOS versions.
Did anyone face an issue with Shared User Defaults via App Groups on iOS 11? I am saving a value in one of the extensions but I am not able to fetch same value via another extension.
In the first extension :
let defaults = UserDefaults.init(suiteName: Constants.commonSuite)
defaults.set("Sample", forKey: "SampleKey")
defaults.synchronize()
In the second extension :
let defaults = UserDefaults.init(suiteName: Constants.commonSuite)
let sampleString = defaults.object(forKey: "SampleKey")
print(sampleString)
Interestingly this thing works fine on iOS 10. Breaks on iOS 11
Had the same issue.
Suitename needs to be the same value as your app group name, not some arbitrary value.
Hope that helps!
I have an iPhone 7 , and I also use it for development. I noticed that in my app , I was storing a session token for auto login purposes into the NSUserDefaults. But sometimes , without removing it the session token was nil and the auto login is not working. This also happens to other apps , where some times it asks me to login again , although I already have. I am guessing that somehow to NSUserDefaults that most of the apps use are being erased somehow. Anyone having a similar issue ?
class func setSessionToken(_ token: String){
let defaults = UserDefaults.standard
defaults.setValue(token, forKey: sessionTokenKey)
defaults.synchronize()
}
class func getSessionToken()->String?{
let defaults = UserDefaults.standard
return defaults.string(forKey: sessionTokenKey)
}
This issue normally occurs when Running an iOS8 or 9 simulator followed by an iOS10 simulator and NSUserDefaults stop working in the simulator.
But, in your case if it is not working in iPhone also . You can try it with latest version of Xcode8 .
I'm not sure how to use the new UserDefaults class with the new Swift3 changes.
I had this code prior to the migration to swift3 which successfully retrieved the data stored in the userDefaults:
if NSUserDefaults.standardUserDefaults().objectForKey("profileArray") != nil {
profileArray = NSUserDefaults.standardUserDefaults().objectForKey("profileArray") as! [String]
}
With the migration to swift3 the code is now:
if UserDefaults.standard.object(forKey: "profileArray") != nil {
profileArray = UserDefaults.standard.object(forKey: "profileArray")! as! [NSString]
}
The new syntax makes sense but when I run the project the data that was previously stored in the user default seems to be gone.The userdefault.standard... is now returning empty/nil.
How do I retrieve the data that was stored prior to the swift3 migration?
Appreciate the help with moving to swift3!
I don't know if that solves your problem, but your syntax is not very efficient – you retrieve the object from user defaults unnecessarily twice.
The recommended way is optional binding and the dedicated method to get an array:
if let array = UserDefaults.standard.array(forKey: "profileArray") as? [String] {
profileArray = array
}
Im Swift use always String rather than NSString unless you have no choice.
I have finally figured this out. The userDefaults weren't "cleared". but the userDefaults are specific to a device. so with the migration to xcode8 the iOS simulators were also upgraded....and these are technically new devices where userDefaults had never been captured.
I proved this theory by adding a simulator (you can go back and re-install iOS 9.x simulators) and this worked.
I also tested on a real device using iOS 9.x & the new swift 3 code and the defaults persisted on that device.
So problem solved! :)
I've migrated my iOS parse SDK from the old Parse SDK to the version released to support a Parse stack hosted on my own infrastructure.
I have my project set up with SocketIO and decided it would be more efficient to append new Parse Objects sent from the server to my iOS apps model instead of making a new network request whenever the model changed, therefore I needed to instanciate a Parse object with an existing object ID.
To do that I used the following code snippet:
let appendError = PFObject(withoutDataWithClassName: "MachineError", objectId: id)
appendError.setValue(errorCode, forKey: "errorCode")
appendError.setValue(errorMessage, forKey: "errorMessage")
appendError.setValue(newDate, forKey: "createDate")
appendError.setValue(serial, forKey: "serialNumber")
appendError.setValue(status, forKey: "status")
appendError.setValue(false, forKey: "completed")
This code used to work fine when I was running xcode v7.1 but since this-morning when I upgraded to xcode 7.3, I was presented with an error that withoutDataWithClassName was not a valid parameter, it offered me outDataWithClassName as an alternative but the naming of that parameter did not sound as declarative as the previous. I did some reading through the PFObject documentation for iOS, but I could not find any details depicting what outDataWithClassName actually does.
I can only assume that it may be a typo on behalf of the Parse team, but I may be wrong. Could anyone here confirm whether withoutDataWithClassName is equivalent to outDataWithClassName?
Looks like it was a mistake related to automatic Objective-C to Swift conversion. It was reported as in issue in the repo, and a fix was committed 3 days ago.
In short, outDataWithClassName will do the same thing as withoutDataWithClassName for now, but since the current method name is rather uninformative, I would recommend updating Parse soon to get the fix.