Swift 3 UserDefaults set NSMutableArray - swift

Saving NSMutableArray with NSUserDefaults in Swift Returns Nil
setObject method removed my codes like that and not work. i try all set types still not work. Any idead ?
var banksAccount : NSMutableArray = []
for bankJson in (self.users?[0].Banks)! {
self.banksAccount.add(bankJson)
}
UserDefaults.standard.set(self.banksAccount, forKey: "myBanksAccounts")
UserDefaults.standard.synchronize()

For saving
let cacheArrayData = NSKeyedArchiver.archivedData(withRootObject: banksAccount)
UserDefaults.standard.set(cacheArrayData, forKey: "EventItems")
For retrieving
let retriveArrayData = UserDefaults.standard.object(forKey: "EventItems") as? NSData
let retriveArray = NSKeyedUnarchiver.unarchiveObject(with: retriveArrayData! as Data) as? NSArray
self.eventsArray = NSMutableArray(array:retriveArray!)

Related

NSNumber swift Dictionary to userdefaults swift3

I am trying to save swift dictionary [NSNumber : NSNumber] to UserDefaults. I have already tried to cast it as NSDictinonary, but still, the application crashes when I use set() function.
Key is a beacon minor key (NSNumber)
Value is an NSTimeinterval cast as NSNumber
the crash:
libc++abi.dylib: terminating with uncaught exception of type
NSException
var recentBeacons: [NSNumber : NSNumber] = [:]
func saveRecentBeaconDict()
{
let recentBeaconKeys = recentBeacons.keys
print("keys type is \(String(describing: recentBeaconKeys.self))")
let recentBeaconsNSDict = recentBeacons as NSDictionary
UserDefaults.standard.set(recentBeaconsNSDict, forKey:"recentBeacons")
}
prints out: keys type is LazyMapCollection< Dictionary < NSNumber, NSNumber >, NSNumber >(_base: [46171: 1501585588.173543], _transform: (Function))
Try with below answer.
var recentBeacons: [NSNumber : NSNumber] = [:]
func saveRecentBeaconDict()
{
let archivedObject = NSKeyedArchiver.archivedData(withRootObject: recentBeacons as NSDictionary)
UserDefaults.standard.set(archivedObject, forKey: "recentBeacons")
let data = UserDefaults.standard.object(forKey: "recentBeacons") as? Data
if let _data = data {
let allData = NSKeyedUnarchiver.unarchiveObject(with: _data) as! NSDictionary
print(allData)
}
}
You can't save Dictionary of type [NSNumber : NSNumber], allowed only [String, AnyObject] or [NSObject : AnyObject].
As approach you can convert your NSNumber's to String's

Switch from NSDictionary to Dictionary

I have some code to get EXIF data from file, but it uses NS-Types. I like to get Swift 3 conform and use standard swift types like Dictionary or String. When deleting "NS", I get the error that ".value()" does not exist. And no hint by the compiler what is the new function call:
let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil)
let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource!, 0, nil)! as NSDictionary
let exifDict = imageProperties.value(forKey: "{Exif}") as! NSDictionary
let dateTimeOriginal = exifDict.value(forKey: "DateTimeOriginal") as! NSString
print ("DateTimeOriginal: \(dateTimeOriginal)")
let PixelXDimension = exifDict.value(forKey: "PixelXDimension") as! Double
print ("PixelXDimension: \(PixelXDimension)")
let exifDictTIFF = imageProperties.value(forKey: "{TIFF}") as! NSDictionary
// optional
if let Software = exifDictTIFF.value(forKey: "Software") as? NSString {
print ("Software: \(Software)")
}
Any hint how to change it?
Additionally:
Using this
let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource!, 0, nil)! as Dictionary
let exifDict = imageProperties["{Exif}"] as! Dictionary
will deliver an error "Ambiguous reference to member 'subScript'" for the second row!
All of the NSDictionary needs to be something like [String:Any]. And all of the value calls should use normal key access.
let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil)
let imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource!, 0, nil) as! [String:Any]
let exifDict = imageProperties["{Exif}"] as! [String:Any]
let dateTimeOriginal = exifDict["DateTimeOriginal"] as! String
print ("DateTimeOriginal: \(dateTimeOriginal)")
let PixelXDimension = exifDict["PixelXDimension"] as! Double
print ("PixelXDimension: \(PixelXDimension)")
let exifDictTIFF = imageProperties["{TIFF}"] as! [String:Any]
// optional
if let Software = exifDictTIFF["Software"] as? String {
print ("Software: \(Software)")
}
This code is terrible. All of those uses of ! are a bad idea. Proper, safe unwrapping and casting should be used throughout this code.

Cannot get the dictionary from NSUserDefaults as saved format

I want to get a swift dictionary from NSUserDefaults as the format that I've saved before. I've saved the dictionary as [String:String] format, but while I'm getting the dictionary with dictionaryForKey(key) method I got [String:AnyObject]?. How can I convert [String:AnyObject]? to [String:String] or how can I get the dictionary in right format?
Saving to NSUserDefaults
var tasks: Dictionary<String,String> = [:]
let defaults = NSUserDefaults.standardUserDefaults()
let key = "key"
defaults.setObject(tasks, forKey: key)
defaults.synchronize()
Getting from NSUserDefaults
let defaults = NSUserDefaults.standardUserDefaults()
let key = "ananZaa"
let incomingArray = defaults.dictionaryForKey(key)
If you've registered it with a default value so it never can be nil, just downcast it to the proper type
let defaults = NSUserDefaults.standardUserDefaults()
let key = "ananZaa"
let incomingDictionary = defaults.objectForKey(key) as! Dictionary<String,String>

Swift class cast fails while casting AnyObject to NSMutableDictionary

var fetchEachStory = Firebase(url: "\(self.individualStoryUrl)\(eachStory)")
// Read data and react to changes
fetchEachStory.observeEventType(.Value) {
snapshot in
let storyDetails = snapshot.value as NSMutableDictionary?
let score = storyDetails!["score"] as Int?
var thisStory = eachStory
if score? > self.minSetScore {
self.showStories[thisStory] = storyDetails
}
}
While Assigning Snapshot.value to story details, it fails some times saying:
error: Execution was interrupted, reason: EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0).
The process has been returned to the state before expression evaluation.
How can I handle this ?
This line of code:
let storyDetails = snapshot.value as NSMutableDictionary?
fails if snapshot.value is not an NSMutableDictionary. It is better to use a conditional cast as? along with optional binding if let to make sure you only proceed if snapshot.value is the type you expect. The same is true for score being an Int.
According to the Firebase Documentation:
value
Returns the contents of this data snapshot as native types.
#property (strong, readonly, nonatomic) id value Return Value The data
as a native object.
Discussion Returns the contents of this data snapshot as native types.
Data types returned: * NSDictionary * NSArray * NSNumber (also
includes booleans) * NSString
Declared In FDataSnapshot.h
So you should be checking for NSDictionary instead of NSMutableDictionary.
I recommend:
// Read data and react to changes
fetchEachStory.observeEventType(.Value) {
snapshot in
if let storyDetails = snapshot.value as? NSDictionary {
// We know snapshot.value was non-nil and it is an NSDictionary.
if let score = storyDetails["score"] as? Int {
// We know "score" is a valid key in the dictionary and that its
// type is Int.
var thisStory = eachStory
if score > self.minSetScore {
self.showStories[thisStory] = storyDetails
self.tableView.reloadData()
}
}
}
}
I found the bug , It's more to do with FireBase FDataSnapshot , Should check if snapshot is nil , with snapshot.exists()
var fetchEachStory = Firebase(url:"\(self.individualStoryUrl)\(eachStory)")
// Read data and react to changes
fetchEachStory.observeEventType(.Value, withBlock: {
snapshot in
if snapshot.exists(){
let storyDetails = snapshot.value as NSDictionary?
let score = storyDetails!["score"] as Int?
var thisStory = eachStory
if score? > self.minSetScore{
self.showStories[thisStory] = storyDetails
self.tableView.reloadData()
}
}
})

UIColor in NSUserDefaults Swift / iOS 8

I'm writing a Swift app for iOS. I need to set and later retrieve a UIColor object to NSUserDefaults.
I set it like this:
var userSelectedColor : NSData? = (NSUserDefaults.standardUserDefaults().objectForKey("UserSelectedColor") as? NSData)
if (userSelectedColor == nil) {
var colorToSetAsDefault : UIColor = UIColor.redColor()
var data : NSData = NSKeyedArchiver.archivedDataWithRootObject(colorToSetAsDefault)
NSUserDefaults.standardUserDefaults().setObject(data, forKey: "UserSelectedColor")
NSUserDefaults.standardUserDefaults().synchronize()
println("SET DEFAULT USER COLOR TO RED")
}
But I can't seem to get it back because the unarchive method on NSKeyedArchiver seems to be missing in Swift.
var userSelectedColorData: NSData? = (NSUserDefaults.standardUserDefaults().objectForKey("UserSelectedColor") as NSData)
var userSelectedColor : UIColor? = NSKeyedArchiver.unarchiveObjectWithData(userSelectedColorData)
What is the proper way to do this in Swift / iOS 8?
Unarchiving is done with NSKeyedUnarchiver, not with NSKeyedArchiver. You also should
use conditional casts (as?) to ensure that the application does not crash if the
saved user default is not of the expected type:
if let userSelectedColorData = NSUserDefaults.standardUserDefaults().objectForKey("UserSelectedColor") as? NSData {
if let userSelectedColor = NSKeyedUnarchiver.unarchiveObjectWithData(userSelectedColorData) as? UIColor {
println(userSelectedColor)
}
}