First I import the existing array saved in user defaults in key - array1
var savedArray = UserDefaults.standard.array(forKey: "array1") as! [String]
var ns = UserDefaults.standard
Then
let savedValue = name
Then
savedArray.append(savedValue!)
Then I save it in key - array1
UserDefaults.standard.set(savedArray, forKey: "array1")
And sync
ns.synchronize()
However, if I go into another viewcontroller and do this
let alreadyShownarray = UserDefaults.standard.object(forKey: "array1") as! [String]
print (alreadyShownarray)
Then I get the same array without the appended savedValue!
Try removing the object and adding the new one.
UserDefaults.standard.removeObject(forKey: "array1")
UserDefaults.standard.set(savedArray, forKey: "array1")
You can fetch the array, assign it to a variable, append your element, then set the object for the same key that you used to fetch.
func enqueue(localNotificationModel: LocalNotificationModel) {
guard let localNotificationJSON = UserDefaults.standard.value(forKey: localNotificationKey) as? [[String: Any]] else { return }
var localNotifiactions = localNotificationJSON.compactMap { LocalNotificationModel(json: $0)}
localNotifiactions.append(localNotificationModel)
UserDefaults.standard.set(localNotifiactions, forKey: localNotificationKey)
}
You cannot update the Array directly from NSUserDefault. you have to create a new arrray and assign the existing array from NSUserDefault then you can set that new array to the NSUserDefault one
var newArray = [String]() //2.create a new array and assign the UserDefault array1 here
var ns = UserDefaults.standard
let savedArray = ns.array(forKey: "array1") as! [String] //1.this is protected cannot update directly
let savedValue: String = "name" //3. the value you wanted to append
newArray = savedArray //4. just copying the value here
newArray.append(savedValue) //5. appending the new value
ns.set(newArray, forKey: "array1") //6. now the value "name" is saved.
// array1[0] = "your initial value"
// array1[1] = "name"
Related
I have an array of [(userID: String, friendBool: Bool)] that I want to filter AND convert to an array of userID's only [String] (removing the friendBool and therefore changing the element). Is there a function in Swift for doing this?
Currently, I am filtering on the array and then using a for loop on the filtered array [(userID: String, friendBool: Bool)] to convert it to an array of [String]. Is there a better way to do this?
Current Code:
let friendArray = [(userID: String, friendBool: Bool)]()
let excludeUsers = [String]()
//Updates with user actions
var userArrayForTableView = [String]()
//Filter friendArray
let newArray = friendArray.filter { (existingFriend) -> Bool in
return !excludeUsers.contains(existingFriend.userID)
}
//Convert array fro [(userID: String, friendBool: Bool)] to [String]
for existingFriend in newArray {
userArrayForTableView.append(existingFriend.userID)
}
What I'm trying to do:
//Loaded on ViewDidLoad
let friendArray = [(userID: String, friendBool: Bool)]()
let excludeUsers = [String]()
//Updates with user actions
var userArrayForTableView = [String]()
//Filter friendArray
/*
Below fitler returns an array of [(userID: String, friendBool: Bool)]...
but I want a filter to return an array of [String] for just userIDs
*/
let newArray = friendArray.filter { (existingFriend) -> Bool in
return !excludeUsers.contains(existingFriend.userID)
}
//ERROR HERE because 'newArray' is not [String]
userArrayForTableView.append(contentsOf: newArray)
What about using compactMap()?
In a certain way, it can be understood as a filter() (that you are already using) + map() (which is the loop for existingFriend in newArray in the first solution)
let userArrayForTableView = friendArray.compactMap({ (existingFriend) in
if excludeUsers.contains($0.userID) {
return nil
} else {
return existingFriend.id
}
})
In a shorter way:
let userArrayForTableView = friendArray.compactMap({ excludeUsers.contains($0.userID) ? nil : $0.userID })
I'm having an issue saving and retrieving an array in UserDefaults from UIImagePickerControllerImageURL. I can get the array after synchronizing, but I am unable to retrieve it. myArray is empty.
The testImage.image does get the image, no problems there.
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
let imageURL: URL = info[UIImagePickerControllerImageURL] as! URL
//test that imagepicker is actually getting the image
let imageData: NSData = try! NSData(contentsOf: imageURL)
let cvImage = UIImage(data:imageData as Data)
testImage.image = cvImage
//Save array to UserDefaults and add picked image url to the array
let usD = UserDefaults.standard
var array: NSMutableArray = []
usD.set(array, forKey: "WeatherArray")
array.add(imageURL)
usD.synchronize()
print ("array is \(array)")
let myArray = usD.stringArray(forKey:"WeatherArray") ?? [String]()
print ("myArray is \(myArray)")
picker.dismiss(animated: true, completion: nil)
}
There are many issue here.
Do not use NSData, use Data.
Do not use NSMutableArray, use a Swift array.
You can get the UIImage directly from the info dictionary`.
You can't store URLs in UserDefaults.
You save array to UserDefaults before you update the array with the new URL.
You create a new array instead of getting the current array from UserDefaults.
You needlessly call synchronize.
You needlessly specify the type for most of your variables.
Here is your code updated to fix all of these issues:
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {
testImage.image = image
}
if let imageURL = info[UIImagePickerControllerImageURL] as? URL {
//Save array to UserDefaults and add picked image url to the array
let usD = UserDefaults.standard
var urls = usD.stringArray(forKey: "WeatherArray") ?? []
urls.append(imageURL.absoluteString)
usD.set(urls, forKey: "WeatherArray")
}
picker.dismiss(animated: true, completion: nil)
}
Note that this saves an array of strings representing each URL. Later on, when you access these strings, if you want a URL, you need to use URL(string: arrayElement).
so i want to assign a list of AnyObject to a key of a dictionary with the structure [String:AnyObject]
here is my code:
let list = try JSONSerialization.jsonObject(with: newData, options: .allowFragments) as! [AnyObject]
let parsedResult = [String:AnyObject]()
parsedResult["dataList"] = list
callback(false, parsedResult)
im parsing data from an http request. i get this error:
Cannot assign value of type [AnyObject] to type AnyObject?
isn't a list of AnyObject, still an object?
Change:
let parsedResult = [String:AnyObject]()
To:
var parsedResult: [String: Any] = [ : ]
And by the way declare parsedResult as var to be able to do parsedResult["dataList"] = list.
For your other issue that you placed a comment on, do this instead:
if let account = data?["account"] as? [String: Any], let accountKey = account["key"] as? Int { ... }
I have a JSON response whose answer I have to parse. I write the single elements into an array called courseDataArray using a for loop. After that, I want to write this newly created array into another array called combinedCourseArray with the aim to pass that on to a UITableView. Creating the first array seems to work fine.
But how can I create another array combinedCourseArray who contain all arrays of type courseDataArray?
for (index, element) in result.enumerate() {
// get one entry from the result array
if let courseEntry = result[index] as? [String:AnyObject]{
//work with the content of the array
let courseName = courseEntry["name"]
let courseType = courseEntry["course_type"]
let courseDate = courseEntry["cor_date"]
let courseId = courseEntry["cor_id"]
let duration = courseEntry["duration"]
let schoolId = courseEntry["sco_id"]
let status = courseEntry["status"]
let courseDataArray = ["courseName" : courseName, "courseType": courseType, "courseDate": courseDate, "courseId": courseId, "duration": duration, "schoolId":schoolId, "status":status]
print(courseDataArray)
var combinedCourseArray: [String: AnyObject] = [:]
combinedCourseArray[0] = courseDataArray //does not work -- error: cannot subscript a value of type...
// self.shareData.courseStore.append(scooter)
}
You should move the combinedCourseArray declaration outside of the array. It should be var combinedCourseArray: [[String: AnyObject]] = [[:]] since it's an array and not a dictionary.
And you should be doing
combinedCourseArray.append(courseDataArray)
instead of
combinedCourseArray[0] = courseDataArray
var FirstArray = [String]()
var SecondArray = [String:AnyObject]()
FirstArray.append(contentsOf: SecondArray.value(forKey: "key") as! [String])
First declare this combinedCourseArray array out side this loop
var combinedCourseArray: [[String: AnyObject]] = [[String: AnyObject]]()
for (index, element) in result.enumerate() {
// get one entry from the result array
if let courseEntry = result[index] as? [String:AnyObject]{
//work with the content of the array
let courseName = courseEntry["name"]
let courseType = courseEntry["course_type"]
let courseDate = courseEntry["cor_date"]
let courseId = courseEntry["cor_id"]
let duration = courseEntry["duration"]
let schoolId = courseEntry["sco_id"]
let status = courseEntry["status"]
let courseDataArray = ["courseName" : courseName, "courseType": courseType, "courseDate": courseDate, "courseId": courseId, "duration": duration, "schoolId":schoolId, "status":status]
print(courseDataArray)
combinedCourseArray.append(courseDataArray) //does not work -- error: cannot subscript a value of type...
// self.shareData.courseStore.append(scooter)
}
}
Just use flatMap on the outer array to translate one array into another array, possibly dropping some elements:
let courseDataArray : [[String:AnyObject?]] = result.flatMap {
guard let courseEntry = $0 as? [String:AnyObject] else {
return nil
}
return [
"courseName" : courseEntry["name"],
"courseType": courseEntry["course_type"],
"courseDate": courseEntry["cor_date"],
"courseId": courseEntry["cor_id"],
"duration": courseEntry["duration"],
"schoolId": courseEntry["sco_id"],
"status": courseEntry["status"]
]
}
Of course, the guard isn't really necessary since the input type is presumably already [[String:AnyObject]] and since you then can't have any internal failures, you can just use map instead of flatMap
I have a for loop that creates a dictionary and then I append the dictionary to an array. I append the dictionary to an array because I don't know how to add more than one value with the same key, when I do that in the for loop the key / value pair is just updated and the old key / value pair is deleted What is the best way to change the array back to a dictionary?
import UIKit
class ViewController: UIViewController {
var jobTitle = ""
var jobDescription = ""
var dict:[String: AnyObject] = ["jobTitle": "jobTitle", "jobDescription": "jobDescription"]
var tArray = [[String: AnyObject]]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
for var i = 0; i < 3; ++i {
jobTitle = "job1"
jobDescription = "Desc1"
dict["jobTitle"] = "job1"
dict["jobDescription"] = "Desc1"
tArray.append(dict)
}
println("\(tArray)")
}
}
Like such, where you have more than one value associated with each key:
let jobnames = ["j1", "j2", "j3"]
let jobdescs = ["d1", "d2", "d3"]
var dict : [String:[String]] = [:]
for index in 0..<3 {
if nil == dict["jobTitle"] { dict["jobTitle"] = [] }
if nil == dict["jobDesc" ] { dict["jobDesc" ] = [] }
dict["jobTitle"]!.append(jobnames[index])
dict["jobDesc" ]!.append(jobdescs[index])
}
Here is the output:
You call the same assignmenta such as
jobTitle = "job1"
at every iteration of the loop. Of course the variable will always contain the same value. The same is true for dict. It is an ivar, so you keep overwriting it.
What you want is to create a new collection of type [String: AnyObject] to add to your array.
let newDict:[String : AnyObject] = [titleKey : titleText,
descriptionKey : descriptionText]
tArray.append(newDict)