When I run the app only numberOfRowsInSection() method is called. So i place the certain number of break point to the every method but I found that numberOfRowsInSection() is called 4-5 times rest of the method is not get called. Here is my code.
import UIKit
var arrSearch = [[String:Any]]()
class RecentSearchViewController: CustomNavigationViewController {
#IBOutlet var tblSearch: UITableView!
var searchBusVC:SearchBusViewController?
override func viewDidLoad() {
super.viewDidLoad()
if let arr = UserDefault["SearchTo"]{
arrSearch.append(arr as! [String:Any])
}
tblSearch.reloadData()
}
extension RecentSearchViewController: UITableViewDataSource , UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrSearch.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "RecentCell") as! RecentCell
cell.selectionStyle = .none
let dict = arrSearch[indexPath.row]
cell.lblFrom.text = (dict["From"] as! String)
cell.lblTo.text = (dict["To"] as! String)
let strDate = Utill.getStringFromDate("EEE MMM dd ,yyyy", date: (dict["fromdate"] as! Date))
cell.lblDate.text = strDate
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let searchvc = self.searchBusVC {
searchvc.setRecentSearch(dict: arrSearch[indexPath.row])
}
self.navigationController?.popViewController(animated: true)
}
}
class RecentCell: UITableViewCell {
#IBOutlet var lblFrom: UILabel!
#IBOutlet var lblTo: UILabel!
#IBOutlet var lblDate: UILabel!
}
I tried many times but it's not going to work for me. Even in console there is no error is shown. Is there any issue with the code?
If numberOfRowsInSection is called, but no other UITableViewDataSource methods are, that must mean that numberOfRowsInSection returns 0. And that must mean that arrSearch is empty. Also, this part of code
if let arr = UserDefault["SearchTo"] {
arrSearch.append(arr as! [String:Any])
}
Should be rewritten. Since you are casting the result of subscript, you can do that as a part of if let, which would also make it safer if the result isn't of [String:Any] type
if let arr = UserDefault["SearchTo"] as? [String:Any] {
arrSearch.append(arr)
}
In short, apparently UserDefault["SearchTo"] returns nil
Related
I have two custom TableViewCells. So first TableViewCell is like a recent list, it can become longer. but second cell is always stays at bottom. so i need to add UILabel that hold's secondTableViewCell. the result that i need.
import UIKit
class bagPage: UIViewController, UITableViewDelegate, UITableViewDataSource {
var itemsName: [String] = []
var itemsPhoto: [UIImage] = []
// these arrays will defined in other view controller
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row < itemsName.count{
return 165
}else{
return 50
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6 + itemsName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < itemsName.count{
let cell = tableView.dequeueReusableCell(withIdentifier: "bagTableViewCell") as? bagTableViewCell
cell?.itemName.text = itemsName.last
cell?.itemPhoto.image = itemsPhoto.last
return cell!
}
if indexPath.row == itemsName.count {
let cellTwo = tableView.dequeueReusableCell(withIdentifier: "extraBagPageTableView") as? extraBagPageTableView
// here i'm hiding views in first row
cellTwo?.textLabel?.text = "These are products that u can add to your cell"
return cellTwo!
}else{
let cellTwo = tableView.dequeueReusableCell(withIdentifier: "extraBagPageTableView") as? extraBagPageTableView
return cellTwo!
}
}
}
This is another attempt at providing a solution. Is this what you are looking for?
Here is a link to the project
https://drive.google.com/file/d/1XlSF4fGiNzOqQHauiNo7TuFhKUTrFbsJ/view?usp=sharing
Let me know if you need more help
Good evening, so I followed your image and made the code follow your convention of 1 tableview section, 2 difference cells. I tried to use your naming convention. Note I had to swap around the height values, you had them wrong way round.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var itemsName: [String] = ["Helmet", "Gloves", "Bindings", "Goggles", "Kneepads", "Boots", "Snowboard"]
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1 + itemsName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < itemsName.count{
let bagTableViewCell = tableView.dequeueReusableCell(withIdentifier: "BagTableViewCell") as? BagTableViewCell
bagTableViewCell?.productsLabel.text = itemsName[indexPath.row]
return bagTableViewCell!
} else {
let extraBagPageTableView = tableView.dequeueReusableCell(withIdentifier: "ExtraBagPageTableView") as? ExtraBagPageTableView
return extraBagPageTableView!
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row < itemsName.count {
return 50
} else {
return 165
}
}
}
And the tableview cells. Please note the second cell has a bad name.
class BagTableViewCell: UITableViewCell {
#IBOutlet weak var additionalProductsLabel: UILabel!
#IBOutlet weak var productsLabel: UILabel!
#IBOutlet weak var productImage: UIImageView!
}
class ExtraBagPageTableView: UITableViewCell {
}
And altogether it looks like this
And the project can be found here. (I set the permissions correctly this time :) )
TableCellWithLabel Project
I'm making an alarm function similar to the iPhone alarm app.
When setting the alarm day, I am writing code to check the day of the week.
class DaySelectCell: UITableViewCell {
#IBOutlet weak var dayLbl: UILabel!
#IBOutlet weak var checkView: Checkbox!
}
import UIKit
class DaySelectViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
let days = ["일요일마다","월요일마다","화요일마다","수요일마다","목요일마다","금요일마다","토요일마다"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
}
extension DaySelectViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return days.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DaySelectCell") as! DaySelectCell
cell.dayLbl.text = days[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "DaySelectCell") as! DaySelectCell
}
}
The part I want to ask is didSelectRowAt
I want to make a checkView.isSelectd of that cell to be true when I click on a certain day cell.
You have to manage datasource to hold the selected value, So you can pretend which index is selected.
var selectedDays: [Int] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.accessoryType = selectedDays.contains(indexPath.row) ? .checkmark : .none
}
Now in didSelectRowAt method write this code
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let index = selectedDays.firstIndex(where: { $0 == indexPath.row }) {
selectedDays.remove(at: index)
} else {
selectedDays.append(indexPath.row)
}
tableView.reloadData()
}
I'm using an array of instances of the same struct to populate a tableview and I'm stumped by the last item in the array displaying in every cell.
class RoutesViewController: UIViewController, UITableViewDataSource {
#IBOutlet weak var routesTableView: UITableView!
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return type1UnownedRoutesArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let routeCell = routesTableView.dequeueReusableCell(withIdentifier: "routeCell") as! RouteTableViewCell
for Flight in type1UnownedRoutesArray {
routeCell.originLabel.text = "Origin: \(Flight.origin)"
routeCell.destinationLabel.text = "Destination: \(Flight.destination)"
routeCell.priceLabel.text = "Price: $\(Flight.popularity)"
}
return routeCell
}
And the struct itself:
struct Flight {
var origin: String
var destination: String
var mileage: Int
var popularity: Int
var isOwned: Bool
}
If I add [indexPath.row] after for Flight in type1UnownedRoutesArray I get Type Flight does not conform to protocol Sequence
Thanks in advance for the help.
The source of your issue is this one in your cellForRow method, you are cycling over all your flights objects in your array, and of course the last value is keeping in your cell, so you need replace this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let routeCell = routesTableView.dequeueReusableCell(withIdentifier: "routeCell") as! RouteTableViewCell
for Flight in type1UnownedRoutesArray {
routeCell.originLabel.text = "Origin: \(Flight.origin)"
routeCell.destinationLabel.text = "Destination: \(Flight.destination)"
routeCell.priceLabel.text = "Price: $\(Flight.popularity)"
}
return routeCell
}
By this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let routeCell = routesTableView.dequeueReusableCell(withIdentifier: "routeCell") as! RouteTableViewCell
let flight = type1UnownedRoutesArray[indexPath.row]
routeCell.originLabel.text = "Origin: \(flight.origin)"
routeCell.destinationLabel.text = "Destination: \(flight.destination)"
routeCell.priceLabel.text = "Price: $\(flight.popularity)"
}
Hope this helps
The problem is you should not be iterating your flights array inside the cellforrow method as it is called once per item in your array.
try this instead
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let routeCell = routesTableView.dequeueReusableCell(withIdentifier: "routeCell") as! RouteTableViewCell
let flight = type1UnownedRoutesArray[indexPath.row]
routeCell.originLabel.text = "Origin: \(flight.origin)"
routeCell.destinationLabel.text = "Destination: \(flight.destination)"
routeCell.priceLabel.text = "Price: $\(flight.popularity)"
return routeCell
}
I'm trying to get different label text when UITabelViewCell is pressed but I can't get it working. The default value of completed is false, when touched it should be true and then label should be changed. Inside the didSelectRowAt the completed value is different so it's good but I can't pass it to cellForRowAt.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var listItems : [ListItem] = []
#IBOutlet weak var plusButton: UIButton!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
//...
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listItems.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var item = listItems[indexPath.row]
item.completed = !item.completed // changing from true to false and rom false to true
tableView.reloadData()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? CellData{
let item = listItems[indexPath.row]
cell.nameLabel.text = item.name
cell.userLabel.text = item.addedBy
if(item.completed == true){ //didSelectRowAt doesn't affect this item.completed
cell.doneLabel.text = "done"
} else {
cell.doneLabel.text = "not"
}
return cell
} else{
return CellData()
}
}
}
ListItem.swift:
struct ListItem{
var name : String!
var addedBy : String!
var completed : Bool!
init(name: String, addedBy: String, completed: Bool){
self.name = name
self.addedBy = addedBy
self.completed = completed
}
}
Your ListItem is a struct when you update it, it doesn't updated on the list as struct is always copied.
I think you should do something like :
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
var item = listItems[indexPath.row]
item.completed = !item.completed //
listItems[indexPath.row] = item
tableView.reloadData()
}
Even though i looked at other threads containing the same question, i have no clue what so ever, why it says this.
My code looks like this:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, HomeModelProtocal {
#IBOutlet weak var listTableView: UITableView!
var feedItems: NSArray = NSArray()
var selectedLocation : Parsexml = Parsexml()
override func viewDidLoad() {
super.viewDidLoad()
//set delegates and initialize homeModel
self.listTableView.delegate = self
self.listTableView.dataSource = self
let homeModel = HomeModel()
homeModel.delegate = self
homeModel.downloadItems()
func itemsDownloaded(items: NSArray) {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of feed items
return feedItems.count
}
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cellIdentifier: String = "BasicCell"
let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
let item: Parsexml = feedItems[indexPath.row] as! Parsexml
myCell.textLabel!.text = item.title
return myCell
}
I have tried to use the suggested code, but no luck.
In Swift 3
numberOfRowsInSection is:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
and cellForRowAt indexPath is:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
You can easily find out yourself: Comment out a whole method and retype the first letters tableV and see what code completion suggests.
Even in Swift 2 the signature of cellForRowAtIndexPath is wrong. All parameters are non-optional values.