Swift iOS 8, first value of NSDictionary - iphone

I have NSDictionary, I know it only has one key and one value, how can I directly get the first value from it?
thanks,

If you have a Swift Dictionary and you know you have exactly 1 key/value pair you can do this:
var dict = ["aaa":"bbb"]
let v = dict.values.first!
If you have more than 1 key/value pair then there is no "first" value since dictionaries are unordered. If you have no key/value pairs this will crash.
If you have an NSDictionary, you can use allValues.first!, but you'll have to cast the result because the value will be an AnyObject:
var dict:NSDictionary = ["aaa":"bbb"]
let v = dict.allValues.first! as! String
or:
let v = dict.allValues[0] as! String

Cast to a Swift Dictionary if it isn't one already. Then use the values property, cast to an Array, and get index 0.
let v = Array(myDictionary.values)[0]

Related

Cast Array<Any> to Array<Int> in Swift

I have array of Any objects called timestamps, in which first object is string, and rest objects are Int. What i want is, to drop first element and treat rest of array as Array of Int objects..
I tried:
let timestamps = xAxisData.dropFirst()
if let timestamps = timestamps as? Array<Int> {
}
It compile, but it says - Cast from 'ArraySlice<Any>' to unrelated type 'Array<Int>' always fails
I could possibly iterate through array and create new temporary array with check every element whether it Int or not, but i think there is a better cleaner way?
You need to create an Array from the ArraySlice created by dropFirst.
let timestamps = Array(xAxisData.dropFirst())
if let timestamps = timestamps as? [Int] {
}
I like to use something like a flatMap so no matter were the non-Int values are in the array they are not consider for the resulting array.
let originalArray:[Any] = ["No int", 2, 3, "Also not int", 666, 423]
let intArray:[Int] = originalArray.flatMap { $0 as? Int }
print(intArray)
Will print this:
[2, 3, 666, 423]
So in your case you could do something like:
let timestamps = xAxisData.flatMap { $0 as? Int }
As stated by Steve Madsen in the comment below, if you are using Swift 4.1 or newer Apple suggest to used compactMap for getting rid of optional nils so that specific use of flatMap is deprecated.
let timestamps = xAxisData.compactMap { $0 as? Int }
Here is another method to convert a subset of an array with mixed types to something more specific:
let intArray = anyArray.compactMap { $0 as? Int }

Accessing values in a dictionary containing AnyObject

I have some data I stored into a dictionary which is defined as:
let data = Dictionary<String, AnyObject>()
In this dictionary the value is always a string, but the value can be an array or integer or string. But when I try to access an item in a array in this dictionary, like:
let item = data["key"][0]
It gives me this error:
Cannot subscript value of type "AnyObject"
How should I access that item?
You need to tell the compiler that you're expecting an array:
if let array = data["key"] as? [Int] {
let item = array[0]
}
Without that, the compiler only knows that there MAY be an AnyObject in data["key"] (it might also be nil).

Immutable value error when appending to array within dictionary after downcasting

var someDict = [String:Any]()
someDict["foo"] = ["hello"]
(someDict["foo"] as? [String])?.append("goodbye") // error here
I am trying to add a value to an existing dictionary containing an array. The dictionary also contains other non-array values, so it has to have value type Any. The problem is that, when I do this, I get an error Cannot use mutating member on immutable value of type '[String]'. Some Googling turned up a few references such as this suggesting that arrays within dictionaries are always immutable, but the compiler doesn't complain if I do this:
var someDict = [String:[String]]()
someDict["foo"] = ["hello"]
someDict["foo"]?.append("goodbye")
so I suspect that information is outdated and it's something specific to the downcasting. Is there any way I can get around this without copying and re-assigning the entire dictionary value?
Yes, it is related the the downcasting. Try this instead:
var someDict = [String:Any]()
someDict["foo"] = ["hello"]
if var arr = someDict["foo"] as? [String] {
arr.append("goodbye")
someDict["foo"] = arr
}

Swift: dictionary access via index

I want to use values from a dictionary in my UITableViewCells. Can I get those from a dictionary by using indexPath.row for the value and indexPath.section for the key?
you can get the keys array and get the key at indexPath.section like this:
Array(yourDictionary.keys)[indexPath.section]
and you can get the value at indexPath.row from the values array like this:
Array(yourDictionary.values)[indexPath.row]
Edit:
if you want to get the values of a specific section key you should write:
let key = Array(yourDictionary.keys)[indexPath.section]
let array = yourDictionary[key]
let value = array[indexPath.row]
Dictionaries are inherently unordered. If you use dictionary.keys, you can get an array of keys and use that, as #Firas says in his/her answer, but there's no guarantee that next time you fetch an array of keys they will be in the same order.
Another option would be to use Int as the key type, then use the indexPath.row as the key.
It's really better to use an array as a data source for a table view.
If you want to store the values for a sectioned table view in a dictionary you should use an outer section array, which contains an inner row array, which contains a dictionary of values for the cell.
You can use:
Array(yourDictionary)[indexPath.row].key // or .value
Here is my small trick to access Dictionary by index. Just wrap dictionary!
var dict = [String: [Int]]()
dict.updateValue([1, 2, 3], forKey: "firstKey")
dict.updateValue([3, 4, 5], forKey: "secondKey")
var keyIndex = ["firstKey": "firstKey", "secondKey": "secondKey"]
var arr = [[String: [Int]]]()
for (key, value) in dict {
arr.append([keyIndex[key]!: value])
}
print(arr[0]) // ["firstKey": [1, 2, 3]]

Assigning value to constant empty dictionary for first time in swift language

If I declare an empty Constant dictionary and want to initialize later, How can I do it?
let emptyDictionary = Dictionary<String, Float>()
How can i assign value to emptyDictionary?
You can't.
You have to create a variable Dictionary:
var emptyDictionary = Dictionary<String, Float>()
emptyDictionary["key"] = 3.0
Or create a filled constant Dictionary:
let emptyDictionary = ["Key": 3.0]