I have an object which has properties and I want to display each property as tableview row. How should I prepare my datasource
For eg:
struct Car {
var make: String
var model: String
var year: String
var vin: String
}
let ford = Car(make: Ford, model: Mustang, year: 2018, vin: 1234)
Now in my tableview i need to display like below i.e., each property as a table row cell
How do I prepare my data source?
I understand that I need to add this to array with propertyname: value like
["make":"Ford", "model":"Mustang", ...]
but how can i do that and how can i parse it to display in my cellForRow method.
Please advice
This is just sample. In my actual struct I have more than 20 properties and each needs to be display in table row. So wanted this to be in tableview
Assuming you know your structure...
Create a custom table view cell, with a "property name" label and a "value" label (as shown in your image).
Add class variables:
let propertyArray = [
"Make",
"Model",
"Year",
"VIN"
]
var valueArray: [String] = [String]()
when you've selected a Car object,
valueArray = [
selectedCarObject.make,
selectedCarObject.model,
selectedCarObject.year,
selectedCarObject.vin
]
Now, your tableView implementation can use:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return labelArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell", for: indexPath) as! MyCustomCell
cell.propertyLabel.text = propertyArray[indexPath.row]
cell.valueLabel.text = valueArray[indexPath.row]
return cell
}
var modelDictionary = ["make":"Ford", "model":"Mustang", ...]
Your modelDictionary will be your datasource, im assuming your cell has two label which you will put the data of key and value of the dictionary.
how will you make an Dictionary of your model data?
You can try creating a function on your model to create an Dictionary for each property it has.
Hope i answer you question.
Related
I have a tableView controller that is pulling data from JSON, the table contains sections and row data using the following structure:
import UIKit
struct Section {
let name : String
let items : [Portfolios]
}
You probably forgot to respecify the value of structure in your didSelectRowAtIndexPath.
Therefore please change your tableView's didSelectRowAtIndexPath method to:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Add this line
structure = sections[indexPath.section].items
let theStructure = structure[indexPath.row]
codeSelected = theStructure.code
// ... code selected must have taken the correct value
}
I have Created two Dictionary of question and answer , and I have created two label in my table view for displaying question and their options serial wise , but after displaying the result into the table view it is shown as the given screenshot , help me to show these data in standard for of question and answer with options
*I have created Dictionary of two*
`[Int:String]`and [Int:Array<String>]
, *and now I want access it in my Table view serially with dictionary1 in question label and dictionary2 in answer label;*
Code --
var dictionary1:[Int:String] =
[0:"Whether you have experienced Pricking-pain, Desquamation,itching or dry skin sensation during seasonal alternate.",
1:"Whether your skin apt to flush( Redness) in hot humid environment ",
2:"Whether your skin has multiple disernible dilated capillaries.",
3:"whether you have once been diagnosed atopic dermatitis or seborrheic dermatitis."]
Dictionary2 for creating options to the questions
var dictionary2 : [Int:Array<String>] =
[0:["Never","Seldom","Usually","Always"],
1:["Never","Seldom","Usually","Always"],
2:["Never","Seldom","Usually","Always"],
3:["Yes", "No"]]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dictionary1.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.questionLabel.text = dictionary1[indexPath.row]
cell.questionLabel.textColor = UIColor.black
let arr = dictionary2[indexPath.row]
var strr = String()
for str in arr! {
strr = strr + str
}
cell.optionsLabel.text = strr
cell.optionsLabel.textColor = UIColor.black
return cell
}
}
// HERE IS THE SCREENSHOT OF MY TABLE VIEW , IT IS NOT SHOWING THE DATA IN MULTILINE AND THE OPTIONS AND THE QUESTION ARE OVERLAPPING
[![enter image description here][1]][1]
List item
[1]: https://i.stack.imgur.com/Erpvq.png
Replace below delegate with yours:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
// TO Display Single Dictionary Data
cell.textLabel?.text = dictionary1[indexPath.row]
// To display Array of string stored in dictionary
cell.textLabel?.text = dictionary2[indexPath.row]?.joined(separator: "\n")
return cell
}
For 2nd Requirement
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dictionary1.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
// FOR FIRST DICTIONARY
cell.lblFirst?.text = dictionary1[indexPath.row]
// FOR SECOND DICTIONARY
cell.lblSecond?.text = dictionary2[indexPath.row]?.joined(separator: "\n")
return cell
}
Note: I wanted to make it a comment, but I also wanted to share this image so I answered, but it's a hint, not the complete answer.
The function you are using takes an array of String as input. you can see the below screen for any function by pressing the option key and clicking the function body.
You need to pass the key as a string. then your dictionary must have a key type as String. Once you make the key a string.
Possible solutions are:
if you are keeping key as Int, then use: dictionary1[indexPath.row]
if you make your key as a string then use: dictionary1["\(indexPath.row)"]
(Just for this case) If you want to show them in a sequence only like 0th element 1st element.. then why not use an Array instead of Dictionary.
arry = ["1st description","2nd description"]
and then use
cell.label.text = arry[indexPath.row]
I am fetching previously selected categorylist from the server. say for an example.cateogrylist i fetched from the server was in following formate
categoryid : 2,6,12,17
now what i need to do is want to enable checkmark in my tableview based on this categorylist,for that purpose i converted this list into an [Int] array like this :
func get_numbers(stringtext:String) -> [Int] {
let StringRecordedArr = stringtext.components(separatedBy: ",")
return StringRecordedArr.map { Int($0)!}
}
in viewDidLoad() :
selectedCells = self.get_numbers(stringtext: UpdateMedicalReportDetailsViewController.catId)
print(myselection)
while printing it's giving me results like this : [12,17,6,8,10]
i want to enable checkimage based on this array.I tried some code while printing its giving me the right result like whatever the categories i selected at the time of posting ,i am able to fetch it but failed to place back this selection in tableview.Requirement : while i open this page it should show me the selection based on the categorylist i fetched from the server.
var selectedCells : [Int] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell1 = table.dequeueReusableCell(withIdentifier: "mycell") as! catcell
cell1.mytext.text = categoriesName[indexPath.row]
if UpdateMedicalReportDetailsViewController.flag == 1
{
selectedCells = self.get_numbers(stringtext: UpdateMedicalReportDetailsViewController.catId)
cell1.checkimage.image = another
print(selectedCells)
}
else
{
selectedCells = []
cell1.checkimage.image = myimage
}
return cell1
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = table.cellForRow(at: indexPath) as! catcell
cell.checkimage.image = myimage
if cell.isSelected == true
{
self.selectedCells.append(indexPath.row)
cell.checkimage.image = another
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let cell = table.cellForRow(at: indexPath) as! catcell
if cell.isSelected == false
{
self.selectedCells.remove(at: self.selectedCells.index(of: indexPath.row)!)
cell.checkimage.image = myimage
}
}
output :
This is a very common use case in most apps. I'm assuming you have an array of all categories, and then an array of selected categories. What you need to do is in cellForRowAtIndexPath, check to see if the current index path row's corresponding category in the "all categories" array is also present in the "selected categories" array. You can do this by comparing id's etc.
If you have a match, then you know that the cell needs to be selected/checked. A clean way to do this is give your cell subclass a custom load method and you can pass a flag for selected/checked.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = table.dequeueReusableCell(withIdentifier: "mycell") as! catcell
let category = self.categories[indexPath.row] // Let's say category is a string "hello"
Bool selected = self.selectedCategories.contains(category)
cell.load(category, selected)
return cell
}
So with the code above, let's say that categories is just an array of category strings like hello, world, and stackoverflow. We check to see if the selectedCategories array contains the current cell/row's category word.
Let's say that the cell we're setting up has a category of hello, and selectedCategories does contain it. That means the selected bool gets set to true.
We then pass the category and selected values into the cell subclass' load method, and inside that load method you can set the cell's title text to the category and you can check if selected is true or false and if it's true you can display the checked box UI.
I have list of product items to display in my table view. At the same time i have i have some other api call, Where i will pass my prodcut item name to check. If that product item is available then that particular data or item cell alone will be highlighted and it will be disabled.
Now what i need is, when i do api call, and after that if that particular data or product name is available in that api, instead of highlight and disable... I should not show that particular data in my table view.
How to do that:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! AllConnectionsTableViewCell
if let contact = filtered?[indexPath.row]{
cell.emailOutlet.text = AccountDataCache.sharedInstance.displayMaskAccnt(items: product.name)
cell.nameOutlet.text = product.name
if let _ = self.checkapicall(items: product.name){
// here if my product name is availble in api, then only the backgroudnd and it will be disabled
if let product = filtered?[indexPath.row]{
cell.namelabel.text = product.name
if let _ = self.checkapicall(items: product.vpa){
cell.cellOuterView.backgroundColor = UIColor.red
cell.isUserInteractionEnabled = false
}else{
cell.cellOuterView.backgroundColor = UIColor.white
cell.isUserInteractionEnabled = true
}
}
}
Instead of chnaging BG, Disable..i should not show that data in that tableview cell.How to do that.?
Thanks
As you described, if your data looks like this:
name1, name2,name3, name4
Then you want to show four rows in your tableView.
If name2 is available in your API call then you want to show this:
name1, name3, name4
So what you need to do is to get all the names before you start updating the tableView. This is because you need to set how many rows you want to display in your tableView.
You could do something like this (I´m not sure how you fetch your data today, but this is an example to get you started):
// check add edit to your product
var products = [Product(name: "name1", vpa: "1"), Product(name: "name2", vpa: "2"), Product(name: "name3", vpa: "3"), Product(name: "name4", vpa: "4")]
// set the produts count
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return products.count
}
// just set the name here, don´t make any checks
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "StartPageCell", for: indexPath)
cell.namelabel.text = product.name
return cell
}
// check the names here and then reload the tableView
func checkNames() {
for product in products {
if self.checkapicall(items: product.vpa){ {
if let index = products.index(where: { $0.vpa == vpa }) {
products.remove(at: index)
}
}
}
tableView.reloadData()
}
First of all don't make such checks in cellForRow, make it in viewDidLoad or viewWillAppear
Add a property var isAvailable = false to your product model
In viewDidLoad or viewWillAppear check the availability of the products and set isAvailable accordingly.
Create the data source array var filtered = [Product]() (assuming Product is the data model) and filter the items filtered = allItems.filter { $0.isAvailable }
Reload the table
I have been trying to add a tableview in my ViewController unfortunately no data is shown in my table view. numberOfSectionsInTableView , numberOfRowsInSection , cellForRowAtIndexPath are not even getting called.I tried tableview inside ViewController as there is another controls like label , text field's and TableView underneath .Because of these label's and text fields I am unable to use a TableViewController. what I have done ...
Created a UIViewController and added controls like label , text fields etc.
From Object Library I dragged a TableView into my UIViewController.
To manage my data from server I created a Model
class Model {
var name : String
var email : String
init?(name : String , email : String)
{
self.name = name
self.email = email
} }
as I have dynamic data, for the cell I created a swift file under the Subclass UITableViewCell named userinfoCell and connected my labels(two label's inside TableViewCell one for username and another for email) to this class(userinfoCell).
Finally in my UIViewController I have added the following code to populate my Table View.
Inside my class definition I have initialised a global variable like this
var model = [Model]()
I have created a function that adds data to my model
func loadMembers()
{
let member1 = Model(name: "Caprese Salad", email: "caprreswe#gmail.com")!
let member2 = Model(name: "Capresed", email: "pepperoni#gmail.com")!
model += [member1, member2]
}
on my ViewDidLoad I calls this function
override func viewDidLoad() {
super.viewDidLoad()
loadMembers()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return model.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Members", forIndexPath: indexPath) as! userinfoCell
let member = model[indexPath.row]
cell.MemberName.text = member.name
cell.MemberEmail.text = member.email
return cell
}
But I am getting an Empty table view. What went wrong in my approach
how can I implement a dynamic UITableView inside UIViewController ???
Modify your loadMembers method like this,
func loadMembers()
{
let member1 = Model(name: "Caprese Salad", email: "caprreswe#gmail.com")!
let member2 = Model(name: "Capresed", email: "pepperoni#gmail.com")!
model += [member1, member2]
// reload the table view after modifying the data source.
self.tableView.reloadData()
}
Ctrl drag from table view to View controller and set datasource and delegate
then call self.tableView.reloadData() in loadMember()
Hold control and drag from tableview to view controller and set data source and delegate like this...