Adding tableview to scrollview with paging enabled. - ios

I am creating an app and one of its screen needs to have a UIScrollView with paging. In each page of the scrollview it needs to have a UITableView as shown:
I have accomplished to create a scrollview with paging enabled (programatically) but the problem I am facing is:
If I create a simple UILabel and add it to the pages, it works fine. But if I create a tableview and add it to the pages (if this term makes sense) nothing gets displayed on the screen. Here is my code with comments on related places for better understanding:
class SampleViewController: UIViewController, UIScrollViewDelegate, UITableViewDelegate, UITableViewDataSource {
let screenHeight = UIScreen.main.bounds.height
let screenWidth = UIScreen.main.bounds.width
let scrollView = UIScrollView()
let tableView = UITableView()
var colors:[UIColor] = [UIColor.red, UIColor.blue, UIColor.green, UIColor.yellow]
let animals: [String] = ["Horse", "Cow", "Camel", "Sheep", "Goat", "Dog", "Cat", "Kitten", "Lion", "Tiger", "Owl", "Skylark", "Snail", "Cub", "Zebra"]
var frame: CGRect = CGRect(x:0, y:0, width:0, height:0)
var pageControl : UIPageControl = UIPageControl(frame: CGRect(x:50,y: 300, width:200, height:50))
let cellReuseIdentifier = "cell"
override func viewDidLoad() {
super.viewDidLoad()
let frameOfScrollView : CGRect = CGRect(x:0, y:0, width:screenWidth, height:screenHeight)
scrollView.frame = frameOfScrollView
scrollView.delegate = self
scrollView.isPagingEnabled = true
tableView.delegate = self
tableView.dataSource = self
self.view.addSubview(scrollView)
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
self.scrollView.contentSize = CGSize(width:self.scrollView.frame.size.width * 4,height: self.scrollView.frame.size.height)
for index in 0..<4 {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
// THIS THING DOESN'T WORK
tableView.frame = frame
self.scrollView .addSubview(tableView)
// THIS THING WORKS
let subView = UILabel(frame: frame)
subView.backgroundColor = colors[index]
subView.text = "how are you?"
self.scrollView .addSubview(subview)
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
pageControl.currentPage = Int(pageNumber)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.animals.count
}
// create a cell for each table view row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
cell.textLabel?.text = self.animals[indexPath.row]
return cell
}
}
What am I doing wrong? Did I miss anything regrading tableview?
Note: I have created views programmatically because I didn't have much understanding regarding which constraints shall I use in order to add paging to scrollview because I am a newbie to iOS. If anyone can provide some solution to my problem in terms of auto layouts, it would be welcomed.
Basically the purpose is just to achieve what is shown in the screenshot attached above. Any alternate approach if applicable, would also be appreciated.

No need to declare global variable for UITableview.
Replace viewDidLoad() to achieve your requirement.
override func viewDidLoad() {
super.viewDidLoad()
let frameOfScrollView : CGRect = CGRect(x:0, y:0, width:screenWidth, height:screenHeight)
scrollView.frame = frameOfScrollView
scrollView.delegate = self
scrollView.isPagingEnabled = true
// tableView.delegate = self
// tableView.dataSource = self
self.view.addSubview(scrollView)
// self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
self.scrollView.contentSize = CGSize(width:self.scrollView.frame.size.width * 4,height: self.scrollView.frame.size.height)
for index in 0..<4 {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
let tableView = UITableView()
tableView.delegate = self
tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
tableView.frame = frame
self.scrollView .addSubview(tableView)
//// // THIS THING DOESN'T WORK
// tableView.frame = frame
// self.scrollView .addSubview(tableView)
// THIS THING WORKS
// let subView = UILabel(frame: frame)
// subView.backgroundColor = colors[index]
// subView.text = "how are you?"
// self.scrollView.addSubview(subView)
}
}
Replace
let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
with
let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
Remove
let tableView = UITableView()

Related

How should I set constraints to the subviews of my tableHeaderView?

I have this viewController:
class CreateSkillGroupViewController: UIViewController {
lazy var headerStack: UIStackView = {
let stack = UIStackView(frame: CGRect(x: 0, y: 0, width: 20, height: 400))
stack.axis = .vertical
let titleField = UITextView(frame: CGRect(x: 0, y: 0, width: 300, height: 88))
titleField.backgroundColor = .green
titleField.snp.makeConstraints{ (make) in
make.height.equalTo(50)
}
let descriptionField = UITextView(frame: CGRect(x: 0, y: 0, width: 300, height: 120))
descriptionField.snp.makeConstraints{ (make) in
make.height.equalTo(100)
}
let headerImage = UIImageView(image: UIImage(named: "AppIcon-bw"))
headerImage.snp.makeConstraints{ (make) in
make.height.equalTo(300)
make.width.equalTo(200)
}
stack.addArrangedSubview(headerImage)
stack.addArrangedSubview(titleField)
stack.addArrangedSubview(descriptionField)
stack.backgroundColor = .blue
return stack
}()
override func viewDidLoad() {
super.viewDidLoad()
configureNavigationItem()
skillsTableView = UITableView(frame: .zero, style: .insetGrouped)
skillsTableView.register(SkillSummaryCell.self)
skillsTableView.tableHeaderView = headerStack
view.addSubview(skillsTableView)
skillsTableView.tableHeaderView?.snp.makeConstraints{ (make) in
make.top.equalToSuperview()
make.left.equalToSuperview()
make.right.equalToSuperview()
make.width.equalToSuperview()
make.height.equalTo(400)
}
skillsTableView.snp.makeConstraints{ (make) in
make.edges.equalToSuperview()
}
...
This is what it creates...
As you can see I use the lazy var headerStack to setup the tableHeaderView which is a stackView. As you can see all of the constraints in that stack view are explicit number sizes. Then in the viewDidLoad, I add the constraints for the tableView itself.
I want to know how I would for instance, center the headerImage in the viewController, or in the tableView for that matter or make its width half of the tableView's width. I cannot set equalToSuperView because the view hasn't been laid out yet. And once its laid out, I cannot access the stack view subviews to retroactively add constraints to them.
First of all, I wouldn't use a stackView as a tableHeaderView because you need your tableHeaderView to be the same width as the tableView. Embed your stackView in a view and use that view as the header. Ensure that header remains the width of the tableView regardless of the stackView content.
Also, it looks like you are trying to mix autolayout with frame-based layout and that's gonna get you into trouble. I'm not sure why you were setting frames on some of your subviews.
Pay attention to how you define stackView.alignment and stackView.distribution. I'm not sure what your goal is so it's hard to give you much advice there. Bit I assume you want your subviews centered and to have their own unique width.
You defined a lot of your subviews in your stackView builder and that got you into trouble. Ensure that you have one builder for each subview. It helps keep your code clean.
Lastly, you can use autolayout to define the width equal to the width of the tableView. There are a lot of solutions on the web that make you compute the frames for your header manually and that's just a pain.
I changed some names around added some colors but I think this will help you:
extension UIColor {
static let headerImage = UIColor.systemPurple
static let header = UIColor.systemPink
static let titleField = UIColor.white
static let descriptionField = UIColor.systemYellow
static let headerStack = UIColor.systemOrange
static let tableView = UIColor.systemMint
}
class ViewController: UIViewController {
lazy var headerImage: UIImageView = {
let headerImage = UIImageView(image: UIImage(systemName: "checkmark"))
headerImage.translatesAutoresizingMaskIntoConstraints = false
headerImage.backgroundColor = .headerImage
return headerImage
}()
lazy var headerView: UIView = {
let header = UIView()
header.backgroundColor = .header
header.translatesAutoresizingMaskIntoConstraints = false
return header
}()
lazy var titleField: UITextView = {
let titleField = UITextView(frame: .zero)
titleField.translatesAutoresizingMaskIntoConstraints = false
titleField.backgroundColor = .titleField
return titleField
}()
lazy var descriptionField: UITextView = {
let descriptionField = UITextView(frame: .zero)
descriptionField.translatesAutoresizingMaskIntoConstraints = false
descriptionField.backgroundColor = .descriptionField
return descriptionField
}()
lazy var headerStack: UIStackView = {
let stack = UIStackView(frame: .zero)
stack.translatesAutoresizingMaskIntoConstraints = false
stack.axis = .vertical
stack.distribution = .fillProportionally
stack.alignment = .center
stack.spacing = 10
stack.backgroundColor = .headerStack
return stack
}()
lazy var tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .insetGrouped)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.register(SkillSummaryCell.self, forCellReuseIdentifier: "SkillSummaryCell")
tableView.backgroundColor = .tableView
tableView.delegate = self
tableView.dataSource = self
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
addViews()
arrangeViews()
tableView.layoutIfNeeded()
}
func addViews() {
view.addSubview(tableView)
headerStack.addArrangedSubview(headerImage)
headerStack.addArrangedSubview(titleField)
headerStack.addArrangedSubview(descriptionField)
headerView.addSubview(headerStack)
tableView.tableHeaderView = headerView
}
func arrangeViews() {
tableView.snp.makeConstraints{ (make) in
make.edges.equalTo(view.safeAreaLayoutGuide)
}
descriptionField.snp.makeConstraints{ (make) in
make.height.equalTo(100)
make.width.equalTo(300)
}
titleField.snp.makeConstraints{ (make) in
make.height.equalTo(100)
make.width.equalTo(300)
}
headerStack.snp.makeConstraints { make in
make.top.equalToSuperview()
make.bottom.equalToSuperview()
make.centerX.equalToSuperview()
}
headerView.snp.makeConstraints { make in
make.width.equalTo(tableView)
}
headerImage.snp.makeConstraints{ (make) in
make.width.equalTo(tableView).dividedBy(2)
make.height.equalTo(headerImage.snp.width)
}
}
}
use it:
viewForHeaderInSection
as
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let tableBounds = tableView.bounds // <- table size
let sectionIndex = section // <- Section index
}
In this method, you can customize the header for a specific section, and take into account the size of your table
ALSO:
You can use UIScreen.main.bounds - get the screen size of your phone at any time, this can be very useful, especially considering that tables are often equal in width to the width of the screen

There is change add to atop duplicate header, but there is a stretch effect?

enter image description hereThere is a stretch effect.But the additional header is duplicated , only without data.Can anyone correct my code that I wrote extra or incorrectly called the header?.I have custom Header xib. link tutorial https://mobikul.com/table-view-stretch-header-parallax-animation-in-swift/
My code:
var headerView: CustomSoccerHeaderView? = {
return Bundle.main.loadNibNamed("CustomSoccerHeaderView", owner: nil, options: nil)!.first as! CustomSoccerHeaderView
}()
override func viewDidLoad() {
super.viewDidLoad()
let backButton = UIBarButtonItem()
backButton.title = ""
self.navigationController?.navigationBar.topItem?.backBarButtonItem = backButton
// self.navigationItem.rightBarButtonItem = barButton
// self.navigationItem.rightBarButtonItem?.tintColor = UIColor.universalColorYellow
let yourBackImage = UIImage(named: "backItem")
self.navigationController?.navigationBar.backIndicatorImage = yourBackImage
self.navigationController?.navigationBar.backIndicatorTransitionMaskImage = yourBackImage
self.navigationController?.navigationItem.leftItemsSupplementBackButton = true
self.navigationController?.navigationBar.tintColor = UIColor.universalColorYellow
//title = detailSoccer.detailTitleS
let nib: UINib = UINib(nibName: "CustomSoccerHeaderView", bundle: nil)
tableView.register(nib, forHeaderFooterViewReuseIdentifier: "CustomSoccerHeaderView")
tableView.tableFooterView = UIView(frame: .zero)
tableView.estimatedRowHeight = 280
headerView?.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 350)
tableView.tableHeaderView = headerView
tableView.tableHeaderView = nil
tableView.contentInset = UIEdgeInsets(top: 350, left: 0, bottom: 0, right: 0)
tableView.addSubview(headerView!)
tableView.separatorStyle = .none
tableView.delegate = self
tableView.dataSource = self
tableView.register(UINib(nibName:"FootTableViewCell",bundle:nil), forCellReuseIdentifier: "cellSoc")
self.view.addSubview(tableView)
tableView.rowHeight = UITableView.automaticDimension
tableView.reloadData()
loadMatchSoccer()
tableView.rowHeight = UITableView.automaticDimension
}
That's going to stretch the effect:
func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
self.tableView.reloadData()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if headerView != nil {
let yPos: CGFloat = -scrollView.contentOffset.y
if yPos > 0 {
var imgRect: CGRect? = headerView?.frame
imgRect?.origin.y = scrollView.contentOffset.y
imgRect?.size.height = 350 + yPos - 350
headerView?.frame = imgRect!
self.tableView.sectionHeaderHeight = (imgRect?.size.height)!
}
}
}
This is the code for the header section of my file xib class.I think I make a mistake in inheriting the header or loading addsubview.Maybe someone more experienced can tweak my code.I would appreciate that.
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: "CustomSoccerHeaderView") as! CustomSoccerHeaderView
header.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 350)
header.clickBravisso = detailSoccer
header.nameHeader.text = detailSoccer.matchS
header.countBravo.text = ""
// header.bravoBtn.addTarget(CustomSoccerHeaderView(), action: #selector(CustomSoccerHeaderView.likeBtn(_:)), for: UIControlEvents.touchUpInside)
detailSoccer.imagePrS.getDataInBackground { (data, error) in
header.imageHeader.image = error == nil ? UIImage(data: data!) : nil
}
return header
}

Swift UITableView does not show up the content

I have a side menu and for each selection I want to load a new ViewController (basically each page has a separate ViewController).
This is the relevant code where I load a new ViewController:
viewController = storyboard!.instantiateViewController(withIdentifier: "commissionsViewController")
var viewInAction = UIView()
viewInAction = viewController.view
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapOnView))
viewInAction.addGestureRecognizer(gestureRecognizer)
viewInAction.layer.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0).cgColor
viewInAction.translatesAutoresizingMaskIntoConstraints = false
if let subview = containerView.viewWithTag(100) {
subview.removeFromSuperview()
}
containerView.insertSubview(viewInAction, belowSubview: menuView)
setConstrainsOnView(viewObject: viewInAction)
This is the code for the ViewController that is loaded:
import UIKit
class CommissionsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView = UITableView()
var tableData = ["Beach", "Clubs", "Chill", "Dance"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView = UITableView(frame: self.view.bounds, style: UITableViewStyle.plain)
tableView.dataSource = self
tableView.delegate = self
tableView.backgroundColor = UIColor.blue
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "my")
tableView.contentInset.top = 20
let contentSize = self.tableView.contentSize
let footer = UIView(frame: CGRect(x: self.tableView.frame.origin.x,
y: self.tableView.frame.origin.y + contentSize.height,
width: self.tableView.frame.size.width,
height: self.tableView.frame.height - self.tableView.contentSize.height))
self.tableView.tableFooterView = footer
view.addSubview(tableView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "my", for: indexPath)
cell.textLabel?.text = "This is row \(tableData[indexPath.row])"
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
The problem: As you can see the CommissionsViewController contains a tableView that is added programatically. That tableView does not show up any cell! Basically the method cellForRowAt is never called! And I don't understand why!
I can see a blue view, which is the tableView's background, so the tableView is in place, but it doesn't load the cells!
The method numberOfRowsInSection is called.
I tried to debug it using the debugger but no result. I simply don't understand the flow.
Thank you respectfully.
When you add another viewController's view to your view hierarchy, you must tell both viewControllers (see this answer for further information).
Add the addChildViewController and didMoveToParentViewController calls like this:
viewController = storyboard!.instantiateViewController(withIdentifier: "commissionsViewController")
self.addChildViewController(viewController)
var viewInAction = viewController.view
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.tapOnView))
viewInAction.addGestureRecognizer(gestureRecognizer)
viewInAction.layer.backgroundColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0).cgColor
viewInAction.translatesAutoresizingMaskIntoConstraints = false
if let subview = containerView.viewWithTag(100) {
subview.removeFromSuperview()
}
containerView.insertSubview(viewInAction, belowSubview: menuView)
setConstrainsOnView(viewObject: viewInAction)
viewController.didMoveToParentViewController(self)
After you set the dataSource and he delegate to self, you never make the tableView load any data. That means you need to call tableView.reloadData() at the end of viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView = UITableView(frame: self.view.bounds, style: UITableViewStyle.plain)
tableView.dataSource = self
tableView.delegate = self
tableView.backgroundColor = UIColor.blue
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "my")
tableView.contentInset.top = 20
let contentSize = self.tableView.contentSize
let footer = UIView(frame: CGRect(x: self.tableView.frame.origin.x,
y: self.tableView.frame.origin.y + contentSize.height,
width: self.tableView.frame.size.width,
height: self.tableView.frame.height - self.tableView.contentSize.height))
self.tableView.tableFooterView = footer
view.addSubview(tableView)
tableView.reloadData()
}
In viewDidLoad method view is loaded but has incorrect size.
Try to change initialization of UITableView in next way
let screenBounds = UIScreen.main.bounds
let rect = CGRect(x: 0, y: 0, width: screenBounds.width, height: screenBounds.height)
tableView = UITableView(frame: rect, style: UITableViewStyle.plain)
Go to ComissionsViewController, viewDidLoad() method and add tableView.reloadData() right after view.addSubview(tableView) — it makes all your troubles disappear.
UPD: I have just made a test project where it works. I have copied the code you posted and only commented a couple of unrelated lines. The only significant difference I made is adding the line of code I mentioned above. You can download and run it to see it works :)
https://drive.google.com/file/d/0B55tO8S_7Ag7VnppMk1fWlg5dWM/view

UIView of TableView can't scroll or tap

What I did was when the search controller is clicked, it shows a View with a tableView in it. (like Instagram) . It shows the tableView but it cannot interact with it.
I was doing some research since people had come across this before here. Here are the things I've tried:
Bring subView to the front
have set tableView.isUserInteractionEnabled = true -> Have also ran on iPhone
Have set tableViewHeight to ScreenHeight
But the tableView still doesn't want to scroll/click!
Here's the relevant code that I have if it helps,
Controller with search bar and collection views:
class UserSearchController: UICollectionViewController, UICollectionViewDelegateFlowLayout,UISearchBarDelegate, UISearchDisplayDelegate {
let cellId = "cellId"
let searchBar: UISearchBar = {
let sb = UISearchBar()
sb.placeholder = "Search"
return sb
}()
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
searchBar.setShowsCancelButton(true, animated: true)
tableView.isHidden = false
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.setShowsCancelButton(true, animated: true)
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
searchBar.setShowsCancelButton(false, animated: true)
searchBar.text = ""
tableView.isHidden = true
}
let tableView: UIView = {
let tv = SearchUsersTv()
tv.isUserInteractionEnabled = true
tv.bringSubview(toFront: tv)
tv.clipsToBounds = false
return tv
}()
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.register(UserProfileVideoCell.self, forCellWithReuseIdentifier: cellId)
view.addSubview(tableView)
tableView.isHidden = true
}
Here's the code for the relevant code for the tableView (SearchUsersTv):
class SearchUsersTv: UIView, UITableViewDelegate, UITableViewDataSource {
let cellId = "cellId"
var tableView = UITableView()
override init(frame: CGRect){
super.init(frame: frame)
setupTv()
}
func setupTv() {
let screenHeight = UIScreen.main.bounds.height
let screenWidth = UIScreen.main.bounds.width
tableView.delegate = self
tableView.dataSource = self
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
tableView.isUserInteractionEnabled = true
tableView = UITableView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight))
self.addSubview(tableView)
bringSubview(toFront: tableView)
}
Problem to fix: Make tableView scroll and click
Thank you in advanced!
Your problems is that you are initialising your custom class in wrongly way, you need call SearchUsersTv(frame: instead of SearchUsersTv() for initialisation because all your tableView setup happen on setupTv() which is called in SearchUsersTv(frame: initialisation only
replace your tableView inline creation by this
let tableView: UIView = {
let screenHeight = UIScreen.main.bounds.height
let screenWidth = UIScreen.main.bounds.width
let tv = SearchUsersTv(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight))
tv.isUserInteractionEnabled = true
tv.bringSubview(toFront: tv)
tv.clipsToBounds = false
tv.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cellId")
return tv
}()

How to change separator height in UITableView Swift 3?

Although there a few answers already on this topic. None of them cover Swift 3 and they are from a long time ago. What is currently the best way to change the separator height in a UITableView in Swift 3?
Updated for Swift 3:
If you want to change the height of the UITableView separator, use the code below.
You should add it to the UITableViewCell method awakeFromNib() to avoid re-creation.
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let mScreenSize = UIScreen.main.bounds
let mSeparatorHeight = CGFloat(3.0) // Change height of speatator as you want
let mAddSeparator = UIView.init(frame: CGRect(x: 0, y: self.frame.size.height - mSeparatorHeight, width: mScreenSize.width, height: mSeparatorHeight))
mAddSeparator.backgroundColor = UIColor.brown // Change backgroundColor of separator
self.addSubview(mAddSeparator)
}
This is a correct way to do this.
First, in your ViewController you should set (tableView.separatorStyle = .none)
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .none
}
}
Second, in your TableViewCell class your should create a separatorView.
And don't forget to inherit TableViewCell class for your cell.
class TableViewCell: UITableViewCell {
let separator = UIView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
separator.backgroundColor = .black
contentView.addSubview(separator)
}
override func layoutSubviews() {
super.layoutSubviews()
//Your separatorLineHeight with scalefactor
let separatorLineHeight: CGFloat = 1/UIScreen.main.scale
separator.frame = CGRect(x: self.contentView.frame.origin.x,
y: self.contentView.frame.size.height - separatorLineHeight,
width: self.contentView.frame.size.width,
height: separatorLineHeight)
}
}
Finally, you've got a thin separator line and, of course, you can increase this value what do you like.
For Those who want to do it using autolayout here is the code
var additionalSeparator:UIView = UIView()
override func awakeFromNib() {
super.awakeFromNib()
self.createSeparator()
}
func createSeparator() {
self.additionalSeparator.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(self.additionalSeparator)
}
func setConstraintForSeparator() {
self.additionalSeparator.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: self.separatorInset.left).isActive = true
self.additionalSeparator.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -self.separatorInset.right).isActive = true
self.additionalSeparator.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: 0).isActive = true
self.additionalSeparator.heightAnchor.constraint(equalToConstant: 1).isActive = true
self.additionalSeparator.backgroundColor = UIColor.greyishBrown
}
Try this Swift 3:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: YOUR_CELL_IDENTIFIER, for: indexPath) as! yourTableViewCell
let viewSeparatorLine = UIView(frame:CGRect(x: 0, y: cell.contentView.frame.size.height - 5.0, width: cell.contentView.frame.size.width, height: 5))
viewSeparatorLine.backgroundColor = .red
cell.contentView.addSubview(viewSeparatorLine)
return cell
}

Resources