Here I am having Json data which I am retrieving from model class in which I need to find if the key value pair title having word starting with Discount for example if I find key value pair starting with Discount I need to set the particular table view cell label as Discount how to find it from key value pairs can anyone help me how to implement this ?
Here is my model class data
struct TotalPriceSegments {
let code : String?
let title : String?
let value : Double?
init(json: [String:Any]) {
self.code = json["code"] as? String
self.title = json["title"] as? String
self.value = json["value"] as? Double
}
}
Here is table view code
let cell = tableView.dequeueReusableCell(withIdentifier: "checkout", for: indexPath) as! CheckoutTableViewCell
let array = totalPriceModel?.totalSegments[indexPath.row]
cell.titleLabel.text = array?.title
let total = doubleToStringDecimalPlacesWithDouble(number: Double((array?.value)!), numberOfDecimalPlaces: 2)
cell.valueLabel.text = (String(describing:("$ \(total)")))
return cell
In cellForRow method add such check:
if array?.title.hasPrefix("Discount") {
cell.titleLabel.text = "Discount"
}
Related
I have an array of dictionaries, [[String:AnyObject]], which is reduce+sorted as below successfully.
var arrUserList = [(key: String, value: [[String : Any]])]()
let result = self.arrJsonDict.reduce(into: [String: [[String:Any]]]()) { result, element in
let strName: String = (element as! NSDictionary).value(forKey: "name") as! String
if let firstLetter = strName.first {
let initial = String(describing: firstLetter).uppercased()
result[initial, default: [[String:Any]]() ].append(element as! [String : Any])
}}.sorted { return $0.key < $1.key }
self.arrUserList = result
Now I wanted to assign keys to table sections and values as table cell text from the array.
This is very cumbersome code.
You are highly encouraged to use a struct rather than a dictionary at least with a member name
struct Person {
let name : String
}
Declare and rename arrJsonDic (more descriptively) as
var people : [Person]()
and arrUserList as
var users = [String: [Person]]()
For the sections declare another array
var letters = [String]()
Group the array and populate letters simply with
users = Dictionary(grouping: people, by: { String($0.name.first!) })
letters = users.keys.sorted()
In the table view in numberOfSections return
return letters.count
and in numberOfRows return
let letter = letters[section]
return users[letter]!.count
In cellForRowAt assign a name to a label with
let letter = letters[indexPath.section]
let user = users[letter]![indexPath.row]
cell.nameLabel.text = user.name
------------------------------
To make it still swiftier declare a second struct Section
struct Section {
let index : String
let people : [Person]
}
delete
var letters = [String]()
and declare users
var users = [Section]()
The grouping is slightly different
let grouped = Dictionary(grouping: people, by: { String($0.name.first!) })
users = grouped.map({ Section(index: $0.0, people: $0.1) }).sorted{$0.index < $1.index}
The code in the three table view delegate methods are
return users.count
-
return users[section].people.count
-
let user = users[indexPath.section].people[indexPath.row]
cell.nameLabel.text = user.name
In this I am getting data from server response after posting parameters and here I need to display it on table view and it should be displayed like shown below in the image 0 is the price for the particular shipping method
already i had written model class for server response data and here it is
struct ShippingMethod {
let carrierCode : String
let priceInclTax : Int
let priceExclTax : Int
let available : Any
let carrierTitle : String
let baseAmount : Int
let methodTitle : String
let amount : Int
let methodCode : String
let errorMessage : Any
init(dict : [String:Any]) {
self.carrierCode = dict["carrier_code"] as! String
self.priceInclTax = dict["price_incl_tax"]! as! Int
self.priceExclTax = dict["price_excl_tax"]! as! Int
self.available = dict["available"]!
self.carrierTitle = dict["carrier_title"] as! String
self.baseAmount = dict["base_amount"]! as! Int
self.methodTitle = dict["method_title"]! as! String
self.amount = dict["amount"]! as! Int
self.methodCode = dict["method_code"] as! String
self.errorMessage = (dict["error_message"] != nil)
}
}
by using this I had formed an array type like this by using code
var finalDict = [String: [String]]()
var responseData = [ShippingMethod]()
do
{
let array = try JSONSerialization.jsonObject(with: data, options: []) as? [[String : Any]]
for item in array! {
self.responseData.append(ShippingMethod.init(dict: item))
}
print(self.responseData)
}
catch let error
{
print("json error:", error)
}
print(self.responseData)
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [String]()
}
self.finalDict[carrierTitle]!.append(methodTitle)
}
print(self.finalDict)
the output of this finalDict is ["Flat Rate": ["Fixed"], "Best Way": ["Table Rate"]] in this carrier title key value pair should be displayed as section title and is Flat Rate and method title key value pair should be displayed as rows in section Fixed but the problem is I need amount key value pair with it also for corresponding method title can anyone help me how to get this ?
Why don't you create another struct for displaying row data:
struct CarrierInfo {
let name:String
let amount:Int
}
Change your finalDict to
var finalDict = [String: [CarrierInfo]]()
and create CarrierInfo instance and set it in finalDict
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
let amount = dict.amount
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [CarrierInfo]()
}
self.finalDict[carrierTitle]!.append(CarrierInfo(name: carrierTitle, amount: amount))
}
Likewise you can make other required changes. This would neatly wrap your row display data inside a structure.
PS: I have not tested the code in IDE so it may contain typos.
You can assign another dictionary with key as methodTitle and amount as value. i.e., ["fixed":"whatever_amount"]
OR
You can use finalDict differently, like ["Flat Rate": ["tilte":"Fixed","amount":"0"], "Best Way": ["title":"Table Rate","amount":"0"]]
If it is difficult for you to code this, you can revert back.
Edit
You can use the following code to create the array in the second solution I suggested above:
for item in self.responseData {
let dict = item
let carrierTitle = dict.carrierTitle
let methodTitle = dict.methodTitle
let amount = dict.amount
if self.finalDict[carrierTitle] == nil {
self.finalDict[carrierTitle] = [[String:String]]()
}
let innerDict = ["title":methodTitle,"amount":amount]
self.finalDict[carrierTitle]!.append(innerDict)
}
I declared a class with all the variables in it.
class Xyz
{
var a: String?
var b: String?
}
In other viewController, I am declaring an array of that class.
var arr = [Xyz]()
var arr2 = ["title1","title2"]
After Json Parsing, I am appending the values in this array.
var temp = Xyz()
var dict = item as! NSDictionary
temp.a = (dict.value(forKey: "a") as? String) ?? ""
temp.b = (dict.value(forKey: "b") as? String) ?? ""
self.arr.append(temp)
How should I display this array in a cell?
cell.textLabel?.text = arr2[indexPath.row]
//The above array shows the title of the row
cell.detailTextLabel?.text = String(describing: arr[indexPath.row])
//indexPath doesn't work here (error: indexPath out of range)
//The reason is the 'arr' array has class in it
The above statement gives error as the array has class in it and not the values.
cell.detailTextLabel?.text = String(describing: arr[0].a)
cell.detailTextLabel?.text = String(describing: arr[0].b)
is the only way I can access my values.
Due to which I am unable to display this array in my tableView.
How to display the content of the array on a tableView cell(each on separate cell)?
There are many mistakes / bad programming habits in the code.
First of all name the class starting with a capital letter and declare the properties non-optional because they are going to contain non-optional values. (Declaring optionals as an alibi not to write an initializer is one of the bad habits.)
Include the title of the row from arr2 as title property in the class, that avoids any out of range exception.
class Xyz
{
var a : String
var b : String
var title : String
init(a: String, b: String, title: String) {
self.a = a
self.b = b
self.title = title
}
}
Declare the data source array
var arr = [Xyz]() // `var arr: [xyz]()` does not compile
Populate the data source array
let dict = item as! [String:Any] // Swift Dictionary !!
let temp = Xyz(a: dict["a"] as? String) ?? "", b: dict["b"] as? String) ?? "", title: "title1")
self.arr.append(temp) // `self.arr.append(value)` does not compile
In cellForRow get the Xyz instance from the array and use the properties
let item = arr[indexPath.row]
cell.textLabel?.text = item.title
cell.detailTextLabel?.text = item.a + " " + item.b
Since all properties are strings anyway, all String(describing initializers (create String from String) are nonsensical.
It seems like you want to display your class properties
Replace the line
cell.detailTextLabel?.text = String(describing: arr[indexPath.row])
With
cell.detailTextLabel?.text = "\(arr[indexPath.row].a) \(arr[indexPath.row].b)"
I went through all the below answers. But none of them produced the solution. The problem in all solution is the array is printed on same cell, leaving the other cell empty(including the answer provided by Vadian - it will give error because it is printing all the value in same row.). While printing an array on a cell, you have to go in a loop, But none of the answers provides that. This will give error back Index out of range .The best solution I came across is to use switch or enum. Due to switch or enum you can put a condition for every row and according to that you can print the item from the array. Here I put the simple array item "title" as case and according to that printed the array of class.
Solution:- The following code helped me to achieve what I asked.
Note:- enum is more preferred than switch. I used switch because easy to understand and got my work done.
let a = arr2[indexPath.row]
let item = arr[0]
switch a
{
case "title1":
cell.detailTextLabel?.text = item.a
return cell
case "title2" :
cell.detailTextLabel?.text = item.b
return cell
default:
break
}
I'm going to display some data from NSArray in the tableViewCell.
Here is my NSArray format
(
{
score = "480.0";
uid = 2;
},
{
score = "550.0";
uid = 1;
}
)
So, how to display for example score?
Here is m code, but it doesn't display it
var gamesRound: NSArray = []
let game = gamesRound[indexPath.row]
//let user = users[Int(game.userId - 1)]
cell.textLabel?.text = game as? String
//cell.detailTextLabel?.text = "\(String(Int(game.score))) PTS"
//print(user.fullname!)
return cell
Change your gamesRound variable to Array of Dictionary like this:
Put some value like this, in viewDidLoad (maybe):
var gamesRound = [[String: Any]]()
To render value on cells of a UITableView
gamesRound = [["score": "480.0", "uid" = 2], ["score": "550.0", "uid": 1]]
Some what like this:
let game = gamesRound[indexPath.row] as! [String: Any]
cell.textLabel?.text = "\(game["score"] as? Int ?? 0)"
cell.detailTextLabel?.text = "\(game["uid"] as? Int ?? 0)"
seems to me that you have an NSDictionary in each position of you NSArray.
So, use this code to get the position that you want:
let game = gamesRound[indexPath.row]
Now the game is an NSDictionary and you only need to extract the information using the key that you want:
let uid = game["uid"]
let score = game["score"]
I hope my example helps you.
Here you have the Array of dictionary so when you write let dict = gamesRound[indexPath.row] you will get the dictionary object and you can get the value by using the key because dictionary has the key value pair while the array has the indexing.
Also, you can Declare array like this
var gamesRound: Array<Dictionary<String,Any>> = []
So you can verify by printing the values step by step:
print(gamesRound)
let dict = gamesRound[indexPath.row] as! Dictionary<String,Any>
print(dict)
let score = dict["score"]
print(dict["score"])
cell.textLabel?.text = "\(score!)"
Try this code,
let gameRound : NSDictionary = yourArray[indexPath.row] as! NSDictionary
let strUid = gameRound["uid"]
cell.textLabel.text = strUid as? String
I am getting JSON data from an url like this:
...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("jsonCell") as! CeldaGeo
var dict = arrRes[indexPath.row]
cell.cofradia.text = dict["cofradia"] as? String
cell.calle.text = dict["calle"] as? String
cell.id.text = dict["idc"] as? String
cell.tipo.text = dict["tipo"] as? String
cell.latitud.text = dict["latitud"] as? String
cell.longitud.text = dict["longitud"] as? String
cell.tipo.text = dict["tipo"] as? String
let tipo = dict["tipo"] as? String
let id = dict["idc"] as? String
cell.imagen.kf_setImageWithURL(NSURL(string: "http://elpenitente.playcofrade.com/img/escudos/\(tipovalue)/\(id!).jpg")!)
return cell
After, I load an image from an url which changes depending the other values.
My problem is, the value tipois a number (1,2,3) but in the url it should be text. For example 1 will be cofradias. How can I assign this values so that I can use them later?
If I understood your problem correctely. You only need to have a separate dictionary mapping the ids with its strings.
let imageNames = ["1":"cofradias","2":"string2","3":"string3"]
Then in your code you'll use it like:
let id = dict["idc"] as? String
let tipo = dict["tipo"] as? String
let imageName = imageNames[tipo!]
cell.imagen.kf_setImageWithURL(NSURL(string: "http://elpenitente.playcofrade.com/img/escudos/cofradias/\(imageName!)/\(id!).jpg")!)