Im trying to retrieve a Int value from a userdefault and show it in a input field, but I keep getting the fatal error: unexpectedly found nil while unwrapping an Optional value, it must be a wrong placed ! or ? somewhere in this code. I have used hours now :-(
func LoadFromDefaultDistances(){
if let v = defaults.objectForKey("DriverMin") as? NSInteger {
inputDriverMin.text = String(defaults.objectForKey("DriverMin") as! NSInteger)
}
}
Use this code to save the value.
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("Your in value", forKey: "myIntValue")
defaults.synchronize()
And use this code to get it back.
let defaults = NSUserDefaults.standardUserDefaults()
if let theInt = defaults.stringForKey("myIntValue")
{
inputDriverMin.text = theInt
}
Related
I stored an Int in UserDefaults. The Int will serve as the index of audioOptionsList, an array of objects, each having a SystemSoundID property.
This crashes with error: Could not cast value of type 'NSTaggedPointerString' (0x7fff87b33c28) to 'NSNumber' (0x7fff87bf4e00).
var soundToPlay = SystemSoundID(1322)
override func viewDidLoad() {
super.viewDidLoad()
if UserDefaults.standard.value(forKey: "timerSoundSelection") != nil {
let storedIndex = UserDefaults.standard.value(forKey: "timerSoundSelection")!
print("stored index is: \(storedIndex)") //prints a non-optional int as expected.
soundToPlay = audioOptionsList[storedIndex as! Int].sound //crashes with error
} else {
soundToPlay = SystemSoundID(1322)
}
Your key is stored as a String not an Int , use string(forKey: then cast it
if let stored = UserDefaults.standard.string(forKey: "timerSoundSelection")
, let value = Int(stored) { }
I am new to swift and trying to store NSMutableArray in Userdefaults. Here is what I am doinig :
//to save aaray in user defaults
var set:NSMutableArray = NSMutableArray(objects: self.listId)
self.saveListIdArray(set)
func saveListIdArray(_ params: NSMutableArray = []) {
let defaults = UserDefaults.standard
defaults.set(params, forKey: "ArrayKey")
defaults.synchronize()
}
//to get array from user default
func getUserDefaultKeyForAllObject(key userDefaultsKey: String) -> NSMutableArray {
let array = UserDefaults.standard.object(forKey: NSUserDefaultsKey.LIST_ID_ARRAY) as! NSMutableArray
print(array)
return array
}
App crashes with "fatal error: unexpectedly found nil while unwrapping an Optional value" exception.
Ignore the way I ask the question, help me out here.
Thank you.
Try converting to NSData then storing to nsuserdefaults like below
func saveListIdArray(_ params: NSMutableArray = []) {
let data = NSKeyedArchiver.archivedData(withRootObject: params)
UserDefaults.standard.set(data, forKey: "test")
UserDefaults.standard.synchronize()
}
For retrieving the data use
if let data = UserDefaults.standard.object(forKey: "test") as? Data {
if let storedData = NSKeyedUnarchiver.unarchiveObject(with: data) as? NSMutableArray
{
// In here you can access your array
}
}
You are force unwrapping the NSMutableArray for a key. Don't force unwrap when you try to get the value from a dictionary or UserDefault for a key because there may be a chance that the value does not exist for that key and force unwrapping will crash your app.
Do this as:
//to get array from user default
if let array = UserDefaults.standard.object(forKey:"ArrayKey") as? NSMutableArray
print(array)
}
I have 2 possible reasons for this:
You need to be 100% sure that you are retrieving array with the same key as you save it with. In your code you are saving the array with "ArrayKey" but retrieving it with NSUserDefaultsKey.LIST_ID_ARRAY, are you sure this is the same string?
What datatype is self.listId? If it's a custom class then you need to make that class conform to the nscoding protocol, then encode it to Data and save that to the userDefaults (Save custom objects into NSUserDefaults)
A 3rd reason is that you are trying to get an object from the defaults without ever writing anything to it. Try changing
let array = UserDefaults.standard.object(forKey: NSUserDefaultsKey.LIST_ID_ARRAY) as! NSMutableArray
print(array)
return array
to
if let array = UserDefaults.standard.object(forKey: "ArrayKey") as? NSMutableArray {
print(array)
return array
}
else {
return NSMutableArray()
}
What I'm trying to do is store my initial user defaults in a plist and then read them into NSUserDefaults when the application loads for the first time.
I've found a couple of posts which have helped me thus far however I can't seem to find an answer as to why I'm finding nil while unwrapping. Obviously I'm missing something, so my question is:
How do I properly register a plist to NSUserDefaults?
I've created a plist with my default settings. I'd like to read from the plist and register them into NSUserDefaults.
settings.plist
ViewController.swift
class ViewController: UIViewController {
let userDefaults = NSUserDefaults.standardUserDefaults()
override func viewDidLoad() {
super.viewDidLoad()
let prefs = NSBundle.mainBundle().pathForResource("Settings", ofType: "plist")
let dict = NSDictionary(contentsOfFile: prefs!)
if let dictionary = dict {
println("Contents of file unwrapped: \(dictionary)") // <---------
let defaults : NSDictionary! = dictionary.valueForKey("Root") as? NSDictionary
println("defaults: \(defaults)") // <---------
userDefaults.registerDefaults(defaults as! [NSObject : AnyObject])
userDefaults.synchronize()
}
if let unwrapDict = dict {
var myValue = unwrapDict.objectForKey("Boolean Switch 1") as! Bool
println("pulled from pList \(myValue)")
}
}
}
I'm sure you've noticed that I am looking for the key 'Root' from my plist...
let defaults : NSDictionary! = dictionary.valueForKey("Root") as? NSDictionary
I have also tried passing it other values like "Boolean Switch 1" and casting to different types. But nothing I try changes the outcome.
Here's my console output from the two println() logs.
After a day of messing with this code I was able to finally get my plist entered into NSUserDefaults. I wasn't satisfied with the final outcome because I noticed that the registerDefaults wasn't actually doing anything.
So I decided to post my working code on Code Review to see if there were any parts of my code that weren't necessary. It turns out that registerDefualts indeed was not necessary, here's an excerpt from the Alex's answer to my question.
This line:
userDefaults.registerDefaults(dict as! [NSObject : AnyObject]) does
not actually set the information on the NSUserDefaults storage file on
disk. All it does is tell NSUserDefaults the default values to be used
when a key doesn't yet exist on disk.
So having said all of that, I'll post the working code. I should note, as it was pointed out to me by nhgrif, that the ViewController is really not the place to put this code and a better place is in the appDelegate in application(_:didFinishLaunchingWithOptions:).
ViewController:
class ViewController: UIViewController {
let userDefaults = NSUserDefaults.standardUserDefaults()
override func viewDidLoad() {
super.viewDidLoad()
let prefs = NSBundle.mainBundle().pathForResource("Settings", ofType: "plist")
let dict = NSDictionary(contentsOfFile: prefs!)
userDefaults.setObject(dict, forKey: "defaults")
userDefaults.synchronize()
// this just toggles the aBool value
if let defaults = userDefaults.valueForKey("aBool") as? NSNumber {
if defaults as NSObject == 1 {
println("inside the conditional: \(defaults)")
userDefaults.setValue(0, forKey: "aBool")
userDefaults.synchronize()
println("Setting aBool to true")
} else {
userDefaults.setValue(1, forKey: "aBool")
userDefaults.synchronize()
println("setting aBool to false")
}
}
}
}
According to Apple document, If you don't change any value on settings, Values reading from NSUserDefaults are nil or 0. In your code, When you read a value from NSUserDefaults, you should set it a default value.
I have a textField for the user to input their name.
#IBAction func nameTextField(sender: AnyObject) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject("\(nameTextField)", forKey: "userNameKey")
}
Then I recall the inputted name in ViewDidLoad with:
NSUserDefaults.standardUserDefaults().stringForKey("userNameKey")
nameLabel.text = "userNameKey"
What am I doing wrong? Result is simply "userNameKey" every time. I'm new to this, thanks!
You just have to assign the result returned by nsuserdefaults method to your nameLabel.text. Besides that stringForKey returns an optional so I recommend using the nil coalescing operator to return an empty string instead of nil to prevent a crash if you try to load it before assigning any value to the key.
func string(forKey defaultName: String) -> String?
Return Value For string values, the string associated with the
specified key. For number values, the string value of the number.
Returns nil if the default does not exist or is not a string or number
value.
Special Considerations
The returned string is immutable, even if the value you originally set was a mutable string.
You have to as follow:
UserDefaults.standard.set("textToSave", forKey: "userNameKey")
nameLabel.text = UserDefaults.standard.string(forKey: "userNameKey") ?? ""
What you need to do is:
#IBAction func nameTextField(sender: AnyObject) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.set(yourTextField.text, forKey: "userNameKey")
}
And later in the viewDidLoad:
let defaults = NSUserDefaults.standardUserDefaults()
let yourValue = defaults.string(forKey: "userNameKey")
nameLabel.text = yourValue
I am having a problem saving and loading up my difficulty integer. I have a button pushed to decide it on one view:
(This is one difficulty)
Difficulty + 1
let SecondDefaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
SecondDefaults.setObject(Difficulty, forKey: "Difficulty")
SecondDefaults.synchronize()
On another view under viewDidLoad for the loading:
let SecondDefaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
var difficulty = SecondDefaults.valueForKey("Difficulty")?.integerValue
SecondDefaults.synchronize()
Difficulty = difficulty!.stringByTrimmingCharactersInSet(NSCharacterSet.decimalDigitCharacterSet().invertedSet).toInt()!
You need to change:
var difficulty = SecondDefaults.valueForKey("Difficulty") as? String
to
var difficulty = SecondDefaults.valueForKey("Difficulty")?.stringValue
I don't know why you need to convert the integer to string. You only need the following code for getting an integer from NSUserDefaults no need to convert it to string.
let SecondDefaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
var difficulty = SecondDefaults.valueForKey("Difficulty")?.integerValue
Your issue lies on this line:
var difficulty = SecondDefaults.valueForKey("Difficulty") as? String
The problem is that the value may be a String or it may nil. Who knows? The as? keyword indicates that the cast may fail, so difficulty is a String optional, which you implicitly unwrap. Anything you unwrap as nil will give you a runtime error.
Assuming that Difficulty from your second code snippet is of type Int, this should work:
let defaults: NSUserDefaults = NSUserDefaults.standardUserDefaults()
let maybeDifficulty = defaults.valueForKey("Difficulty") as? Int
if let difficulty = maybeDifficulty {
Difficulty = difficulty
} else {
println("Difficulty is not an Int or may be nil")
}