Swift import dictionary to tableviewcell - swift

I am trying to create a table view to show the content of a dictionary called tableText<String, String>. But in the cellForRowAtInSection method, when I do something like
let obj = tableText[indexPath.row]
It gives me a error saying that
cannot subscript a value of type 'Dictionary<String, String> with an index of Int.
I also tried things like
let obj = tableText[indexPath.row] as? NSDictionary
but the error is still there.
Could you help me with this please?

If you just want the values, you can get an array of values from the dictionary and used the indexPath.row on that array.
if let text = tableText.values[indexPath.row] as? String {
cell.textLabel.text = text
}
Obviously if you need them to be sorted you would have to sort them as dictionary is not sorted based on keys.
If you wanted them sorted alphabetically, you could do this
let sortedText = tableText.values.sorted { $0.localizedCaseInsensitiveCompare($1) == NSComparisonResult.OrderedAscending }
And use this sortedText array as your datasource

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).

Variable used within its own initial value Swift 3

I try to convert my code to swift 3 an I have spent hours on the following error:
Type 'Any' has no subscript members
Here's was my original code:
let data: AnyObject = user.object(forKey: "profilePicture")![0]
I looked at the answers here but I'm still stuck. (I do programming as a hobby, I'm not a pro :/)
I've try that:
let object = object.object(forKey: "profilePicture") as? NSDictionary
let data: AnyObject = object![0] as AnyObject
But now I get this error:
Variable used within its own initial value
Second issue: Use always a different variable name as the method name, basically use more descriptive names than object anyway.
First issue: Tell the compiler the type of the value for profilePicture, apparently an array.
if let profilePictures = user["profilePicture"] as? [[String:Any]], !profilePictures.isEmpty {
let data = profilePictures[0]
}
However, the array might contain Data objects, if so use
if let profilePictures = user["profilePicture"] as? [Data], !profilePictures.isEmpty {
let data = profilePictures[0]
}
Or – what the key implies – the value for profilePicture is a single object, who knows (but you ...)
And finally, as always, don't use NSArray / NSDictionary in Swift.

Cannot convert return expression of type 'AnyObject' to return type 'NSComparisonResult'

I have a Swift based iOS application. I am trying to use one of the Swift sort methods to sort my array of objects by the "createdAt" NSDate property.
My array has a bunch of PFObject - these objects have different properties including an NSDate property called "createdAt".
All I want to do, is to order the array so that the objects which are the oldest, are sent to the bottom of the array.
Here is my code:
let sortedArray = (self.statusData.copy() as! NSArray).sortedArrayUsingComparator { (obj1, obj2) -> NSComparisonResult in
if (((obj1 as! PFObject).createdAt?.compare((obj2 as! PFObject).createdAt!)) == NSComparisonResult.OrderedDescending) {
return obj2
}
else {
return obj1
}
}
However when I try to return the objects, I get the following error:
Cannot convert return expression of type 'AnyObject' to return type
'NSComparisonResult'
I don't understand whats wrong, why can't I just return the date comparison result which is determined my if statement?
Thanks for your time, Dan.
Your problem is that it's expecting a return type of NSComparasonResult and you're returning anAnyObject. However, you are already getting an NSComparasonResult in your existing code. Therefore, simply replace all of that with this:
let sortedArray = (self.statusData.copy() as! NSArray).sortedArrayUsingComparator { (obj1, obj2) -> NSComparisonResult in
return (obj1 as! PFObject).createdAt?.compare((obj2 as! PFObject).createdAt!)
}

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]]