To display each user input I created a table view which displays an array of structs. It works fine, but I'm currently trying to add a headerCell to each entry displaying the date of the input.
Therefore I created another cell called DateCell displaying the date. Additionally I added: func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) to the TableViewController.
My approach is working, but only partially - the DateCell is being displayed but only once with all timelineCells containing the entries underneath. Every time a entry and therefore a timelineCell is being added, the date inside of the DateCell is solely being updated, but I want every timelineCell to have its own DateCell with its own date.
TableViewController
class TimelineViewController: UIViewController {
#IBOutlet weak var toolbar: UIToolbar!
#IBOutlet weak var timlineView: UITableView!
#IBOutlet weak var buttonBack: UIBarButtonItem!
let defaults = UserDefaults.standard
var isAsc = false
override func viewDidLoad() {
super.viewDidLoad()
sortArray()
self.setToolbarInvisible(toolbar: toolbar)
timlineView.delegate = self
timlineView.dataSource = self
setShadow()
}
...
func sortArray() {
addDataArray.sort(by: { $1.date < $0.date })
}
}
extension TimelineViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return addDataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let rowData = addDataArray[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "TimelineCell") as! TimelineCell
cell.setDrivenKm(drivenKm: rowData.driven)
cell.setConsumedL(consumedL: rowData.consumedL)
cell.setPricePerLiter(pricePerLiter: rowData.pricePerLiter)
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let rowData = addDataArray[section]
let headerCell = tableView.dequeueReusableCell(withIdentifier: "DateCell") as! DateCell
headerCell.setDate(date: rowData.date)
return headerCell
}
}
HeaderCell
class DateCell: UITableViewCell {
#IBOutlet weak var dateLabel: UILabel!
func setDate(date: Date) {
let date = date
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy"
let currentDate = formatter.string(from: date)
dateLabel.text = currentDate
}
}
As Sean mentioned in his comment, you can create a section for every entry of addDataArray.
You need to return sections count and change numberOfRows to 1 in each section. Also you need to change the way you retrieve data for you timeline cells, using section instead of row.
So you need to change your UITableViewDelegate methods like this:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func numberOfSections(in tableView: UITableView) -> Int {
return addDataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let rowData = addDataArray[indexPath.section]
let cell = tableView.dequeueReusableCell(withIdentifier: "TimelineCell") as! TimelineCell
cell.setDrivenKm(drivenKm: rowData.driven)
cell.setConsumedL(consumedL: rowData.consumedL)
cell.setPricePerLiter(pricePerLiter: rowData.pricePerLiter)
return cell
}
Alternatively you can double your cells count and return both header and items as cells
Then you need to make these changes:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return addDataArray.count * 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row % 2 == 0 {
let rowData = addDataArray[indexPath.row / 2 ]
let headerCell = tableView.dequeueReusableCell(withIdentifier: "DateCell") as! DateCell
headerCell.setDate(date: rowData.date)
return headerCell
} else {
let rowData = addDataArray[indexPath.row / 2]
let cell = tableView.dequeueReusableCell(withIdentifier: "TimelineCell") as! TimelineCell
cell.setDrivenKm(drivenKm: rowData.driven)
cell.setConsumedL(consumedL: rowData.consumedL)
cell.setPricePerLiter(pricePerLiter: rowData.pricePerLiter)
return cell
}
}
I've created a playground to show an example. Check it out here.
Related
I have stuck up with an issue where I have a UITableView with a label and button in each row when the button is clicked from a particular row it will navigate to the next view and it has UITableView with a country list, when selected the country it will popup to the previous view and I want to update the country name with selected row, Could someone guide me how to update it. Below is my code. TIA
FirstViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomTableCell
let dict = customData[indexPath.row] as? NSObject
cell.lblTitle.text = "Title"
// cell.lblSubTitle.text = ""
cell.selectedButton.tag = indexPath.row
cell.selectedButton.addTarget(self, action: #selector(buttonClick), for: .touchUpInside)
return cell
}
#objc func buttonClick(sender: UIButton){
let customCell = CountryViewController(nibName: nil, bundle: nil)
self.navigationController?.pushViewController(customCell, animated: true)
}
CountryViewController.swift
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CountryCell", for: indexPath) as! CountryTableCell
cell.lblTitle.text = CountryList[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedCountry = CountryList[indexPath.row]
self.navigationController?.popViewController(animated: true)
}
You can use delegation pattern:
protocol SelectCountry {
func countrySelected(withName countryName: String)
}
in your FirstViewController.swift conform to that protocol
extension FirstViewController: SelectCountry {
func countrySelected(withName countryName: String) {
// Assign country name to your label here
}
in your CountryViewController.swift make a variable called delegate/anyName you want
var delegate: SelectCountry?
in your buttonClick method
customCell.delegate = self
in your CountryViewController in didSelectRowAt method
delegate?.countrySelected(withName: CountryList[indexPath.row])
your label will be updated with country name you selected in CountryViewController.
NOTE: Names are just placeholders here you can use your own names for protocol/methods
First Controller:
"CountrySelectionDelegate" confirm this delegate in your first controller
Next, Pass/Store your FirstViewController cell selection index.
Go to your Country Controller, Select country, Pass it through "func selectedCountry(country: String,index: Int) {}" , Update your custom Data/Array.
Lastly reload your Table view with updated Custom data.
class FirstViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,CountrySelectionDelegate {
#IBOutlet weak var yourFirstTable: UITableView!
var customData = [Details(title: "Title-1", country: ""),Details(title: "Title - 2", country: ""),]
override func viewDidLoad() {
super.viewDidLoad()
}
func selectedCountry(country: String,index: Int) {
self.customData[index].country = country
yourFirstTable.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return customData.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! DetailTableCell
let custInfo = customData[indexPath.row]
cell.yourTitleLabel.text = "Title: " + custInfo.title
cell.yourCountryLabel.text = (custInfo.country.count > 0 ? "Country: \(custInfo.country)" : "Country: ---")
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let nextVC = self.storyboard?.instantiateViewController(withIdentifier: "CountryViewController") as? CountryViewController
nextVC?.selectedIndex = indexPath.row
nextVC?.delegate = self
self.navigationController?.pushViewController(nextVC!, animated: true)
}
}
CountryViewController:
import UIKit
protocol CountrySelectionDelegate {
func selectedCountry(country: String, index:Int)
}
class CountryViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var countryTable: UITableView!
var selectedIndex: Int = 0
let countryList = ["India","USA","UK","Nepal","Bangladesh","Pakistan","Bhutan"]
weak var delegate: CountrySelectionDelegate?
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return countryList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CountryTableViewCell
cell.countryLabel.text = countryList[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.selectedCountry(country: countryList[indexPath.row], index: selectedIndex)
self.navigationController?.popViewController(animated: true)
}
}
I would like to show table view with cell where will be one label and tableview below this label. I have such layout right now:
view above my tables view will be hidden in some conditions so as a result I will have table view on whole screen. So... I found this video where developer managed to solve my task. I did everything similarly to his video but I didn't manage to show table view inside table view cell. Here is my steps:
Added all views to general view.
Attached tags to my table views: 100 for main table view and 90 for inside table view.
Created cell classes and attached them to both cells.
Added extension at main cell like in video.
Handled table view tag in main view controller.
As I see the problem is with inside table view which can't be shown. Below you can see classes for cells. Main cell:
class GeneralCell : UITableViewCell {
#IBOutlet weak var answerOptions: UITableView!
#IBOutlet weak var questionText: UILabel!
}
extension GeneralCell{
func setTableViewDataSourceDelegate <D:UITableViewDelegate & UITableViewDataSource> (_ dataSourceDelegate: D, forRow row: Int)
{
answerOptions.delegate = dataSourceDelegate
answerOptions.dataSource = dataSourceDelegate
answerOptions.reloadData()
}
}
inside cell:
class AnswersCell: UITableViewCell {
#IBOutlet weak var answerOption: UILabel!
}
and here is my view controller:
class PollsController: UIViewController, UITableViewDataSource,UITableViewDelegate {
#IBOutlet weak var questionTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
questionTableView.delegate = self
questionTableView.dataSource = self
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(tableView.tag)
if tableView.tag == 100 {
let cell: GeneralCell = tableView.dequeueReusableCell(withIdentifier: "GeneralCell") as! GeneralCell
cell.answerOptions.reloadData()
return cell
}else{
let cell: AnswersCell = tableView.dequeueReusableCell(withIdentifier: "AnswersCell") as! AnswersCell
return cell
}
}
func numberOfSections(in tableView: UITableView) -> Int {
if tableView.tag == 100 {
return 1
}else{
return 6
}
}
}
Then I did some test for getting to know where the problem is. I added print() into data loader function:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(tableView.tag)
if tableView.tag == 100 {
print("1")
let cell: GeneralCell = tableView.dequeueReusableCell(withIdentifier: "GeneralCell") as! GeneralCell
cell.answerOptions.reloadData()
return cell
}else{
print("2")
let cell: AnswersCell = tableView.dequeueReusableCell(withIdentifier: "AnswersCell") as! AnswersCell
return cell
}
}
and in the output I saw only one tag:
100
and as I see inside table view can't be loaded but I can't understand why. Maybe someone of you will find problem or mistake?
I suggest you use only one tableview, here some example
struct Answer {
let answerText: String
}
struct Question {
let questionText: String
let answers: [Answer]
}
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var questions: [Question] = []
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...10 {
let question = Question(questionText: "Question \(i)", answers: [
Answer(answerText: "Answer 1 Question \(i)"),
Answer(answerText: "Answer 2 Question \(i)"),
Answer(answerText: "Answer 3 Question \(i)"),
Answer(answerText: "Answer 4 Question \(i)")
])
questions.append(question)
}
tableView.dataSource = self
tableView.delegate = self
tableView.sectionHeaderHeight = UITableView.automaticDimension;
tableView.estimatedSectionHeaderHeight = 44
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return questions.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return questions[section].answers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "AnswerCell", for: indexPath) as! AnswerCell
cell.answerLabel.text = questions[indexPath.section].answers[indexPath.row].answerText
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "QuestionCell") as! QuestionCell
cell.questionLabel.text = questions[section].questionText
return cell
}
}
Try this
class GeneralCell : UITableViewCell {
#IBOutlet weak var answerOptions: UITableView!
#IBOutlet weak var questionText: UILabel!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(tableView.tag)
if tableView == questionTableView{
let cell: GeneralCell = tableView.dequeueReusableCell(withIdentifier: "GeneralCell") as! GeneralCell
cell.answerOptions.delegate = self
cell.answerOptions.dataSource = self
cell.answerOptions.reloadData()
return cell
}else{
let cell: AnswersCell = tableView.dequeueReusableCell(withIdentifier: "AnswersCell") as! AnswersCell
return cell
}
}
What I'm trying to do is separate my cells into sections by their Brand
what Ive been able to do so far is pass data of selected items from HomeVC to populate the cells of the CartVC
I am trying to separate the sections by brand, the brand data is a part of the model Items Class (name, brand, imageUrl, price, & weight) and the Items class retrieves data from CloudFirestore to populate the cells of the HomeVC
How would I be able to to separate the cells into sections by their brand, when passed into the CartVC.
So far what I've done seems to fail, because once I pass an item from the HomeVC to the CartVC I only get one header cell, with the brand name of the first item I passed into the CartVC. When I pass more data into the the CartVC all the cells stay in the section of the first item passed when im trying to section off all my CartCells by their brand
extension HomeViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemSetup.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "HomeCell") as? HomeCell else { return UITableViewCell() }
let item = itemSetup[indexPath.row]
cell.configure(withItems: item)
cell.addActionHandler = { (option: Int) in
print("Option selected = \(option)")
self.tray.append(Tray(cart: item))
item.selectedOption = option
}
return cell
}
}
class CartViewController: UIViewController {
var items: ProductList!
var sectionModel: [SectionModel] = []
var tray: [Tray] = []
var groupedItems: [String: [Tray]] = [:]
var brandNames: [String] = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
groupedItems = Dictionary(grouping: tray, by: {$0.cart.brand})
brandNames = groupedItems.map{$0.key}.sorted()
}
}
extension CartViewController: UITableViewDataSource, UITableViewDelegate {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CartCell", for: indexPath) as! CartCell
let cart = tray[indexPath.row]
cell.configure(withItems: cart.cart)
return cell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cartHeader = tableView.dequeueReusableCell(withIdentifier: "CartHeader") as! CartHeader
cartHeader.storeName.text = "Brand: \(tray[section].cart.brand)"
return cartHeader
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 45
}
}
class Tray {
var cart: ProductList!
init(cart: ProductList) {
self.cart = cart
}
}
just set your your tableview functions like and you'll have no problem setting things up by section
func numberOfSections(in tableView: UITableView) -> Int {
return brandNames.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let brand = brandNames[section]
return groupedItems[brand]!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cartCell = tableView.dequeueReusableCell(withIdentifier: "CartCell") as! CartCell
let brand = brandNames[indexPath.section]
let itemsToDisplay = groupedItems[brand]![indexPath.row]
cartCell.configure(withItems: itemsToDisplay.cart)
return cartCell
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cartHeader = tableView.dequeueReusableCell(withIdentifier: "CartHeader") as! CartHeader
let headerTitle = brandNames[section]
cartHeader.brandName.text = "Brand: \(headerTitle)"
return cartHeader
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == table1{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! acntTableViewCell
cell.account.text = account[indexPath.row].email
return cell
}
else if tableView == table2 {
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2")
as! popTableViewCell
cell2.pop.text = pop[indexPath.row].answer
return cell2
}
}//its give me error here Missing return in function
I am going to fill two different tables in one viewcontroller. when I return cell it give me error Missing return in function where I am doing wrong can any one suggest me what's wrong with this code
In the first place, you should compare tables using === (references), not ==.
This is one of the cases when an assertion failure is a good way to tell the compiler that no other way of the function exists e.g.:
if tableView === table1 {
return ...
} else if tableView === table2 {
return ...
} else {
fatalError("Invalid table")
}
You can also use a switch:
switch tableView {
case table1:
return ...
case table2:
return ...
default:
fatalError("Invalid table")
}
Both answers are correct, but I believe the best way to do it would be to separate each table view to have its own data source object, not a view controller. Putting multiple tableview data source protocols adds a decent amount of unnecessary code, and if you refactor them into separate objects, you can help avoid a Massive View Controller.
class FirstTableViewDataSource : NSObject, UITableViewDataSource {
var accounts: [ObjectTypeHere]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return accounts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! AcntTableViewCell
cell.account.text = accounts[indexPath.row].email
return cell
}
}
class SecondTableViewDataSource : NSObject, UITableViewDataSource {
var pops: [ObjectTypeHere]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pops.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! PopTableViewCell
cell.account.text = pops[indexPath.row].answer
return cell
}
}
From there, just update the tableviews to pull from these objects
override func viewDidLoad() {
super.viewDidLoad()
self.table1.dataSource = FirstTableViewDataSource()
self.table2.dataSource = SecondTableViewDataSource()
}
The compiler is analyzing what will happen if tableView is neither table1 nor table2. If that should happen, the function will exit with nothing to return.
That's an error.
Your cellForRowAt method should always return a cell, so
Try this way
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == table1{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! acntTableViewCell
cell.account.text = account[indexPath.row].email
return cell
}
//if tableView is not table1 then
let cell2 = tableView.dequeueReusableCell(withIdentifier: "cell2")
as! popTableViewCell
cell2.pop.text = pop[indexPath.row].answer
return cell2
}
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var table1: UITableView!
#IBOutlet weak var table2: UITableView!
let firstClassRef = FirstTableView()
let secondClassRef = SecondTableView()
override func viewDidLoad() {
super.viewDidLoad()
firstClassRef.array1 = ["1","2","3"]
secondClassRef.array2 = ["1","2","3","1","2","3"]
self.table1.dataSource = firstClassRef
self.table2.dataSource = secondClassRef
self.table1.delegate = firstClassRef
self.table2.delegate = secondClassRef
self.table1.reloadData()
self.table2.reloadData()
}
}
class FirstTableView: NSObject, UITableViewDataSource, UITableViewDelegate {
var array1 = Array<Any>()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return array1.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath) as UITableViewCell
cell.textLabel?.text = array1[indexPath.row] as? String
cell.backgroundColor = UIColor.yellow
return cell
}
}
class SecondTableView: NSObject, UITableViewDataSource, UITableViewDelegate {
var array2 = Array<Any>()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return array2.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as UITableViewCell
cell.textLabel?.text = array2[indexPath.row] as? String
cell.backgroundColor = UIColor.yellow
return cell
}
}
Use Switch Statement
import UIKit
class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource {
#IBOutlet weak var topTableView: UITableView!
#IBOutlet weak var downTableview: UITableView!
var topData : [String] = []
var downData = [String]()
override func viewDidLoad() {
super.viewDidLoad()
topTableView.delegate = self
downTableview.delegate = self
topTableView.dataSource = self
downTableview.dataSource = self
for index in 0...20 {
topData.append("Top Table Row \(index)")
}
for index in 10...45 {
downData.append("Down Table Row \(index)")
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var numberOfRow = 1
switch tableView {
case topTableView:
numberOfRow = topData.count
case downTableview:
numberOfRow = downData.count
default:
print("Some things Wrong!!")
}
return numberOfRow
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
switch tableView {
case topTableView:
cell = tableView.dequeueReusableCell(withIdentifier: "topCell", for: indexPath)
cell.textLabel?.text = topData[indexPath.row]
cell.backgroundColor = UIColor.green
case downTableview:
cell = tableView.dequeueReusableCell(withIdentifier: "downCell", for: indexPath)
cell.textLabel?.text = downData[indexPath.row]
cell.backgroundColor = UIColor.yellow
default:
print("Some things Wrong!!")
}
return cell
}
}
Im really new to Swift, the question is how can I represent values from array in label.
I want a TableView with cells dynamically represent values from array into the labels which will be created in tableView rows.
import UIKit
import Foundation
class TableViewMarketItemsViewCell: UITableViewController {
var fruits = ["Avocado", "Apricot", "Pomegranate", "Quince"]
var PriceArray = ["1000 тг.","4000 тг.","3000 тг.","2000 тг."]
var categoryArray = ["Green category","Maroon category","Red category","Yellow category"]
// MARK: - UITableViewDataSource
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) as! TableViewCell
let fruitName = fruits[indexPath.row]
cell.productTitle.text = fruitName
cell.productImage.image = UIImage(named: fruitName)
return cell
}
}
Thnx in advance
import UIKit
import Foundation
class TableViewMarketItemsViewCell: UITableViewController {
var fruits = ["Avocado", "Apricot", "Pomegranate", "Quince"]
var PriceArray = ["1000 тг.","4000 тг.","3000 тг.","2000 тг."]
var categoryArray = ["Green category","Maroon category","Red category","Yellow category"]
// MARK: - UITableViewDataSource
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return fruits.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) as! TableViewCell
let fruitName = fruits[indexPath.row]
cell.productTitle.text = fruitName
cell.productImage.image = UIImage(named: fruitName)
cell.productPrice.text = PriceArray[indexPath.row]
cell.productsubTitle.text = categoryArray[indexPath.row]
return cell
}
}
This helped me.
result in picture below:
img
For inserting data into UITableViewcell use below code:
import UIKit
class ViewController: UIViewController,UITableViewDataSource {
#IBOutlet var tableView: UITableView!
var dataArray:NSArray!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.dataSource = self
dataArray = NSArray(objects: "a","b","c")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = dataArray.object(at: indexPath.row) as? String
return cell
}
}
tableView is outlet of UItableView.
You can populate an UITableView from an array like below:
(assuming that your array has a list of string values):
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Creating the tableView cell
let tableViewCell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as! UITableViewCell
//Assigning values
tableViewCell.lblName?.text = array.object(at: indexPath.row) as? String
return tableViewCell
}
In this way you can show the value from your array to the label in your tableView.