I am currently trying to populate a UITableView with data from a dictionary. I am getting an error "Cannot subscript a value of type 'Dictionary'". I know what it means but I don't know how to fix it. I know how to make it work with an array. Is it possible to use a dictionary?
// my dictionary
var contactDictionary: Dictionary = [String: String]()
//function that throws error
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "contactcell", for: indexPath) as! UITableViewCell
let object = contactDictionary[indexPath.row]
}
You can use contactDictionary.keys to retrieve the array of keys and use the key to find value, but the order may change every time; Swift does not guarantee the order of dictionary. If order is important, you can search for 3rd party OrderedDictionary or other data structures.
You just need to change your dictionary declaration code from
var contactDictionary: Dictionary = [String: String]()
to
var contactDictionary = [String: String]()
or
var contactDictionary: [String: String] = [:]
As already mentioned in comments Dictionary is an unordered collection. If you need to keep it sorted you can use an array of key value pairs:
var contacts: [(key: String, value: String)] = []
Related
I have an array defined like so..
var filteredData = [[String: Any]]()
But when I try to convert it like so,
var filteredArray = filteredData as! NSMutableArray //CRASH HERE
dic = filteredArray[indexPath.row] as! NSMutableDictionary
cell.Sched_celltitle.text = "\(dic["name"]!)"
I get a crash like mentioned above saying Could not cast value of type 'Swift.__SwiftDeferredNSArray' (0x103..) to 'NSMutableArray' (0x200..).
Unlike the immutable types NSMutable... collection types are not related to native Swift collection types.
You cannot even cast the type from NSArray to NSMutableArray in Objective-C.
Just don't do that. NSMutable... collection types are pointless in Swift. The native types declared as variable are mutable for free.
var filteredData = [[String: Any]]()
...
let item = filteredArray[indexPath.row]
cell.Sched_celltitle.text = item["name"] as? String
A much better way is to create a custom struct replacing the quite unspecified [String:Any] dictionary
The goal of this code below is to filter out dictionaries with a certain ID, where ID is a string.
let dictArray = networkData["dicts"] as! [[String:AnyObject]]
localData["dicts"] = dictArray.filter{ ($0["id"] as! String) != sample.getId() }
This code, however, generates an error:
Cannot invoke 'filter' with an argument list of type '(([String :
AnyObject]) throws -> Bool)'
Based on other SO answers like this one and this one, it seems the error is the dictionaries don't conform to Equatable.
So is the only option for using filter to create a custom class to hold the array of dictionaries and make that class conform to Equatable?
If so, perhaps it seems cleaner to simply iterate and create a new array.
Filtering [[String:AnyObject]] (a.k.a. Array>) results in another [[String:AnyObject]]. You're trying to assign this to a var of type AnyObject, which is not allowed in Swift 3, since arrays are structs, not objects.
Make a type-safe struct or object to hold this data, rather than a dict.
For example:
let dictArray = networkData["dicts"] as! [[String:AnyObject]]
let filteredDicts = dictArray.filter{ ($0["id"] as! String) != sample.getId() }
localData["dicts"] = filteredDicts
The issue isn't on hash objects not conform to Equatable because you are using String to do the comparing.
I have the code runs well in Playground:
// make sure data is type of [String: [[String: AnyObject]]]
// make sure filteredData is type of [String: [[String: AnyObject]]]
let key = "hashes"
if let hashArray = data[key] {
let id = sample.getId() // make sure it's String type
filteredData[key] = hashArray.filter { ($0["id"] as? String) != id }
}
I'd like to populate a tableView with results from a Firebase query. I successfully get the results and store them into an array but I'm struggling with how to put those values into the table.
I'm getting back a "userID" and a "title". I'm storing those in an array [[String]]. An example of an array after getting back a value would be [["OYa7U5skUfTqaGBeOOplRLMvvFp1", "manager"],["JQ44skOblqaGBe98ll5FvXzZad", "employee"]]
How would I access an individual value, such as the userID? This is what I have so far in my cellForRowAtIndexPath function:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
let invite = inviteArray[indexPath.row]
print(inviteArray)
print(invite)
return cell
}
Thanks!
EDIT: added function to store snapshot in an array
var dictArray: [Dictionary<String, String>] = []
func getAlerts(){
let invitesRef = self.rootRef.child("invites")
let query = invitesRef.queryOrderedByChild("invitee").queryEqualToValue(currentUser?.uid)
query.observeEventType(.Value, withBlock: { snapshot in
for child in snapshot.children {
guard let invitee = child.value["invitee"] as? String else{
return
}
guard let role = child.value["role"] as? String else{
return
}
self.dictArray.append(child as! Dictionary<String, String>)
print(self.dictArray)
}
})
}
I want to display some of name on tableview cell which is stored in postFromFriends array but when i wrote this code which is shown below its give me an error of " Cannot subscript a value of type 'String' with an index of type 'String' " on declaration of name constant. If anyone can help.Thanx
var postsFromFriends = [String]()
This is my array for appending the name.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as! FriendsTaskTableViewCell
if let name = postsFromFriends[indexPath.row]["name"] as? String {
cell.name?.text = name
}
return cell
}
You have declared postsFromFriends as an array of String, but it sounds like you want an array of dictionary:
var postsFromFriends = [[String:String]]()
Assuming from your error message that postsFromFriends is an array of Strings, then postsFromFriends[indexPath.row] returns a String, which you're then trying to subscript with ["name"]. Did you perhaps intend your postsFromFriends array to store Dictionaries, or some custom object type that has a subscriptable name field?
I am using this library to parse an API endpoint that returns an array: https://github.com/SwiftyJSON/SwiftyJSON
I am grabbing an array fetched from a JSON response and I am trying to feed it into a table.
Right after my class in my view controller is declared, I have
var fetched_data:JSON = []
Inside of my viewDidLoad method:
let endpoint = NSURL(string: "http://example.com/api")
let data = NSData(contentsOfURL: endpoint!)
let json = JSON(data: data!)
fetched_data = json["posts"].arrayValue
To feed the table, I have:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell1")! as UITableViewCell
cell.textLabel?.text = self.fetched_data[indexPath.row]
return cell
}
I am getting this error, when trying to set the cell textLabel:
Cannot subscript a value of a type ‘JSON’ with an index type of ‘Int’
How do I do this properly and get this to work?
You are declaring fetched_data as JSON
var fetched_data:JSON = []
but you are assigning Array to it:
fetched_data = json["posts"].arrayValue
Lets change the type to array of AnyObject:
var fetched_data: Array<AnyObject> = []
and then assigning should be like this (we have [AnyObject] so we need to cast):
if let text = self.fetched_data[indexPath.row] as? String {
cell.textLabel?.text = text
}
Edit: You also need to remember to assign correct Array, by doing arrayObject instead of arrayValue:
fetched_data = json["posts"].arrayObject