Crash while getting value from the dictionary in Swift - ios

I have created a dictionary like
var tempArray1 = ["sdds","dsads"]
var tempArray2: AnyObject = ["sddsa",34,tempArray1]
var dictionary: [String:Array] = ["key1":["value1"],"key2":["value2",6,tempArray2]]
The application crashed when I tried to print all values from the dictionary like
let allValues = [Array](dictionary.values)
for value in allValues{
println(value)
}
I just started learning dictionary concept in swift language. I want to know my approach is right or wrong.
Please help me to figure it out

As Swift arrays have associated I don't think that you can declare type with array without specifying its associated type. I am not sure why you do not get compile time errors. This should work:
var tempArray1 = ["sdds","dsads"]
var tempArray2: AnyObject = ["sddsa",34,tempArray1]
var dictionary: [String:Array<AnyObject>] = ["key1":["value1"],"key2":["value2",6,tempArray2]]
let allValues = [Array<AnyObject>](dictionary.values)
for value in allValues{
println(value)
}
Or even shorter:
var tempArray1 = ["sdds","dsads"]
var tempArray2: AnyObject = ["sddsa",34,tempArray1]
var dictionary: [String:[AnyObject]] = ["key1":["value1"],"key2":["value2",6,tempArray2]]
let allValues = dictionary.values
for value in allValues{
println(value)
}

You can try this also
var tempArray1 = ["sdds","dsads"]
var tempArray2: AnyObject = ["sddsa",34,tempArray1]
println("Array inside array \(tempArray2)")
var dictionary: [String:Array] = ["key1":["value1"],"key2":["value2",6,tempArray2]]
println(dictionary)
let allValues = Array(dictionary.values)
for value in allValues{
println(value)
}

Related

Changing value in Dictionary in a Array in UserDefaults

I have a problem changing the value of a Dictionary in a Array
var array = (defaults.array(forKey: "Transactions")! as! [Dictionary<String, Any>])
(array.reversed()[index]["Title"] as! String) = titleTextField.text! // Cannot assign to immutable expression of type 'String'
Cannot assign to immutable expression of type 'String'
This is the error I get back
Is there a solution to this problem?
As Joakim points out, array.reversed() returns an immutable array.
Try this:
guard
var array = (defaults.array(forKey: "Transactions")! as? [Dictionary<String, Any>]),
let newText = titletextfield.text,
array[array.count-index]["Title"] = newText
(And then re-save your array to UserDefaults)
One more step will work
if var array = UserDefaults.standard.array(forKey: "Transactions") as? [Dictionary<String, Any>], let valueText = titleTextField.text {
array.reverse()
array[index]["Title"] = valueText
}

cannot assign to immutable expression of type anyobject

var arr_contacts2 = [AnyObject]()
ViewDidLoad(){
for contacts in info {
var dict_contact = [String:AnyObject]()
dict_contact["id"] = contacts.contact_id
dict_contact["type"] = contacts.type
dict_contact["value"] = contacts.value
arr_contacts2.append(dict_contact)
}
}
IBAction(){
var dict_contact = arr_contacts2[0]
dict_contact["value"] = "gg" //Cannot assign to immutable expression of type 'AnyObject?!'
}
Why I am getting this error?
What is the wrong with the code?
Help me to solve this.
Thank you for your time
ISSUE IN YOUR CODE:
var dict_contact = arr_contacts2[0] // IT ASSIGNS object of type "AnyObject" to dict_contact
//compiler couldn't possibly know, that dict_contact have a dictionary value
UPDATE YOUR CODE as below
func IBAction(){
guard let dict_contact = arr_contacts2[0] as? [String:AnyObject]
else{
return
}
var contactInfo = dict_contact
contactInfo["value"] = "gg" //Now it should work
}
OR
Declare your arr_contacts2 as below
var arr_contacts2 = [[String:AnyObject]]()
arr_contacts2 is of type [AnyObject].
contact is of type AnyObject.
You cannot assign a String to contact["value"].
It should work if you change arr_contacts2 to [[String: Any]].

Cannot subscript a value of type '[Int : [String]]' with an index of type 'String!'

please, ask me, where is my mistake? I have Xcode error:
Cannot subscript a value of type '[Int : [String]]' with an index of
type 'String!'
in let keyExists = myDict[tmp.Hour] != nil, myDict[tmp.Hour] = Int and myDict[tmp.Hour].append(tmp.Minutes) of that part of code:
func array() -> Dictionary <Int,[String]>
{
let timeInfos = getTimeForEachBusStop()
var myDict: Dictionary = [Int:[String]]()
for tmp in timeInfos {
let keyExists = myDict[tmp.Hour] != nil
if (!keyExists) {
myDict[tmp.Hour] = [Int]()
}
myDict[tmp.Hour].append(tmp.Minutes)
}
return myDict
}
I understand, that problem is in optional type, but where is problem I don't understand
upd
func getTimeForEachBusStop() -> NSMutableArray {
sharedInstance.database!.open()
let lineId = getIdRoute
let position = getSelectedBusStop.row + 1
let getTimeBusStop: FMResultSet! = sharedInstance.database!.executeQuery("SELECT one.hour, one.minute FROM shedule AS one JOIN routetobusstop AS two ON one.busStop_id = (SELECT two.busStop_id WHERE two.line_id = ? AND two.position = ?) AND one.day = 1 AND one.line_id = ? ORDER BY one.position ASC ", withArgumentsInArray: [lineId, position, lineId])
let getBusStopInfo : NSMutableArray = NSMutableArray()
while getTimeBusStop.next() {
let stopInfo: TimeInfo = TimeInfo()
stopInfo.Hour = getTimeBusStop.stringForColumnIndex(0)
stopInfo.Minutes = getTimeBusStop.stringForColumnIndex(1)
getBusStopInfo.addObject(stopInfo)
}
sharedInstance.database!.close()
return getBusStopInfo
}
You are declaring your dictionary as a dictionary with keys of type Int and values of type [String]:
var myDict: Dictionary = [Int:[String]]()
(better written as: var myDict: [Int: [String]] = [:] because by casting it to Dictionary you are removing the types).
However, in
myDict[tmp.Hour] = [Int]()
You are using a value which is of [Int] type and tmp.Hour is probably a String.
So, your problem is a type mismatch.
The error states that you cannot subscribe your [Int:[String]] dictionary with a String key.
Therefore the type of tmp.Hour is obviously String rather than the expected Int
If tmp.Hour is guaranteed to be an integer string you can convert the value
let hour = Int(tmp.Hour)!
myDict[hour] = [Int]()
On the other hand since myDict is [Int:[String]] you might mean
let hour = Int(tmp.Hour)!
myDict[hour] = [String]()
Hour and Minutes are of type string (I guess - stringForColumnIndex) so your dictionary is wrong type. Should be:
func array() -> Dictionary <String,[String]>
{
let timeInfos = getTimeForEachBusStop()
var myDict: Dictionary = [String:[String]]()
for tmp in timeInfos {
let keyExists = myDict[tmp.Hour] != nil
if (!keyExists) {
myDict[tmp.Hour] = [String]()
}
myDict[tmp.Hour].append(tmp.Minutes)
}
return myDict
}

Swift - Array of Any to Array of Strings

How can I cast an array initially declared as container for Any object to an array of Strings (or any other object)?
Example :
var array: [Any] = []
.
.
.
array = strings // strings is an array of Strings
I receive an error : "Cannot assign value of type Strings to type Any"
How can I do?
You can't change the type of a variable once it has been declared, so you have to create another one, for example by safely mapping Any items to String with flatMap:
var oldArray: [Any] = []
var newArray: [String] = oldArray.flatMap { String($0) }
Updated to Swift 5
var arrayOfAny: [Any] = []
var arrayOfStrings: [String] = arrayOfAny.compactMap { String(describing: $0) }
You can use this synatic sugar grammar. Still one line of code :)
var arr: [Any] = []
var strs = [String]()
arr = strs.map {$0 as! [String]}

Swift NSUserDefaults NSArray using objectForKey

I'm pretty new to Swift, and I've managed to get pretty stuck.
I'm trying to retrieve data from NSUserDefaults and store it in an array (tasks):
#lazy var tasks: NSArray = {
let def = NSUserDefaults.standardUserDefaults()
let obj: AnyObject? = def.objectForKey("tasks")
return obj as NSArray
}()
All I'm getting is a warning: EXE_BAD_INSTRUCTION on line 3.
Also to note that I haven't actually set any data yet, but what I'm aiming for is that if there is no data, I want the array to be empty. I'll be using the data to populate a table view.
Now using a var instead of a constant:
#lazy var tasks: NSArray = {
let def = NSUserDefaults.standardUserDefaults()
var obj: AnyObject? = {
return def.objectForKey("tasks")
}()
return obj as NSArray
}()
The error has now moved to the return line.
I think the problem here is that you are attempting to cast nil to a non-optional type and return it. Swift does not allow that. The best way to solve this would be the following:
#lazy tasks: NSArray = {
let defaults = NSUserDefaults.standardUserDefaults()
if let array = defaults.arrayForKey("tasks") as? NSArray {
return array
}
return NSArray()
}
Using Swift's if let syntax combined with the as? operator lets you assign and safe cast in one line. Since your method does not return an optional, you must return a valid value if that cast fails.

Resources