I have defined an array like this in my iOS app
var array=[Bool]()
and assigning some bool values to this.After that I am storing this array in my user defaults in this way.
userDefaults.setObject(dm.array, forKey: "array")
Now I want to retrievw this array. So I did like this
dm.array=userDefaults.arrayForKey("array") as! Array
But here im getting an error
Down cast from '[AnyObject]?' to 'Array' only unwraps optional; did you mean to use '!'?
array = userDefaults.objectForKey("array") as? [Bool] ?? [Bool]()
Related
I tried to update Swift 3 and I got the following error :
Ambiguous use of 'mutableCopy()'
Before update to swift 3. It runs well.
Swift 2.3
NSUserDefaults.standardUserDefaults().objectForKey("listsavednews")?.mutableCopy() as! NSMutableArray
Swift 3.0
(UserDefaults.standard.object(forKey: "listsavednews")? as AnyObject).mutableCopy() as! NSMutableArray
I found that mutableCopy in Swift3 return Any that doesnt have method mutableCopy() so that it needs to cast to AnyObject.
Any helps thanks.
I dont know why I can't comment.
Thanks all, I'll be using :
UserDefaults.standard.mutableArrayValue(forKey: "listsavednews")
mutableCopy is an Objective-C method from NSObject. There's little reason to use it in Swift 3.
Since you are dealing with UserDefaults and mutableCopy, you must be dealing with either an array or dictionary. Or it could be a string.
The proper way to do this in Swift 3 is to use the proper UserDefaults method to get an array or dictionary. And assign the result to a var. That combination will give you a mutable array or mutable dictionary.
var someArray = UserDefaults.standard.array(forKey: "somekey")
or:
var someDictionary = UserDefaults.standard.dictionary(forKey: "somekey")
In the two above cases, you end up with an optional since there might not be any data for the given key. And you also get a non-specific array or dictionary which isn't ideal. It would be better to cast the result to the appropriate type.
Let's say you have an array of strings and you want an empty array if there is nothing currently in user defaults. You can then do:
var someArray = UserDefaults.standard.array(forKey: "somekey" as? [String]) ?? []
Adjust as necessary if the array contains something other than String.
If you actually have a dictionary, the code would be similar.
var someDictionary = UserDefaults.standard.dictionary(forKey: "somekey") as? [String:String] ?? [:]
If your original object is just a string, then you could do:
var someString = UserDefaults.standard.string(forKey: "somekey") ?? ""
I am using the NSUserDefaults to store an array (of strings), and when loading it, it appears to be interpreted as an AnyObject instead of an Array. I don't understand how this is possible because I am using the arrayForKey method for my default, which I thought was supposed to return an array?
The exact error I am getting is:
Value of type '[AnyObject]?' has no member 'removeAtIndex'
which is occurring at shoppingListDefaults.arrayForKey("ShoppingList").removeAtIndex(indexPath.row)
let shoppingListDefaults = NSUserDefaults.standardUserDefaults()
let deleteAction = UITableViewRowAction(style: .Normal, title: "Delete") { (rowAction:UITableViewRowAction, indexPath:NSIndexPath) -> Void in
shoppingListDefaults.arrayForKey("ShoppingList").removeAtIndex(indexPath.row)
self.slItems.reloadData() // `slItems` is the IBOutlet for a UITableView
}
deleteAction.backgroundColor = UIColor.redColor()
return [deleteAction]
arrayForKey returns an optional, so you have to unwrap it before you can call anything else on it. You also can't directly edit the array you get from defaults since it is immutable. You have to edit the array and then update defaults with the update array.
Try:
if var list = shoppingListDefaults.arrayForKey("ShoppingList") {
list.removeAtIndex(indexPath.row)
shoppingListDefaults.setArray(list, forKey: "ShoppingList")
}
This array is immutable. You need to retrieve it from defaults, remove object, and set back modified array to defaults.
When I am trying to take the value from a plist and append it to an array
nameArray.append(namesArray!.objectForKey("Item1")! as! String)
The target item is a string but it appears to be inside the plist array, can anyone explain how to get it out please?
The print of namesArray!.objectForKey("Item1")! followed by the error are shown below:
Cast the value of the "Item1" key as an array of Strings, then fetch the first object from the array (since it appears there's only one). And if you like the idea that your app should not crash everytime a value is nil, better use if let than force-unwrapping everything with !.
Example:
if let names = namesArray,
let items = names.objectForKey("Item1") as? [String],
let result = items.first {
nameArray.append(result)
}
Just take the first element of your array:
nameArray.append((namesArray!.objectForKey("Item1")! as! [String])[0])
I am trying to unwrap a NSMutableArray from user defaults, but keep getting the error unexpectedly found nil while unwrapping an Optional value. I tried to check for nil after getting the array, but it is happening on the line that is getting the array from the UserDefaults, so I don't know how to fix this error. Can anyone help?
var classURLs: NSMutableArray = NSMutableArray();
let defaults: NSUserDefaults = NSUserDefaults(suiteName: "group.myCompany.Array")!;
classURLs = NSMutableArray(object: defaults.objectForKey("Class URLs")!);
NSUserDefaults.objectForKey returns an optional for a reason – if the key isn’t present, you get nil back. You shouldn’t just force-unwrap it with !
The most common case is this is the first time you’ve tried reading it without having ever written it.
In which case you probably want a default value, perhaps an empty array:
let classURLs = defaults.stringArrayForKey("Class URLs") as? [String] ?? []
(?? substitutes the value on the right if the value on the left is nil)
Note, it’s probably better if you’re writing Swift to go with a Swift array (e.g. [String]) rather than NSMutableArray, unless all you are going to do is pass it straight into a call to Objective-C.
You can also avoid the ! you’re using with the NSUserDefaults init by using optional chaining:
let defaults = NSUserDefaults(suiteName: "group.myCompany.Array")
var classURLs = defaults?.stringArrayForKey("Class URLs") as? [String] ?? []
If the key does not exist, the forced unwrap (!) of the nil object will result in a crash. You need to account for this case.
var classURLs = NSMutableArray(object:
NSUserDefaults.standardUserDefaults().objectForKey("foo") ?? [])
NB: transitioning from Objective-C? You don't need the semicolons! ;-)
I have an array of Printable objects, but I need them Equatable and AnyObject compliant.
private(set) var items: [Printable] = []
class func withItems<T: AnyObject where T: Equatable, T: Printable>(items: [T], selectedItem: T? = nil) {
... instance init ...
instance.items = items
}
And it result on EXC_BAD_INSTRUCTION:
fatal error: array cannot be bridged from Objective-C
This is one try to this problems:
Generic function and attribute with Equatable and Printable as parameters in Swift
why?
A Swift Array must contain all one kind of object (e.g. all String or all Int). An Objective-C NSArray can contain many different kinds of objects (e.g. some NSStrings and some NSNumbers). Hence if you get that kind of array from Objective-C you can't magically assign it into a Swift array reference.
What I do in that situation is munge the array to make it acceptable to Swift. I don't know what the details are of what you're getting back from Objective-C; your actual strategy will depend on those details and what you want to do with the array. One approach is to assign / cast into a Swift array of AnyObject. Or you might decide to leave it as an NSArray and work with it entirely through NSArray methods.
Here's an example from my own code. arr is an NSArray that's a mixed bag of NSString and NSNull objects. I know none of the NSString objects are the empty string, so I substitute the empty string for all the NSNull objects, thus giving me an array of just strings, which Swift can deal with:
let arr2 = (arr as Array).map { $0 as? String ?? "" }
Now arr2 is a pure Swift [String] array.