Add photo to a section in UITableview - uitableview

Is there a way to add a photo in a section instead of adding the textviews?
for example bat-and-ball that only has one photo instead of all those textviews?
and in the other sections have the textviews?
?

I think you need something like this:
//
// ViewController.swift
// Test
//
// Created by Dennis Mostajo on 9/29/20.
//
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var table: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// MARK: - UITableView
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat
{
var height:CGFloat = 0
if tableView == self.table
{
height = 25
}
return height
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
var height:CGFloat = 0
if tableView == self.table
{
height = 50
}
return height
}
func numberOfSections(in tableView: UITableView) -> Int {
var sections:Int = 0
if tableView == self.table
{
sections = 4
}
return sections
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
var rows:Int = 0
if tableView == self.table
{
switch section
{
case 0:
rows = 3
break
case 1:
rows = 3
break
case 2:
rows = 2
break
case 3:
rows = 3
break
default:
break
}
}
return rows
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 25))
headerView.backgroundColor = .black
if tableView == self.table
{
switch section
{
case 0: // for image only
let imageView = UIImageView.init(frame: headerView.frame)
imageView.image = UIImage(named:"flagBolivia.png")
imageView.contentMode = .scaleToFill
headerView.addSubview(imageView)
break
case 1: // for image and text
let imageView = UIImageView.init(frame: headerView.frame)
imageView.image = UIImage(named:"flagBolivia2.jpg")
imageView.contentMode = .scaleToFill
headerView.addSubview(imageView)
let label = UILabel.init(frame: headerView.frame)
label.text = "Main Cities"
label.textColor = .white
label.font = UIFont.boldSystemFont(ofSize: 16.0)
label.backgroundColor = .clear
headerView.addSubview(label)
break
case 2: // for text only
let label = UILabel.init(frame: headerView.frame)
label.text = "Showing images only"
label.textColor = .white
label.backgroundColor = .black
headerView.addSubview(label)
break
case 3: // for text only
let label = UILabel.init(frame: headerView.frame)
label.text = "Bolivian Food"
label.textColor = .white
label.backgroundColor = .black
headerView.addSubview(label)
break
default:
break
}
}
return headerView
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "cell")
if tableView == self.table
{
switch indexPath.section
{
case 0:
switch indexPath.row
{
case 0:
cell.textLabel?.text = "CODING"
break
case 1:
cell.textLabel?.text = "FROM"
break
case 2:
cell.textLabel?.text = "BOLIVIA"
break
default:
break
}
break
case 1:
switch indexPath.row
{
case 0:
cell.textLabel?.text = "La Paz"
break
case 1:
cell.textLabel?.text = "Cochabamba"
break
case 2:
cell.textLabel?.text = "Santa Cruz"
break
default:
break
}
break
case 2:
switch indexPath.row
{
case 0: // for image only
let imageView = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
imageView.image = UIImage(named:"flagBolivia.png")
imageView.contentMode = .scaleToFill
cell.contentView.addSubview(imageView)
break
case 1:
let imageView = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: 50))
imageView.image = UIImage(named:"flagBolivia2.jpg")
imageView.contentMode = .scaleToFill
cell.contentView.addSubview(imageView)
let label = UILabel.init(frame: cell.frame)
label.text = "Custom Cell"
label.textColor = .white
label.font = UIFont.boldSystemFont(ofSize: 16.0)
label.backgroundColor = .clear
cell.contentView.addSubview(label)
break
default:
break
}
break
case 3:
switch indexPath.row
{
case 0:
cell.textLabel?.text = "Fricasé"
break
case 1:
cell.textLabel?.text = "Silpancho"
break
case 2:
cell.textLabel?.text = "Majadíto"
break
default:
break
}
break
default:
break
}
}
return cell
}
}

Related

How can I make section header like Android sticky view?

I am using the section header of the tableview.
https://www.youtube.com/watch?v=U3gqR4dRiT8
If you look at it, almost at the end
When the section header goes up, the existing top section header goes up and collides and disappears.
And the text in the top section header is changed and floats
But when I run the sample, the text changes.
It doesn't seem to have the effect of pushing up the section header.
What should I do?
import UIKit
class MyTableviewControllerTableViewController: UITableViewController {
private let numberOfSections = 3
var meat = ["Beef","Turkey","Fish", "Lamb", "Chicken", "Pork", "Beef","Turkey","Fish", "Lamb", "Chicken", "Pork"]
var fruit = ["Apple","Banana","Cherry","Apple","Banana","Cherry","Apple","Banana","Cherry"]
var vegetable = ["Lettuce","Broccoli","Cauliflower","Lettuce","Broccoli","Cauliflower","Lettuce","Broccoli","Cauliflower"]
override func viewDidLoad() {
super.viewDidLoad()
// make the header sticky
self.automaticallyAdjustsScrollViewInsets = false
}
// MARK: - Table view data source
// return the number of sections
override func numberOfSections(in tableView: UITableView) -> Int {
return numberOfSections
}
// return the number of rows in the specified section
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var rowCount = 0
switch (section) {
case 0:
rowCount = meat.count
case 1:
rowCount = fruit.count
case 2:
rowCount = vegetable.count
default:
rowCount = 0
}
return rowCount
}
// Content Cell
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath)
switch (indexPath.section) {
case 0:
cell.textLabel?.text = meat[indexPath.row]
case 1:
cell.textLabel?.text = fruit[indexPath.row]
case 2:
cell.textLabel?.text = vegetable[indexPath.row]
default:
cell.textLabel?.text = "Other"
}
return cell
}
// Header Cell
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCell(withIdentifier: "HeaderCell") as! CustomTableViewHeaderCell
headerCell.backgroundColor = UIColor.gray
switch (section) {
case 0:
headerCell.headerLabel.text = "Meat";
case 1:
headerCell.headerLabel.text = "Fruit";
case 2:
headerCell.headerLabel.text = "Vegetable";
default:
headerCell.headerLabel.text = "Other";
}
return headerCell
}
// Footer Cell
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
let rect = CGRect(origin: CGPoint(x: 0,y :0), size: CGSize(width: tableView.frame.size.width, height: 20))
let footerView = UIView(frame: rect)
footerView.backgroundColor = UIColor.darkGray
return footerView
}
// footer height
override func tableView(_ : UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 20.0
}
You can do it programmatically, and the result is perfect... Declare your table view and carry under your UIViewController (Attention, it's No UITableViewController) class:
class YourControllerClass: UIViewController {
let tableView = UITableView()
let cellId = "cellId"
let headerId = "headerId"
var meat = ["Beef","Turkey","Fish", "Lamb", "Chicken", "Pork", "Beef","Turkey","Fish", "Lamb", "Chicken", "Pork"]
var fruit = ["Apple","Banana","Cherry","Apple","Banana","Cherry","Apple","Banana","Cherry"]
var vegetable = ["Lettuce","Broccoli","Cauliflower","Lettuce","Broccoli","Cauliflower","Lettuce","Broccoli","Cauliflower"]
now in viewDidLoad configure nav bar and set tableview attributes and constraints:
override func viewDidLoad() {
super.viewDidLoad()
configureNavigationBar(largeTitleColor: .yourPreferColor, backgoundColor: .ultraDark, tintColor: .fuxiaRed, title: "My Title", preferredLargeTitle: true) // I use my function to configure navBar
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
tableView.register(HeaderCell.self, forCellReuseIdentifier: headerId)
tableView.backgroundColor = .yourPreferColor
tableView.delegate = self
tableView.dataSource = self
tableView.separatorColor = UIColor(white: 1, alpha: 0.2)
tableView.tableFooterView = UIView()
tableView.translatesAutoresizingMaskIntoConstraints = false
if #available(iOS 11.0, *) {
tableView.contentInsetAdjustmentBehavior = .never
} else {
automaticallyAdjustsScrollViewInsets = false
}
if #available(iOS 15.0, *) {
tableView.sectionHeaderTopPadding = 0
tableView.sectionFooterHeight = 0
} else {
UITableView.appearance().sectionHeaderTopPadding = CGFloat(0)
UITableView.appearance().sectionFooterHeight = CGFloat(0)
}
view.addSubview(tableView)
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}
Now create an extension for tableView delegate and datasource:
extension NavBarAppearenceController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 3
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50 // header height
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView()
let headerCell = tableView.dequeueReusableCell(withIdentifier: headerId) as! HeaderCell // header cell
headerCell.translatesAutoresizingMaskIntoConstraints = false
headerView.addSubview(headerCell)
headerCell.topAnchor.constraint(equalTo: headerView.topAnchor).isActive = true
headerCell.leadingAnchor.constraint(equalTo: headerView.leadingAnchor).isActive = true
headerCell.trailingAnchor.constraint(equalTo: headerView.trailingAnchor).isActive = true
headerCell.bottomAnchor.constraint(equalTo: headerView.bottomAnchor).isActive = true
switch section {
case 0:
headerCell.label.text = "Meat"
case 1:
headerCell.label.text = "Fruit"
default:
headerCell.label.text = "Vegetables"
}
return headerView
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return meat.count
case 1:
return fruit.count
case 2:
return vegetable.count
default:
return 0
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let mySection = indexPath.section
switch mySection {
case 0:
cell.textLabel?.text = "\(meat[indexPath.row])"
case 1:
cell.textLabel?.text = "\(fruit[indexPath.row])"
default:
cell.textLabel?.text = "\(vegetable[indexPath.row])"
}
cell.contentView.backgroundColor = .yourPreferColor
cell.textLabel?.textColor = .white
cell.selectionStyle = .none
return cell
}
}
Create your custom header cell:
class HeaderCell: UITableViewCell {
let myView: UIView = {
let v = UIView()
v.backgroundColor = .yourPreferColor
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
let label = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.backgroundColor = .yourPreferColor
label.textColor = .white
label.font = .systemFont(ofSize: 20, weight: .bold)
label.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(myView)
myView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
myView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 20).isActive = true
myView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
myView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
myView.addSubview(label)
label.topAnchor.constraint(equalTo: myView.topAnchor).isActive = true
label.leadingAnchor.constraint(equalTo: myView.leadingAnchor).isActive = true
label.trailingAnchor.constraint(equalTo: myView.trailingAnchor).isActive = true
label.bottomAnchor.constraint(equalTo: myView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
This is the result:
BONUS
This is my navBar configuration func:
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
if #available(iOS 13.0, *) {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.backgroundColor = backgoundColor
navigationController?.navigationBar.standardAppearance = navBarAppearance
navigationController?.navigationBar.compactAppearance = navBarAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.tintColor = tintColor
navigationItem.title = title
} else {
// Fallback on earlier versions
navigationController?.navigationBar.barTintColor = backgoundColor
navigationController?.navigationBar.tintColor = tintColor
navigationController?.navigationBar.isTranslucent = false
navigationItem.title = title
}
}

Cannot find 'selectedIndexPaths' in scope

My Viewcontroller shows "Cannot find 'selectedIndexPaths' in scope" and other errors
My viewcontroller with errors:- import UIKit
class ProductViewController: UIViewController, UITableViewDataSource,
UITableViewDelegate {
let notificationButton = SSBadgeButton()
let rightbarbuttonimage = UIImage(named:"ic_cart")
fileprivate var cart = Cart()
let scrollView = UIScrollView()
let sections = ["Section A", "Section B","Section C", "Section D","Section E","Section F","Section G","Section H", "Section I","Section J","Section K","Section L"]
let rowspersection = [2,3,1,2,2,3,3,1,4,2,1,2]
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
self.tableView.backgroundColor = UIColor.gray
//Add and setup scroll view
self.tableView.addSubview(self.scrollView)
self.scrollView.translatesAutoresizingMaskIntoConstraints = false;
//Constrain scroll view
self.scrollView.leadingAnchor.constraint(equalTo: self.tableView.leadingAnchor, constant: 20).isActive = true;
self.scrollView.topAnchor.constraint(equalTo: self.tableView.topAnchor, constant: 20).isActive = true;
self.scrollView.trailingAnchor.constraint(equalTo: self.tableView.trailingAnchor, constant: -20).isActive = true;
self.scrollView.bottomAnchor.constraint(equalTo: self.tableView.bottomAnchor, constant: -20).isActive = true;
// customising rightBarButtonItems as notificationbutton
notificationButton.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
notificationButton.setImage(UIImage(named: "ic_cart")?.withRenderingMode(.alwaysTemplate), for: .normal)
notificationButton.badgeEdgeInsets = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 15)
self.navigationItem.rightBarButtonItem = UIBarButtonItem(customView: notificationButton)
//following register is needed because I have rightbarbuttonitem customised as uibutton i.e. notificationbutton
notificationButton.addTarget(self, action: #selector(self.registerTapped(_:)), for: .touchUpInside)
}
#objc func registerTapped(_ sender: UIButton) {
self.performSegue(withIdentifier: "showCart", sender: nil)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Workaround to avoid the fadout the right bar button item
self.navigationItem.rightBarButtonItem?.isEnabled = false
self.navigationItem.rightBarButtonItem?.isEnabled = true
//Update cart if some items quantity is equal to 0 and reload the product table and right button bar item
cart.updateCart()
//self.navigationItem.rightBarButtonItem?.title = "Checkout (\(cart.items.count))"
notificationButton.badge = String(cart.items.count)// making badge equal to no.ofitems in cart
tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// this segue to transfer data
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showCart" {
if let cartViewController = segue.destination as? CartViewController {
cartViewController.cart = self.cart
}
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return productMap.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productMap[section]?.count ?? 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let product = productMap[indexPath.section]![indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductTableViewCell") as! ProductTableViewCell
cell.imageView?.image = product.imagename
cell.delegate = self as CartDelegate
cell.setButton(state: self.cart.contains(product: product))
return cell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 44
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch(section) {
case 0: return "Section A"
case 1: return "Section B"
case 2: return "Section C"
case 3: return "Section D"
case 4: return "Section E"
case 5: return "Section F"
case 6: return "Section G"
case 7: return "Section H"
case 8: return "Section I"
case 9: return "Section J"
case 10: return "Section K"
case 11: return "Section L"
default: return ""
}
}
}
extension ProductViewController: CartDelegate {
// MARK: - CartDelegate
func updateCart(cell: ProductTableViewCell) {
guard let indexPath = tableView.indexPath(for: cell) else { return }
let product = productMap[indexPath.section]![indexPath.row]
/// `var selectedIndexPaths = [IndexPath]()` defined inside `ProductViewController`, to keep track of the selected products// **error -Cannot find 'selectedIndexPaths' in scope**
if selectedIndexPaths.contains(indexPath) {**//error -Cannot find 'selectedIndexPaths' in scope**
if let index = selectedIndexPaths.firstIndex(of: indexPath) {
selectedIndexPaths.remove(at: index)**//error -Cannot find 'selectedIndexPaths' in scope**
removeProductFromCart(indexPath: indexPath)
}
} else {
selectedIndexPaths.append(indexPath)
addProductToCart(indexPath: indexPath)
}
// addProductToCart(indexPath: indexPath)
/// **I commented this out because I don't have the code for `Cart`**
//Update Cart with product
// cart.updateCart(with: product)
// self.navigationItem.rightBarButtonItem?.title = "Checkout (\(cart.items.count))"
// notificationButton.badge = String(cart.items.count) // making badge equal to noofitems in cart
}
}
func addProductToCart(indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? ProductTableViewCell {
if let imageView = cell.imagename {
let initialImageViewFrame = imageView.convert(imageView.frame, to: self.view)
let targetImageViewFrame = self.notificationButton.frame
let imgViewTemp = UIImageView(frame: initialImageViewFrame)
imgViewTemp.clipsToBounds = true
imgViewTemp.contentMode = .scaleAspectFill
imgViewTemp.image = imageView.image
self.view.addSubview(imgViewTemp)
UIView.animate(withDuration: 1.0, animations: {
imgViewTemp.transform = CGAffineTransform(scaleX: 1.5, y: 1.5)
}) { _ in
UIView.animate(withDuration: 0.5, animations: {
imgViewTemp.transform = CGAffineTransform(scaleX: 0.2, y: 0.2).rotated(by: CGFloat(Double.pi))
imgViewTemp.frame = targetImageViewFrame
}) { _ in
imgViewTemp.removeFromSuperview()
UIView.animate(withDuration: 1.0, animations: {
self.notificationButton.transform = CGAffineTransform(scaleX: 1.4, y: 1.4)
}, completion: {_ in
self.notificationButton.transform = CGAffineTransform.identity
})
}
}
}
}
}
func removeProductFromCart(indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? ProductTableViewCell {
if let imageView = cell.imagename {
let initialImageViewFrame = self.notificationButton.frame
let targetImageViewFrame = imageView.convert(imageView.frame, to: self.view)
let imgViewTemp = UIImageView(frame: initialImageViewFrame)
imgViewTemp.clipsToBounds = true
imgViewTemp.contentMode = .scaleAspectFill
imgViewTemp.image = imageView.image
self.view.addSubview(imgViewTemp)
var initialTransform = CGAffineTransform.identity
initialTransform = initialTransform.scaledBy(x: 0.2, y: 0.2)
initialTransform = initialTransform.rotated(by: CGFloat(Double.pi))
UIView.animate(withDuration: 0.5, animations: {
self.notificationButton.animationZoom(scaleX: 1.4, y: 1.4)
imgViewTemp.transform = initialTransform
}) { _ in
UIView.animate(withDuration: 1, animations: {
self.notificationButton.animationZoom(scaleX: 1, y: 1)
imgViewTemp.transform = CGAffineTransform.identity
imgViewTemp.frame = targetImageViewFrame
}) { _ in
imgViewTemp.removeFromSuperview()
}
}
}
}
}
screenshot of the error-
I have tableview in my productviewcotroller as shown below. so, thats not an issusem still errors:-
There are other errors also which it is showing.
How to sort it out ?
var selectedIndexPaths = IndexPath
Please define selectedIndexPaths inside the main class not in the extension then check it again .

UITableView scroll freezes when scrolling fast

I am using custom tableview cells in a tableview. The data is loaded from the server and height calculation of that particular cell is done inside the cell only.
<iframe width="560" height="315" src="https://www.youtube.com/embed/h-FjYkSBuNM" frameborder="0" allowfullscreen></iframe>
I am attaching the code for tableview cell for row at indexpath, custom cell method and code for get request.
class QuesAnsFeedTableViewCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setup()
}
override func layoutSubviews() {
super.layoutSubviews()
self.questionLabel.preferredMaxLayoutWidth = questionLabel.frame.width
self.answerLabel.preferredMaxLayoutWidth = answerLabel.frame.width
super.layoutSubviews()
}
func setup(){
topLeftLabel = UILabel()
topLeftLabel.font = UIFont(name: regularFont, size: 12)
topLeftLabel.text = "Yesterday"
topLeftLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
topRightLabel = UILabel()
topRightLabel.font = UIFont(name: regularFont, size: 12)
topRightLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
topRightLabel.text = ""
topRightLabel.textAlignment = .right
questionLabel = UILabel()
questionLabel.font = UIFont(name: mediumFont, size: 14)
questionLabel.text = "First Ques Comes Here and ans will be below this question"
questionLabel.numberOfLines = 0
questionLabel.lineBreakMode = .byWordWrapping
userImageView = UIImageView()
userImageView.backgroundColor = .purple
userImageView.layer.cornerRadius = CGFloat(sidePadding)/2
userImageView.clipsToBounds = true
userNameLabel = UILabel()
userNameLabel.font = UIFont(name: regularFont, size: 12)
userNameLabel.text = ""
answerLabel = UILabel()
answerLabel.font = UIFont(name: regularFont, size: 14)
answerLabel.text = ""
answerLabel.numberOfLines = 0
answerLabel.lineBreakMode = .byWordWrapping
viewOtherAnswerLabel = UILabel()
viewOtherAnswerLabel.font = UIFont(name: mediumFont, size: 12)
viewOtherAnswerLabel.text = ""
viewOtherAnswerLabel.textAlignment = .center
viewOtherAnswerLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
writeAnswerLabel = UILabel()
writeAnswerLabel.font = UIFont(name: mediumFont, size: 14)
writeAnswerLabel.backgroundColor = CommonFunctions.hexStringToUIColor(hex: crispBlue)
writeAnswerLabel.text = "Write Answer"
writeAnswerLabel.textAlignment = .center
writeAnswerLabel.textColor = .white
tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tappedCell(sender:)))
tapGesture.numberOfTapsRequired = 1
self.addGestureRecognizer(tapGesture)
// self.addSubview(likeButton)
// self.addSubview(descriptionLabel)
}
func updateData(data:NSDictionary) -> CGFloat{
if let viewCount = data["vc"] {
topRightLabel.text = "\(viewCount) read"
}
if let ques = data["q"] as? String{
topLeftLabel.frame = CGRect(x:sidePadding/2, y: 2*sidePaddingForCollectionCells, width: screenWidth/2-sidePadding, height: Int(CommonFunctions.calculateHeight(inString: topLeftLabel.text!, forFont: topLeftLabel.font, andWidthOfLabel: CGFloat(screenWidth/2))))
topRightLabel.frame = CGRect(x: screenWidth/2, y: 2*sidePaddingForCollectionCells, width: screenWidth/2-sidePadding/2, height: Int(topLeftLabel.frame.height))
let newHeight = CommonFunctions.calculateHeight(inString: ques,forFont:questionLabel.font,andWidthOfLabel:questionLabel.frame.width)
questionLabel.frame = CGRect(x:sidePadding/2 ,y: Int(topLeftLabel.frame.maxY)+sidePaddingForCollectionCells,width: screenWidth - sidePadding, height: Int(ceil(Float(newHeight))))
questionLabel.text = ques
self.addSubview(topLeftLabel)
self.addSubview(topRightLabel)
self.addSubview(questionLabel)
// questionLabel.attributedText = CommonFunctions.justifiedText(string: ques)
}
if let user = data.object(forKey: "user") as? NSDictionary{
if let usrName = user.value(forKey: "name"){
userNameLabel.text = "\(usrName)"
}
if let imgLink = user["image"] as? String{
if let url = URL(string: imgLink){
userImageView.sd_setImage(with: url,placeholderImage:#imageLiteral(resourceName: "placeholderImage"))
}
}
}
if let otherAnswer = data.value(forKey: "cc") {
viewOtherAnswerLabel.text = "View Other Answer \(otherAnswer)"
}
if let ans = data.value(forKey: "comt") as? String{
answered = true
userImageView.frame = CGRect(x: sidePadding/2, y: Int(questionLabel.frame.maxY)+2*sidePaddingForCollectionCells, width: sidePadding, height: sidePadding)
userNameLabel.frame = CGRect(x: 3*sidePadding/2+2*sidePaddingForCollectionCells, y:Int(questionLabel.frame.maxY)+sidePaddingForCollectionCells, width: screenWidth-2*sidePadding, height: Int(topLeftLabel.frame.height))
let newHeight = CommonFunctions.calculateHeight(inString: ans,forFont:answerLabel.font,andWidthOfLabel:answerLabel.frame.width)
let frame = CGRect(x: 3*sidePadding/2+2*sidePaddingForCollectionCells, y:Int(userNameLabel.frame.maxY) + sidePaddingForCollectionCells, width: screenWidth-2*sidePadding-2*sidePaddingForCollectionCells, height: Int(ceil(Float(newHeight))))
answerLabel.frame = frame
answerLabel.text = ans
viewOtherAnswerLabel.frame = CGRect(x: 0, y: Int(answerLabel.frame.maxY)+2*sidePaddingForCollectionCells, width: screenWidth, height: 2*sidePadding/3)
self.addSubview(userImageView)
self.addSubview(userNameLabel)
self.addSubview(answerLabel)
self.addSubview(viewOtherAnswerLabel)
writeAnswerLabel.removeFromSuperview()
return viewOtherAnswerLabel.frame.maxY
}
else{
answered = false
writeAnswerLabel.frame = CGRect(x: 0, y:Int(questionLabel.frame.maxY) + 2*sidePaddingForCollectionCells, width: screenWidth, height: sidePadding)
self.addSubview(writeAnswerLabel)
userImageView.removeFromSuperview()
userNameLabel.removeFromSuperview()
answerLabel.removeFromSuperview()
viewOtherAnswerLabel.removeFromSuperview()
return writeAnswerLabel.frame.maxY
}
}
TableView Code
class GenericView: UIView ,UITableViewDelegate,UITableViewDataSource {
var tableView:UITableView!
var viewFrame = CGRect()
var parentView = ""
var discussViewHeight = [Int:CGFloat]()
var nextUrlPath = ""
var currentUrlPath = ""
private var sliderLabelsText = ["Favourites","Sign In"]
private var tableBlocks = [NSDictionary]()
override init(frame: CGRect) {
super.init(frame: frame)
viewFrame = frame
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if viewFrame != CGRect() {
setup()
}
}
public func updateView(){
viewFrame = self.frame
tableView.frame = (viewFrame)
getRequest()
}
func getRequest(){
currentUrlPath = baseUrl+nextUrlPath
if parentView == discussView{
// let url = baseUrl + nextUrlPath
Alamofire.request(currentUrlPath).responseJSON { response in
if let dict = response.result.value as? [String:AnyObject]{
if (dict["msc"]) as? String == "700", let blocks = dict["blocks"] as? NSArray{
self.nextUrlPath = (dict["next"] as? String ?? "")
for block in blocks{
if let blk = block as? NSDictionary{
if blk.value(forKey: "ty") as? String == "qa"{
self.tableBlocks.append(blk)
}
appDelegate.tableBlocks.append(blk)
}
}
DispatchQueue.main.async(execute: { () -> Void in
self.refreshControl.endRefreshing()
self.tableView.reloadData()
})
}
else{
DispatchQueue.main.async(execute: { () -> Void in
self.currentUrlPath = ""
self.getRequest()
})
}
}
}
return
}
}
func setup(){
backgroundColor = UIColor.white
tableView = UITableView(frame: viewFrame, style: .grouped)
tableView.delegate = self
tableView.dataSource = self
self.addSubview(tableView)
registerCells()
}
//MARK: TableView DataSource Methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if parentView == discussView{
return 1
}
return 0
}
func numberOfSections(in tableView: UITableView) -> Int {
if parentView == discussView{
return tableBlocks.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (parentView == discussView){
var cell:QuesAnsFeedTableViewCell? = tableView.dequeueReusableCell(withIdentifier: quesAnsFeedViewCellIdentifier, for: indexPath) as? QuesAnsFeedTableViewCell
if (cell == nil){
cell = QuesAnsFeedTableViewCell(style: .default, reuseIdentifier: quesAnsFeedViewCellIdentifier)
}
cell?.selectionStyle = .none
discussViewHeight[indexPath.section] = (cell?.updateData(data: tableBlocks[indexPath.section]))!
cell?.setNeedsLayout()
cell?.layoutIfNeeded()
return cell!
}
return UITableViewCell()
}
//MARK: TableView Delegate Methods
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if parentView == discussView{
return discussViewHeight[indexPath.section] ?? 0
}
return 0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if parentView == discussView{
return sectionHeaderView
}
return UIView()
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if parentView == discussView && indexPath.section+5 > tableBlocks.count{
if currentUrlPath != baseUrl + nextUrlPath{
getRequest()
}
}
}
}
I have deleted some code from classes just to keep the size of question small.
The call for next fetch will depend on the indexpath of cell which is currently being displayed and the function which fetches the content from server will be getRequest().
Any help is greatly appreciated

UITableView section headers overlapping UITableviewCell and have no background colour

In a previous project using ObjectiveC, I had a multiple section tableView showing section headers with different background colours and with header text that dynamically updated itself dependent upon the number of items within the section. It worked perfectly.
I have tried to replicate this code in a new project in which we are using Swift and it doesn't work. The header text displays correctly, but there is no background colour and most importantly, the section header overlays the top cell in each section rather than sitting above it. This is the relevant code:
// MARK: TableView delegates
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
if let sections = fetchedResultsController!.sections {
return sections.count
}
return 0
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if let sections = fetchedResultsController!.sections {
let currentSection = sections[section]
return currentSection.numberOfObjects
}
return 0
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRectMake(0, 0, tableView.bounds.size.width, 30))
let textHeader = UILabel(frame: CGRectMake(11, 0, 320, 20))
switch (section) {
case 0:
headerView.backgroundColor = UIColor.greenColor()
case 1:
headerView.backgroundColor = UIColor.blueColor()
case 2:
headerView.backgroundColor = UIColor.redColor()
case 3:
headerView.backgroundColor = UIColor.purpleColor()
default:
break
}
let hText: String = "\(fetchedResultsController!.sections![section].name)"
let hItems: String = "\((fetchedResultsController!.sections![section].numberOfObjects) - 1)"
let headerText: String = "\(hText) - \(hItems)items"
textHeader.text = headerText
textHeader.textColor = UIColor.whiteColor()
textHeader.backgroundColor = UIColor.clearColor()
headerView.addSubview(textHeader)
return headerView
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat? {
return 20.0
}
The header overlays because its height is 30, and you return only 20.0 in heightForHeaderInSection func. the background color doesn't show up because you miss a break for each "case" in the switch statements.
Switch cases should end with break, then only it will return the backgroundcolor
Check below code
switch (section) {
case 0:
headerView.backgroundColor = UIColor.greenColor()
break
case 1:
headerView.backgroundColor = UIColor.blueColor()
break
case 2:
headerView.backgroundColor = UIColor.redColor()
break
case 3:
headerView.backgroundColor = UIColor.purpleColor()
break
default:
break
}

Show no data in table view - when no data return from api

I have some 15 collection view cell.when user click each cell, that respective cell data will display in next screen table view.But , some cell are don't have any data.In that case i need to shoe in table view that "No Data".How to show that??
here is my code:
These are the delegate method in my table view :
// array to store the value from json
var arrDict = [Businessdata]()
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
// number of rows
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.arrDict.count
}
// calling each cell based on tap and users ( premium / non premium )
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
//let cell:customCell = self.TableViewList.dequeueReusableCellWithIdentifier("cell") as! customCell
let cell:customCell = tableView.dequeueReusableCellWithIdentifier("cell") as! customCell
cell.vendorName.text = arrDict[indexPath.row].BusinessName
cell.vendorAddress.text = arrDict[indexPath.row].Address
cell.VendorRating.rating = arrDict[indexPath.row].Rating!
return cell
}
Please help me out, where i have to declare that .I am new to ios development.Thanks !
Try this:
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
var numOfSection: NSInteger = 0
if YourArraydata.count > 0
{
self.tableView.backgroundView = nil
numOfSection = 1
}
else
{
var noDataLabel: UILabel = UILabel(frame: CGRectMake(0, 0, self.tableView.bounds.size.width, self.tableView.bounds.size.height))
noDataLabel.text = "No Data Available"
noDataLabel.textColor = UIColor(red: 22.0/255.0, green: 106.0/255.0, blue: 176.0/255.0, alpha: 1.0)
noDataLabel.textAlignment = NSTextAlignment.Center
self.tableView.backgroundView = noDataLabel
}
return numOfSection
}
Use the following extension
extension UITableView {
func setEmptyMessage(_ message: String) {
let messageLabel = UILabel(frame: CGRect(x: 0, y: 0, width: self.bounds.size.width, height: self.bounds.size.height))
messageLabel.text = message
messageLabel.textColor = .black
messageLabel.numberOfLines = 0
messageLabel.textAlignment = .center
messageLabel.sizeToFit()
self.backgroundView = messageLabel
self.separatorStyle = .none
}
func restore() {
self.backgroundView = nil
self.separatorStyle = .none
}
}
Use it in Table View items in row delegate function as
if your_list.count == 0 {
self.tableView.setEmptyMessage("There is no data")
} else {
self.tableView.restore()
}
return your_list.count

Resources