Interface:
Interface in debugger:
Here is configuration of tableview
private func configureTableView(){
view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
// tableView.rowHeight = UITableView.automaticDimension
tableView.register(DishCell.self, forCellReuseIdentifier: "dishCell")
// tableView.sectionHeaderHeight = UITableView.automaticDimension
}
Here is tableView extensions
extension MenuViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.section == 0 {
return 380
}
return 48
}
func tableView(_ tableView: UITableView, estimatedHeightForHeaderInSection section: Int) -> CGFloat {
return 122
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
}
extension MenuViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return viewModel.dishes.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.dishes[section].count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let dishType = viewModel.dishTypes[section]
if section == 0 {
let restaurant = viewModel.restaurant
return FirstMenuHeader(restaurant: restaurant, dishType: dishType)
}else{
return DefaultMenuHeader(dishType: dishType)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "dishCell") as! DishCell
let dish = viewModel.dishes[indexPath.section][indexPath.row]
cell.set(dish: dish)
return cell
}
}
Just to clarify DishCell, FirstMenuHeader and DefaultMenuHeader look well if you put them outside of UITableview. And they have constraints that define their height. However their height is dynamic and depends on amount of line of text.
Problem was in dishCell.I made constraints with view, while I had to make constraints with contentView.
I have rewrote my constraints and problem was resolved.
Related
I am creating a static tableView. My goal is to have a single view that displays a tableView with 3 rows (get support, send feedback, participation terms), and a header + footer.
Right now, it all works fine EXCEPT the fact that there are two extra separators (one between the header and the first cell and the other between the last cell and the footer) that I cannot seem to get rid of.
Here is my code:
final class viewController: UITableViewController {
private let headerContainer = UIView()
private let footerContainer = UIView()
private let tableData = ["Get Support", "Send Feedback", "Participation Terms"]
override func viewDidLoad() {
super.viewDidLoad()
setupHeaderAndFooter()
setupTableView()
}
func setupHeaderAndFooter() {
/* setup code here (not relevant to this question) */
func setupTableView() {
// reinitializing tableView so that we can change its style to grouped
tableView = UITableView(frame: CGRect.zero, style: .grouped)
tableView.delegate = self
tableView.separatorStyle = .singleLine
}
//MARK: UITableView Methods
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
return headerContainer
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 150
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
return footerContainer
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 200
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 70
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell")
cell.textLabel!.text = tableData[indexPath.row]
return cell
}
}
One way to achieve this is don't use default separator provided by UITableView. and place one UILabel or UIView and set its background color to light gray and set its height=1 (As per your requirement), width (full tableview width or as per your requirement) and position at bottom of all you content inside cell, header or footer.
Ok here you go.
The easy trick is actually a one-liner and a self-explanatory:
self.tableView.separatorColor = self.tableView.backgroundColor
AFTER:
I hope this helps!
You have to set clipsToBounds to true on your header view.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = //Get your header here
header.clipsToBounds = true
return header
}
Before:
After:
I am working on an app in which I need to show multiple rows with a header. In my case only one section is showing. I have searched everything but can't find a suitable solution.
Here is my code:
class Timeline: UITableViewCell {
#IBOutlet weak var timelineData: UITextView!
}
class StudenTimelineViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
let section = ["pizza", "deep dish pizza", "calzone"]
let items = [["Margarita", "BBQ Chicken", "Peproni"], ["sausage", "meat lovers", "veggie lovers"], ["sausage", "chicken pesto", "prawns & mashrooms"]]
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items[section].count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return section.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.section[section]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TimelineId", for: indexPath) as! Timeline
let gpsData = items[indexPath.section][indexPath.row]
cell.timelineData.text = gpsData
return cell
}
func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 40
}
What I am getting
How will I get all the sections. Thanks in advance.
This is because your method name func numberOfSectionsInTableView(tableView: UITableView) -> Int is incorrect and hence not called.
Replace the name with func numberOfSections(in tableView: UITableView) -> Int and see the magic happen.
//MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewCell", for: indexPath)
cell.selectionStyle = UITableViewCellSelectionStyle.none
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let cell: UITableViewCell
cell = tableView.dequeueReusableCell(withIdentifier: "tableviewHeader")!
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.backgroundColor = UIColor.white
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 32;
}
I not find what is my problem.
I need to give space between one cell and another.
I wrote self.tableView Storyline.delegate = self because I read that this could be the problem, but not know if it is correct.
This is my code:
class ClassName: UIViewController, UITableViewDataSource, UITabBarControllerDelegate, UITableViewDelegate {
public var notifications: [APINotification] = []
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.delegate = self
tableViewStoryline.rowHeight = UITableViewAutomaticDimension
tableViewStoryline.estimatedRowHeight = 140
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(_ animated: Bool) {
self.notifications = []
self.getLastNotifications()
APIAuth.shared.count_badge = 0
self.tabBarController?.tabBar.items![0].badgeValue = nil
}
public func getLastNotifications() {
let req = Notification()
req.getLastNotifications(onComplete: {events in
self.notifications = events
DispatchQueue.main.async(execute: {
self.tableViewStoryline.delegate = self
self.tableViewStoryline.dataSource = self
self.tableViewStoryline.sectionHeaderHeight = 10
self.tableViewStoryline.reloadData()
})
})
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
// There is just one row in every section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if self.notifications.count > 4 {
return 4
} else {
return self.notifications.count
}
}
// Set the spacing between sections
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell = tableView.dequeueReusableCell(withIdentifier: "controller")! as UITableViewCell
titleLbl.text = notifications[indexPath.row].title
bodyLbl.text = notifications[indexPath.row].description
typeLbl.text = notifications[indexPath.row].type
return cell!
}
}
Does anyone have any idea what the problem is?
Is there some code missing?
Thanks!
I think this is what you want:
func numberOfSections(in tableView: UITableView) -> Int {
if self.notifications.count > 4 {
return 4
} else {
return self.notifications.count
}
}
// There is just one row in every section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
Then you have to change also cellForRowAt to take this into account.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell = tableView.dequeueReusableCell(withIdentifier: "controller")! as UITableViewCell
titleLbl.text = notifications[indexPath.section].title
bodyLbl.text = notifications[indexPath.section].description
typeLbl.text = notifications[indexPath.section].type
return cell!
}
Instead of having one section with notifications.count rows, you want notifications.count sections and each section with one row. Now setting 10 points as height for section header will make cells appear as having spaces between them.
There are some other options that you can consider, see my other answer.
you are using wrong delegate function.
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
is used for the hieght of header not for height of cell.
use func tableView(UITableView, heightForRowAt: IndexPath)
you will get correct sized cells.
Hope this helps!
My structure is the following:
UIViewController -> UIVIew -> UITableView
tableView(_ tableView: UITableView, numberOfRowsInSection section: Int)
and
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
is called but
tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
is not called.
class ViewcontrollerA : UIViewController , UITableViewDelegate , UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
self.doctortableView.delegate = self
self.doctortableView.dataSource = self
self.doctortableView.allowsSelection = true
}
func callTable() {
doctortableView.frame = CGRect(......)
view1.addSubview(doctortableView)
doctortableView.isUserInteractionEnabled = true
self.view.addSubview(view1)
}
// Tableview Functions
// Number of Sections in Table
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count = Int()
return count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = UITableViewCell()
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//This function is not called
}
}
The problem seems to be in this datasource method at first glance.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count = Int()
return count
}
Doesn't Int() return 0? That means your tableview doesn't have any cells.
As per discussion on Chat
You are creating TableView programatically and add to self.view
func callTable() {
doctortableView.frame = CGRect(......)
view1.addSubview(doctortableView)
doctortableView.isUserInteractionEnabled = true
self.view.addSubview(view1)
}
but your tableView is not on top, so you are not able to scroll it and that's why delegate are not working
following line is missing
self.view.bringSubview(toFront: doctortableView)
Here is Full code
func callTable() {
doctortableView.frame = CGRect(......)
view1.addSubview(doctortableView)
doctortableView.isUserInteractionEnabled = true
self.view.addSubview(view1)
self.view.bringSubview(toFront: doctortableView)
}
i am trying to resort UITableView cell's by long press then drag and drop the cell , its not working when i use Custom cell view any idea why !
Here is the TableView viewcontroller :
override func viewDidLoad()
{
super.viewDidLoad()
// Then delegate the TableView
self.tableView.delegate = self
self.tableView.dataSource = self
// Register table cell class from nib
let bundle = Bundle(for: type(of: self))
let cellNib = UINib(nibName: "tbc_song_vertical", bundle: bundle)
self.tableView.register(cellNib, forCellReuseIdentifier: "tbc_song_vertical")
//Loading Template
let nib_tbc_loading = UINib(nibName: "tbc_loading", bundle: bundle)
self.tableView.register(nib_tbc_loading, forHeaderFooterViewReuseIdentifier: "tbc_loading")
//Automated ell height
self.tableView.estimatedRowHeight = 44.0
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.reloadData()
self.tableView.isEditing = true
}
// MARK: - Sorting
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
return .none
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let movedObject = self.data[sourceIndexPath.row]
data.remove(at: sourceIndexPath.row)
data.insert(movedObject, at: destinationIndexPath.row)
// To check for correctness enable: self.tableView.reloadData()
}
//loading footer
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let footerView = self.tableView.dequeueReusableHeaderFooterView(withIdentifier: "tbc_loading") as! tbc_loading
footerView.startAnimate()
return footerView
}
//loading footer
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return ( self.is_fetching ) ? 40 : 0
}
//Pagination
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
//Bottom Refresh
if scrollView == tableView{
if ((scrollView.contentOffset.y + scrollView.frame.size.height) >= scrollView.contentSize.height )
{
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell : tbc_song_vertical = tableView.dequeueReusableCell(withIdentifier: "tbc_song_vertical", for: indexPath) as! tbc_song_vertical
cell.fillwithInfo(dto: self.data[indexPath.row] )
return cell
}
// Tabbed Cell
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { }
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
}
only if i use custom view its not working , but when i hold my finger on the right side of any cell to drag it up or down its dragging all the table
Add the following method
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}