Unable to get NSMutableArray with multiple Object from UserDefaults in Swift - ios

I am having custom class which stores the login information of the user.
App can have multiple users logged in at a time.
This is how I am storing the logged in users data to UserDefaults.
let userDefaults = UserDefaults.standard
let decoded = userDefaults.data(forKey: "CPContactInfo")
if userDefaults.object(forKey: "CPContactInfo") != nil {
let decodedTeams = NSKeyedUnarchiver.unarchiveObject(with: decoded!) as! NSMutableArray
arrayOfArray.add(qidInfo)
}
} else {
print("userdefault not exist")
arrayOfArray.add(qidInfo)
}
addQID(qid_info: arrayOfArray)
Where qidInfo is custom object of class QBM_CPContactInfo which I store it in array,
at first I checked if UserDefault is present or not for given key at very first time, then added my qidInfo object into the array arrayOfArray and then that array is saved into UserDefault by calling function addQID(qid_info: arrayOfArray)
This is how my addQID function is,
func addQID(qid_info: NSMutableArray) {
let userDefaults = UserDefaults()
let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: qid_info)
userDefaults.set(encodedData, forKey: "CPContactInfo")
userDefaults.synchronize()
}
After this when I add second logged in details it executes the
if userDefaults.object(forKey: "CPContactInfo") != nil
perfectly.
When I try to retrieve data from UserDefaults as below,
let userDefaults = UserDefaults.standard
let decoded = userDefaults.data(forKey: "CPContactInfo")
if userDefaults.object(forKey: "CPContactInfo") != nil {
let decodedTeams = NSKeyedUnarchiver.unarchiveObject(with: decoded!) as! NSMutableArray
print(decodedTeams)
qid_info = decodedTeams.object(at: 0) as! QBM_CPContactInfo
print(qid_info?.qidEmail)
}
it gives me only one object in return for decodedTeams as NSMutableArray, but actually I have added two items in NSMutableArray.
Can any one tell me whats I am doing wrong.
further I need to compare the email of user selected which is in
let title = action.title along with qid_info?.qidEmail.
Any help will be appreciated.
Thanks in advance.

You can have the following approach.
let userDefaults = UserDefaults.standard
let decoded = userDefaults.data(forKey: "CPContactInfo")
if userDefaults.object(forKey: "CPContactInfo") != nil {
let decodedTeams = NSKeyedUnarchiver.unarchiveObject(with: decoded!) as! Array<QBM_CPContactInfo>
arrayOfArray = decodedTeams
arrayOfArray.append(qidInfo)
} else {
arrayOfArray.append(qidInfo)
}
addQID(qid_info: arrayOfArray)
Here, first, get the saved Array from defaults in a temporary array and copy that temporary array in your existing array.
Then append new elements into it and save the updated array for the same key.

Related

How to retrieve nested nodes from Firebase realtime database to iOS app

I'm building a simple app which stores and retrieve data from firebase realtime database. At present my database has these data of an user.
Database content
Here is the code which I used to insert data.
let ref = Database.database().reference()
let user = ref.child("bill")
user.setValue(["name":"Bill gates"])
user.child("Request/One").setValue(["Phno":" ","Message":" "])
As you can see I'm inserting a dictionary with empty values because I don't know how to create a child node without any data within them.
I'm trying to retrieve the Request part of the database completely whenever a new node is added as a child to request node.
Here I my code for retrieving
user.observe(.childAdded) { (DataSnapshot) in
for case let i as DataSnapshot in DataSnapshot.children
{
guard let dict = i.value as? [String:Any] else{print("Error"); return}
let a = dict["Message"] as? String
let b = dict["Phno"] as? String
print(a!)
print(b!)
}
}
But in above code it doesn't get called when I explicitly add a new node in database
Solved it by using below code
user.observe(.childAdded) { (DataSnapshot) in
if let dict = DataSnapshot.value as? NSDictionary
{
for i in dict.allKeys
{
if let data = dict[i] as? NSDictionary
{
let message = data["Message"] as! String
let phno = data["Phno"] as! String
if(message != "" && phno != "")
{
print(message)
print(phno)
}
}
}
}

How to Save Array of object in UserDefaults in iOS 12.0. using Any Array [[String: Any]]

I want to save an array of object in user default without using Codable.
I tried it to convert an array in data and save in User default:
let childsArray = result["childs"] as? [[String: Any]]
let childsData = NSKeyedArchiver.archivedData(withRootObject: childsArray!)
UserDefaults.standard.set(childsData, forKey: "childsArray")
UserDefaults.standard.synchronize()
It gives me this warning:
'archivedData(withRootObject:)' was deprecated in
iOS 12.0: Use +archivedDataWithRootObject:requiringSecureCoding:error: instead
How do I resolve this warning and achieve my desired goal of saving an array of objects in UserDefaults?
You can archived array using code below:
do {
let childsData = try NSKeyedArchiver.archivedData(withRootObject: childsArray!, requiringSecureCoding: true)
UserDefaults.standard.set(childsData, forKey: "childsArray")
UserDefaults.standard.synchronize()
} catch {
print(error)
}
And unarchive objects using code below:
do {
let childData = UserDefaults.standard.value(forKey: "childsArray")
if let childArray = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(childData as! Data) {
print(childArray)
}
} catch {
print(error)
}
let object1 = ["key1":"value1"]
let object2 = ["key2":"value2"]
let array = [object1, object2]
UserDefaults.standard.set(array, forKey: "childArray")
UserDefaults.standard.synchronize()
let storedArray = UserDefaults.standard.value(forKey: "childArray") as! [[String:String]]
print(storedArray)

I was unable to edit and save the data to the core data using swift 3.0?

here I had completed saving data and displaying it on table view also had done but the problem is I am unable to edit and update the data to the core data database can anyone help me ?
#IBAction func updateButtonClicked(_ sender: Any) {
var firstname = ""
var lastname = ""
var emailid = ""
var Password = ""
var mobileNumber = ""
firstname = firstnameTextfield.text!
lastname = lastanameTextField.text!
emailid = emailidTextField.text!
Password = passwordTextField.text!
mobileNumber = mobilenumberTextField.text!
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName:"Account")
do {
let list = try context.fetch(fetchRequest) as? [NSManagedObject]
if list?.count != 0
{
let newManagedObject = NSEntityDescription.insertNewObject(forEntityName: "Account", into: context)
newManagedObject.setValue(firstnameTextfield.text, forKey: "firstName")
newManagedObject.setValue(lastanameTextField.text, forKey: "lastname")
newManagedObject.setValue(emailidTextField.text, forKey: "emailID")
newManagedObject.setValue(passwordTextField.text, forKey: "password")
newManagedObject.setValue(mobilenumberTextField.text, forKey: "mobileNumber")
try managedContext.save()
}
}
catch let error as NSError {
print("Fetch failed: \(error.localizedDescription)")
}
In your code you have a mix of fetching data and inserting new data. Please check those answers:
https://stackoverflow.com/a/28258374/4689446
https://stackoverflow.com/a/38423458/4689446
General idea for how to update existing object in Core Data:
fetch data with predicate
you get back array of matching objects
set values for those objects and save them back

Saving array with UserDefaults

Is this the right way to save array of dictionaries in tableView using UserDefaults in Swift 3?
var arrNotes = [String:String]
func saveNotesArray () {
UserDefaults.standard.set(arrNotes, forKey: "notes")
UserDefaults.standard.synchronize()
}
Use this function to get your notes:
func saveNotesArray () {
var notes = UserDefaults.standard.object(forKey: "notes") as? [String:String]
}
Are you getting object in same way?
"[String: String]" Means a dictionary where the keys and the values are Strings.
"[[String: String]]" Means an array that contains dictionaries where the keys and values are strings.
create a dictionary of string and an array to hold them
let dictionary: [String: String] = ["keyOne" : "valueOne", "keyTwo": "valueTwo"]
let arrayWithDictionaryOfStrings: [[String: String]] = [dictionary]
add the array to userDefaults
let userDefaults = UserDefaults.standard
userDefaults.set(arrayWithDictionaryOfStrings, forKey: "arrayWithDictionaryOfStrings")
userDefaults.synchronize();
get the array of dictionaries from the userdefaults
if let fetchedArrayWithDictionaryOfStrings: [[String: String]] = (userDefaults.object(forKey: "arrayWithDictionaryOfStrings") as? [[String: String]]) {
// handle fetchedArrayWithDictionaryOfStrings
}
your should do it like This
For Saving
let placesData = NSKeyedArchiver.archivedData(withRootObject: placesArray)
UserDefaults.standard.set(arrNotes, forKey: "notes")
To Retrieved array from NSUserDefault.
let placesData = UserDefaults.standard.object(forKey: "notes") as? NSData
if let placesData = placesData {
let arrNotes = NSKeyedUnarchiver.unarchiveObject(with: placesData as Data) as? NSMutableArray
print(arrNotes)
}
In Swift-3, the following way to Saving array with UserDefaults :
let userDefaults = UserDefaults.standard
userDefaults.set(arrayOfname, forKey:"Keyname")
userDefaults.synchronize()

How do I check if core data class is nil. in SWIFT

I have created an Entity called Status with an attribute called statusUpdate. I want the user to be able to create a status for the first time which would then be saved in core data, then when the status is next updated to save over the old status in core data. Here is what i've done:
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
let newUser = NSEntityDescription.insertNewObjectForEntityForName("Status", inManagedObjectContext: context) as NSManagedObject
var request = NSFetchRequest(entityName: "Status")
request.returnsObjectsAsFaults = false
var results = context.executeFetchRequest(request, error: &self.error)
if results?.count > 0 {
for result: AnyObject in results! {
if var oldStatus = result.valueForKey("statusUpdate") as? String {
println("Current User fetched status from Core Data")
var newStatus = self.updateStatusText.text
result.setValue(newStatus, forKey: "statusUpdate")
} else if result.valueForKey("statusUpdate") == nil {
var newStatus = self.updateStatusText.text
newUser.setValue(newStatus, forKey: "statusUpdate")
println("Status uploaded for the first time")
}
}
}
context.save(&self.error)
The problem is the else if seems to always run. I want it to basically only run of the Status entity is nil (so it will only run for the first time somebody updates a status) and then when the status is updated after that it will run just the regular if statement.
I'm not sure what i'm doing wrong???
Thanks in advance.
Line 3 of your code inserts a new Status object, so each time this code is executed, you are adding an extra object. The newly inserted object will have a statusUpdate of nil (most likely).
When you execute the fetch, in line 6, this new Status object will be included in the results, together with any objects you have saved previously. So when you iterate through all the results, there will always be one for which statusUpdate is nil.
I would restructure your code to do the fetch first, establish whether there are any results. If so, update the statusUpdate; if not, create the new object and set the statusUpdate field. Something like this:
let appDel: AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context: NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "Status")
request.returnsObjectsAsFaults = false
var results = context.executeFetchRequest(request, error: &self.error)
if let resultsArray = results { // explicitly test for nil results
if resultsArray.count > 0 {
// count should be at most one, but just in case we will iterate through:
for result: AnyObject in resultsArray {
println("Current User fetched status from Core Data")
var newStatus = self.updateStatusText.text
result.setValue(newStatus, forKey: "statusUpdate")
}
else { // resultsArray is empty, so insert a new object
var newStatus = self.updateStatusText.text
let newUser = NSEntityDescription.insertNewObjectForEntityForName("Status", inManagedObjectContext: context) as NSManagedObject
newUser.setValue(newStatus, forKey: "statusUpdate")
println("Status uploaded for the first time")
}
} else { // fetch returned nil, so log an error:
println("Nil returned by fetch")
}
context.save(&self.error)
if (var oldStatus = result.valueForKey("statusUpdate") as? String) != nil{
println("Current User fetched status from Core Data")
var newStatus = self.updateStatusText.text
result.setValue(newStatus, forKey: "statusUpdate")
}else {
var newStatus = self.updateStatusText.text
newUser.setValue(newStatus, forKey: "statusUpdate")
println("Status uploaded for the first time")
}

Resources