Empty Horizontal Table Cells - ios

I've been following (and converting to swift) a Ray Wenderlich tutorial (link to tutorial) on how to make an interface with horizontal tables. My application loads but does not show any data in the cells as below:
I have three swift files in the project:ArticleTableViewCell.swiftHorizontalTableViewCell.swiftArticleListViewController.swift
// ArticleTableViewCell.swift
// HorizontalTables
import UIKit
class ArticleTableViewCell: UITableViewCell {
var thumbnail: UIImageView!
var titleLabel: UILabel!
override init(frame: CGRect) {
super.init(frame: frame)
var frameA: CGRect = CGRectMake(3, 3, 100, 314)
thumbnail = UIImageView(frame: frameA)
thumbnail.opaque = true
self.contentView.addSubview(thumbnail)
var frameB: CGRect = CGRectMake(0, thumbnail.frame.size.height * 0.632, thumbnail.frame.size.width, thumbnail.frame.size.height * 0.37)
titleLabel = UILabel(frame: frameB)
titleLabel.opaque = true
titleLabel.backgroundColor = UIColor.clearColor()
titleLabel.textColor = UIColor.blackColor()
titleLabel.numberOfLines = 2
titleLabel.font = UIFont(name: "Helvetica Neue", size: 12)
thumbnail.addSubview(titleLabel)
self.transform = CGAffineTransformMakeRotation(CGFloat(M_PI) * 0.5)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func reuseIdentifier() -> String {
return "ArticleCell"
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
// HorizontalTableViewCell.swift
// HorizontalTables
import UIKit
class HorizontalTableViewCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource {
var horizontalTableView: UITableView!
var articles: NSArray!
override init(frame: CGRect) {
super.init(frame: frame)
var frameA: CGRect = CGRectMake(0, 0, 106, 320)
horizontalTableView = UITableView(frame: frameA)
horizontalTableView.showsVerticalScrollIndicator = false
horizontalTableView.showsHorizontalScrollIndicator = false
horizontalTableView.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI) * 0.5)
horizontalTableView.frame = CGRectMake(0, 0, 320, 106)
horizontalTableView.rowHeight = 106
horizontalTableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine
horizontalTableView.separatorColor = UIColor.clearColor()
horizontalTableView.backgroundColor = UIColor(red: 201/252, green: 235/252, blue: 245/252, alpha: 1)
horizontalTableView.dataSource = self
horizontalTableView.delegate = self
self.addSubview(horizontalTableView)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return articles.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ArticleCell", forIndexPath: indexPath) as ArticleTableViewCell
let currentArticle: NSDictionary = articles.objectAtIndex(indexPath.row) as NSDictionary
cell.titleLabel.text = currentArticle.objectForKey("Title") as NSString
var pics: AnyObject = currentArticle.objectForKey("ImageName")!
cell.imageView?.image = UIImage(named: "\(pics)")
return cell
}
}
// ArticleListViewController.swift
// HorizontalTables
import UIKit
class ArticleListViewController: UITableViewController {
var articleDictionary: NSDictionary = NSDictionary()
let kHeadlineSectionHeight: Int = 26
let kRegularSectionHeight: Int = 26
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.rowHeight = 45
let path = NSBundle.mainBundle().pathForResource("Articles", ofType: "plist")
UITableViewHeaderFooterView.appearance().tintColor = UIColor(red: 201/252, green: 235/252, blue: 245/252, alpha: 1)
articleDictionary = NSDictionary(contentsOfFile: path!)!
}
override func awakeFromNib() {
super.awakeFromNib()
self.tableView.backgroundColor = UIColor(red: 201/252, green: 235/252, blue: 245/252, alpha: 1)
tableView.rowHeight = 106
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 45
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return articleDictionary.allKeys.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
let keys: NSArray = articleDictionary.allKeys
var sortedCategories: NSArray = keys.sortedArrayUsingSelector("localizedCompare:")
var categoryName: NSString = sortedCategories.objectAtIndex(section) as NSString
return categoryName.substringFromIndex(1)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier", forIndexPath: indexPath) as HorizontalTableViewCell
let keys: NSArray = articleDictionary.allKeys
var sortedCategories: NSArray = keys.sortedArrayUsingSelector("localizedCompare:")
var categoryName: NSString = sortedCategories.objectAtIndex(indexPath.section) as NSString
let currentCategory: NSArray = articleDictionary.objectForKey(categoryName) as NSArray
cell.articles = currentCategory
if (indexPath.row % 2) == 1 {
cell.backgroundColor = UIColor(red: 201/252, green: 235/252, blue: 245/252, alpha: 1)
} else {
cell.backgroundColor = UIColor.clearColor()
}
return cell
}
}
Any thoughts on why I have tableView cells with no data?

It looks like you didn't register your cells to your tableview. If you're using a Storyboard, you need to enter in the cell identifier there. If XIBs, you'll need to register the class to the tableview first:
tableView.registerClass(ArticleTableViewCell.self, forCellReuseIdentifier: "ArticleCell")

The UITableViewController will be initialized. In the meanwhile, the delegate method and data sources methods are called for initializing purpose. That moment, you will only get what you have from your prototype of UITableViewCell. So, you have to call reloadData after you successfully distribute the data.

The problem is that you are using dequeueReusableCellWithIdentifier. It doesn't even use HorizontalTableViewCell(frame:CGRect) to init a TableViewCell, unless you manually do so. You should do something like this:
var cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier", forIndexPath: indexPath) as? HorizontalTableViewCell
if cell == nil {
cell = HorizontalTableViewCell(frame: CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height))
}
Same for ArticleTableViewCell:
var cell = tableView.dequeueReusableCellWithIdentifier("ArticleCell", forIndexPath: indexPath) as? ArticleTableViewCell
if cell == nil {
cell = ArticleTableViewCell(frame: CGRectMake(0, 0, 106, 106))
}

You can try using this init function in your cell
initWithStyle:reuseIdentifier:

Related

Swift UITableView separator hidden until scroll

I have implemented a custom table view cell which appears but without the separator until you scroll. In the viewDidAppear I have set the separator style, the label border is not overlapping the cell edges. Help
Before Scrolling
After Scrolling
Larger Sim Window
On device testing
The pattern is MVVM with a custom cell.
Model
import Foundation
struct OAuthList {
let providers: [String]
init() {
self.providers = OAuthProviders.providers
}
}
View Model
import Foundation
struct OAuthListViewModel {
var providerList: [String]
init(providers: [String]) {
self.providerList = providers
}
}
LoginViewController
import UIKit
class LoginViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
var providerButtons = OAuthListViewModel(providers: OAuthProviders.providers)
override func viewDidLoad() {
super.viewDidLoad()
let attributes = [NSAttributedString.Key.foregroundColor: UIColor.white, NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17)]
self.navigationController?.navigationBar.titleTextAttributes = attributes
self.navigationController?.navigationBar.isTranslucent = false
self.navigationController?.navigationBar.barTintColor = #colorLiteral(red: 1, green: 0.738589704, blue: 0.9438112974, alpha: 1)
self.navigationItem.title = "LOGIN / SIGNUP"
self.navigationItem.leftBarButtonItem?.tintColor = .white
self.navigationItem.leftBarButtonItem?.isEnabled = false
self.tableView.separatorColor = .white
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.register(CustomCell.self, forCellReuseIdentifier: TextCellIdentifier.textCellIdentifier)
self.tableView.layoutMargins = UIEdgeInsets.zero
self.tableView.separatorInset = UIEdgeInsets.zero
self.tableView.tableFooterView = UIView()
}
}
extension LoginViewController {
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return providerButtons.providerList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: TextCellIdentifier.textCellIdentifier, for: indexPath) as! CustomCell
let row = indexPath.row
cell.backgroundColor = #colorLiteral(red: 1, green: 0.738589704, blue: 0.9438112974, alpha: 1)
cell.buttonLabel.text = providerButtons.providerList[row]
cell.layoutMargins = UIEdgeInsets.zero
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print(providerButtons.providerList[indexPath.row])
}
}
Custom Cell
class CustomCell: UITableViewCell {
var labelText: String?
var buttonLabel: UILabel = {
var label = UILabel()
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: TextCellIdentifier.textCellIdentifier)
self.addSubview(buttonLabel)
buttonLabel.translatesAutoresizingMaskIntoConstraints = false
buttonLabel.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
buttonLabel.centerXAnchor.constraint(equalTo: self.centerXAnchor).isActive = true
buttonLabel.textColor = UIColor.white
}
override func layoutSubviews() {
if let labelText = labelText {
buttonLabel.text = labelText
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
You can hide the separator and simply add UIView to act as a separator inside your custom cells
Enlarge your simulator window or try it on an actual device not sim.
When the sim window is small enough it can have a hard time displaying separators in a tableview since the separators are normally only 0.5pt in height.
A good indicator that the issue I mentioned above is occurring is when you scroll the tableview on the simulator and random separators start to appear while some are hidden. Which is what appears to be happening in your second screenshot.

UITableview scrolling is not responding properly?

booktable.frame = CGRect(x: 0, y: booktopview.bounds.height, width: screenWidth, height: screenHeight-booktopview.bounds.height-tabbarView.bounds.height)
booktable.register(UITableViewCell.self, forCellReuseIdentifier: "mycell")
booktable.dataSource = self
booktable.delegate = self
booktable.separatorColor = UIColor.lightGray
booktable.backgroundColor = UIColor.clear
booktable.separatorStyle = .singleLine
bookview.addSubview(booktable)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(tableView == booktable)
{
let cell1 = booktable.dequeueReusableCell(withIdentifier: "mycell")
for object in (cell1?.contentView.subviews)!
{
object.removeFromSuperview();
}
let img :UIImageView = UIImageView()
let lbl : UILabel = UILabel()
img.frame = CGRect(x: 15, y: 15, width: 80, height: 130)
img.image = imgarray[indexPath.row]
img.layer.borderWidth = 1.0
img.layer.borderColor = UIColor.lightGray.cgColor
cell1?.contentView.addSubview(img)
imgheight = img.bounds.height
lbl.frame = CGRect(x: img.bounds.width + 40, y: (imgheight+40-80)/2, width: booktable.bounds.width-img.bounds.width + 40 - 100, height: 80)
lbl.text = imgname[indexPath.row]
lbl.numberOfLines = 0
lbl.textAlignment = .left
lbl.font = UIFont(name: "Arial", size: 23)
lbl.textColor = UIColor.black
cell1?.selectionStyle = .none
cell1?.contentView.addSubview(lbl)
return cell1!
}
The code shown above is for book table, which sometimes scrolls like normal and sometimes not scrolling at all. I am doing all the code programatically. I have tested this on both simulators and devices but still the problem exists. Any help is appreciated...
Create Custom UITableViewCell, let's say it is ListTableCell
class ListTableCell: UITableViewCell {
#IBOutlet weak var lblTemp: UILabel!
#IBOutlet weak var imgTemp: UIImage!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I've created UITableViewCell with xib like this and bind IBOutlets
Let's say we have struct Model and array like this
struct Model {
let image : UIImage
let name: String
}
for i in 0...10 {
let model = Model(image: #imageLiteral(resourceName: "Cat03"), name: "Temp \(i)")
array.append(model)
}
Now on ViewController viewDidLoad() method,
tableView.register(UINib(nibName: "ListTableCell", bundle: nil), forCellReuseIdentifier: "ListTableCell")
Implement UITableViewDataSource methods like this,
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ListTableCell") as! ListTableCell
let model = array[indexPath.row]
cell.lblTemp.text = model.name
cell.imgTemp.image = model.image
return cell
}
FYI
For different tableviews, you can create different custom cell the same way and cellForRowAt indexPath and numberOfRowsInSection method will change appropriately.
Let me know in case of any queries.
UPDATE
Follow this and this to create CustomTableCell programmatically

Swift 'Must register a nib or a class for the identifier or connect a prototype cell in a storyboard'

I have some basic code, trying to load a UITableView with some cells. I had set cell's ID in Storyboard,and create a swift file and xib for cell named "DemoListCell". I keep getting this error, although i don't use storyboards in my project.
Any ideas? Thanks for all of you .
import UIKit
// MARK:
class ViewController: UIViewController,UITableViewDataSource {
let cellId = "DemoListID"
let TopTableView = UITableView()
let PageTableView = UITableView()
let PageScrollView = UIScrollView()
var CellsIdentifier:String = ""
var NumbersofTab:CGFloat = 4
var Number:CGFloat = 4
var Size:CGFloat = 0
var OldPoint:CGFloat = 0
var NewPoint:CGFloat = 0{
didSet{
TopTableView.reloadData()
}
}
// MARK: - ViewDidLoad and init()
override func viewDidLoad() {
let TopWidth = self.view.frame.size.width
Size = TopWidth
let TopHeight:CGFloat = 50
let TopY = 0 - (TopWidth - TopHeight)/2
let TopX = 0 + (TopWidth - TopHeight)/2
let PageY = TopHeight
let PageHeight = self.view.frame.size.height - TopHeight
//TopTableView
TopTableView.frame = CGRectMake(TopX, TopY, TopHeight,TopWidth)
TopTableView.transform = CGAffineTransformMakeRotation(CGFloat(-M_PI/2))
TopTableView.showsVerticalScrollIndicator = false
TopTableView.backgroundColor = UIColor.yellowColor()
TopTableView.dataSource = self
TopTableView.delegate = self
//PageTableView
PageTableView.frame = CGRectMake(0, 0, TopWidth,PageHeight)
let nib = UINib(nibName: "DemoListCell", bundle: nil) //Cell's Name
self.PageTableView.registerNib(nib, forCellReuseIdentifier: cellId)
PageTableView.backgroundColor = UIColor.blueColor()
//PageScrollView
PageScrollView.frame = CGRectMake(0, PageY, TopWidth,PageHeight)
PageScrollView.delegate = self
PageScrollView.contentSize = CGSize(width: TopWidth * NumbersofTab, height: PageScrollView.frame.height)
PageScrollView.pagingEnabled = true
PageScrollView.alwaysBounceHorizontal = false
PageScrollView.alwaysBounceVertical = false
//addSubview
self.view.addSubview(TopTableView)
PageScrollView.addSubview(PageTableView)
self.view.addSubview(PageScrollView)
}
}
// MARK: - UIScrollViewDelegate
extension ViewController: UIScrollViewDelegate{
func scrollViewWillBeginDragging(scrollView: UIScrollView) {
OldPoint = PageScrollView.contentOffset.x
}
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
NewPoint = PageScrollView.contentOffset.x
print("\( NewPoint)")
}
}
// MARK: - UITableViewDalegate
extension ViewController:UITableViewDelegate{
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(self.cellId, forIndexPath: indexPath) as! DemoListCell
if tableView.isEqual(TopTableView){
var cell:TopTableViewCell! = tableView.dequeueReusableCellWithIdentifier("cd") as? TopTableViewCell
if (cell == nil) {
cell = TopTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cd")
switch indexPath.row{
case 0:
cell.backgroundColor = UIColor.greenColor()
case 1:
cell.backgroundColor = UIColor.redColor()
case 2:
cell.backgroundColor = UIColor.yellowColor()
case 3:
cell.backgroundColor = UIColor.whiteColor()
default:
cell.backgroundColor = UIColor.grayColor()
}
}
cell.TabTitle.text = "\(Int(NewPoint / Size))"
}
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let RowNumber:Int = 1
switch RowNumber{
default: return Int(NumbersofTab)
}
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let NumberofPages = Size / NumbersofTab
return NumberofPages
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
UIView.animateWithDuration(0.3) { () -> Void in
let Pages = self.Size * CGFloat(indexPath.row)
self.PageScrollView.contentOffset = CGPoint(x: Pages, y: 0)
self.TopTableView.reloadData()
self.NewPoint = self.PageScrollView.contentOffset.x
}
}
}
and this is "CellId" cell's Code:
class DemoListCell: UITableViewCell {
#IBOutlet weak var cellImg: UIImageView!
#IBOutlet weak var cellLabel: UILabel!
#IBOutlet weak var cellIcon: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
self.cellImg.layer.masksToBounds = true
self.cellImg.layer.cornerRadius = 20.0
self.cellImg.layer.borderWidth = 0.0
self.cellImg.image = UIImage(named: "avatar.jpg")// Initialization code
self.cellIcon.image = UIImage(named: "Next")
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
and there is "Cd" cell's Code:
class TopTableViewCell: UITableViewCell {
var TabTitle = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
TabTitle = UILabel(frame: CGRectZero)
TabTitle.textAlignment = NSTextAlignment.Right
TabTitle.numberOfLines = 1
TabTitle.backgroundColor = UIColor.clearColor()
TabTitle.textColor = UIColor(red: 130/255, green: 137/255, blue: 141/255, alpha: 1.0)
self.contentView.addSubview(self.TabTitle)
// 130 137 141
self.separatorInset = UIEdgeInsets(top: 0, left: 100, bottom: 0, right: -100)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
let marginX = CGFloat(0.0)
let marginY = CGFloat(0.0)
let width = CGFloat(30)
let height = self.contentView.frame.size.width
self.TabTitle.transform = CGAffineTransformMakeRotation(CGFloat(M_PI/2))
self.TabTitle.frame = CGRectMake(marginX, marginY, width, height)
}
}
When you register a nib with registerNib, you pass in a reuse identifier (second parameter). That identifier needs to be used in cellForRowAtIndexPath. However, your cellForRowAtIndexPath uses "cd" as the reuse identifier, not cellId, the one you registered the nib with. To fix this, change the two reuse identifier strings in cellForRowAtIndexPath:
var cell:TopTableViewCell! = tableView.dequeueReusableCellWithIdentifier(cellId) as? TopTableViewCell
if (cell == nil) {
cell = TopTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: cellId)
Edit
My mistake, I did not see the other dequeue at the top of the cellForRowAtIndexPath. However, I only saw one nib registered in viewDidLoad, so that means TopTableViewCell was never registered with identifier "cd".

Can't add UITableView to UIView swift

I have a UIViewController with a header subview and a UITableView.
My tableView with its custom cells works perfectly when I implement it on a UITableView class, but once I try to imbed it in my UIViewController, I get the tableview frame that I see based on the different background color but it doesn't get populated with my custom cell.
My print statement in tableview (...cellForRowAtIndexPath ..) doesn't print anything, it's as if the function is not called.
I'm not sure what I'm doing wrong, any help is much appreciated!
import UIKit
class ProfileViewController: UIViewController , UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView!
var header: UIView!
var userName: UILabel!
var userImage: UIImageView!
var dataDict : NSDictionary!
var cellArray: NSArray!
var friends = [Friends]()
init(dataDict: NSDictionary , nibName: String?, bundle: NSBundle?){
super.init(nibName: nibName, bundle: bundle)
self.dataDict = dataDict
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
cellArray = dataDict?.objectForKey("data") as! NSArray
tableView.delegate = self
tableView.dataSource = self
header = UIView(frame: CGRectZero)
header.backgroundColor = UIColor( red:77/255.0, green:255/255.0, blue:195/255.0, alpha:1.0)
userName = UILabel(frame: CGRectZero)
userName.textAlignment = .Left
userName.text = "Nachwa El khamlichi"
userName.textColor = UIColor.blackColor()
userName.frame = CGRectMake(10, 100, self.view.frame.width/2, 40)
userImage = UIImageView(frame: CGRectZero)
userImage.frame = CGRectMake(10, 30, 80, 80)
tableView.contentInset = UIEdgeInsets(top: 300, left: 0, bottom: 0, right: 0)
tableView.backgroundColor = UIColor.orangeColor()
tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine
self.view.addSubview(header)
self.view.addSubview(userName)
self.view.addSubview(userImage)
self.view.addSubview(tableView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print(cellArray.count)
let cell = tableView.dequeueReusableCellWithIdentifier( NSStringFromClass(Cell), forIndexPath: indexPath) as! Cell
let friendName = cellArray[indexPath.row]["name"] as? String
let avatarId = cellArray[indexPath.row]["id"] as? String
friends.append(Friends(name: friendName!, avatarId: avatarId!))
cell.friend?.name = friendName
cell.friend = friends[indexPath.row]
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 40
}
}
I think you forget to add
tableView = UITableView(frame: UIScreen.mainScreen().bounds, style: UITableViewStyle.Plain)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.view.addSubview(self.tableView)
at the same time you forget to add frame
header = UIView(frame: CGRectZero)
header.frame = CGRectMake(10, 100, self.view.frame.width/2, 40)
header.backgroundColor = UIColor( red:77/255.0, green:255/255.0, blue:195/255.0, alpha:1.0)
OPtion-2
if every thing is fine check once
your cellArray contains data available or not`,
option-3
after this line add this
self.view.addSubview(self.tableView)
tableView.reloadData()

swift table section header duplicating on scroll

I am admitting defeat with these custom headers in Swift. I have tried for days to prevent the labels and images inside of the section headers from duplicating. Basically on scroll the labels/images inside the headers duplicate and lay on top of each other.
Would someone please for the love of god explain to me why this is happening and how to fix it.
The circular image keeps creating images and laying them on top of the previous, the same with the name and date labels!!
Here is my ViewController:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var navigationBar: UINavigationItem!
#IBOutlet weak var tableView: UITableView!
var list = []
var audioPlayer:AVAudioPlayer!
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getListBro() -> NSArray {
return list
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.dataSource = self;
tableView.delegate = self;
self.tableView.rowHeight = UITableViewAutomaticDimension
let streamURL = NSURL(string: "http://192.241.174.8:8000/beat-stream-all/")!
let stuff = GetBeatStream(url:streamURL)
self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 50.0; //
stuff.downloadJSONFromURL {
(let jsonDictionary) in
if let jsonList = jsonDictionary["results"] as? NSArray {
self.list = jsonList
}
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// do some task
dispatch_async(dispatch_get_main_queue()) {
// update some UI
self.tableView.reloadData()
}
}
}
}//end view did load
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("streamCell", forIndexPath: indexPath) as! StreamTableViewCell
cell.beatCover.image = UIImage(named: "imgres")
if let id = list[indexPath.section] as? NSDictionary {
if let beatID = id["id"] as? NSInteger {
cell.setID(beatID)
}
}
if let beat_cover = list[indexPath.section] as? NSDictionary {
if let beat_cover_image = beat_cover["beat_cover"] as? String {
cell.beatCover.downloadImageFrom(link: beat_cover_image, contentMode: UIViewContentMode.ScaleToFill) //set your image from link array.
}
}
if let audio = list[indexPath.section] as? NSDictionary {
if let audio_url = audio["audio"] as? String {
cell.url = audio_url
cell.buildPlayer()
}
}
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return list.count
}
func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let beatAuthorLabel = UILabel(frame: CGRectMake(55, 5, 200, 40))
//USER PIC
let profilePictureImageView = UIImageView(frame: CGRectMake(5, 5, 40, 40));
profilePictureImageView.layer.borderWidth = 0
profilePictureImageView.layer.masksToBounds = false
profilePictureImageView.layer.borderColor = UIColor.blackColor().CGColor
profilePictureImageView.layer.cornerRadius = profilePictureImageView.frame.height/2
profilePictureImageView.clipsToBounds = true
profilePictureImageView.layer.masksToBounds = true
profilePictureImageView.image = UIImage(named: "imgres") //set placeholder image first.
if let userPicSection = list[section] as? NSDictionary {
if let artist = userPicSection["artist"] as? NSDictionary {
if let profilePic = artist["profile_pic"] as? String {
profilePictureImageView.downloadImageFrom(link: profilePic, contentMode: UIViewContentMode.ScaleAspectFit)
}
}
}
if let nameSection = list[section] as? NSDictionary {
if let name = nameSection["artist"] as? NSDictionary {
if let adminName = name["admin_name"] as? NSString {
print(adminName)
beatAuthorLabel.text = adminName as String
beatAuthorLabel.font = UIFont(name: beatAuthorLabel.font.fontName, size: 14)
}
}
}
var dateLabel = UILabel(frame: CGRectMake(225, 5, 200, 40))
if let created = list[section] as? NSDictionary {
if let date = created["created_at"] as? String {
dateLabel.text = date as String
dateLabel.font = UIFont(name: dateLabel.font.fontName, size: 8)
}
}
let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
header.contentView.addSubview(beatAuthorLabel)
header.contentView.addSubview(dateLabel)
header.contentView.addSubview(dateLabel)
header.contentView.addSubview(profilePictureImageView)
header.contentView.backgroundColor = UIColor(red: 179/255, green: 194/255, blue: 191/255, alpha:1)
header.textLabel!.textColor = UIColor.whiteColor()
header.alpha = 1
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = tableView.indexPathForSelectedRow
let currentCell = tableView.cellForRowAtIndexPath(indexPath!)! as! StreamTableViewCell
currentCell.player.play()
}
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let leavingCell = cell as! StreamTableViewCell
leavingCell.player.pause()
}
}
Header views, like cells, are reused. So, when the table view sends you tableView(_:willDisplayHeaderView:), it might not be the first time you've received that message for that header view. Yet every time you receive the message, you add four subviews to it.
Don't implement tableView(_:willDisplayHeaderView:forSection:) at all.
Instead, make a subclass of UITableViewHeaderFooterView with properties for the different subviews. This is just like how you created a subclass of UITableViewCell named StreamTableViewCell. Maybe you could call your header subview class StreamSectionHeaderView. Then you have two options for setting up the header view's subviews.
Option 1: In StreamSectionHeaderView.initWithFrame(_:), create the subviews of the header view (and store them in the instance properties and add them as subviews). This is essentially what you're doing now in tableView(_:willDisplayHeaderView:forSection:), but you would move most of the code into the StreamSectionHeaderView class. Register the StreamSectionHeaderView class with the table view using UITableView.registerClass(_:forHeaderFooterViewReuseIdentifier:).
Option 2: Design the header view and its subviews in a XIB (you can't do it in a storyboard), connect the subviews to the StreamSectionHeaderView properties (which must be IBOutlets in this case), and register the XIB in the table view with UITableView.registerNib(_:forHeaderFooterViewReuseIdentifier:).
To produce section, implement tableView(_:viewForHeaderInSection:) by calling tableView.
dequeueReusableHeaderFooterViewWithIdentifier(_:) and then configuring the header view's subviews, which already exist by the time dequeueReusableHeaderFooterViewWithIdentifier(_:) returns.
UPDATE
Here's your StreamSectionHeaderView, assuming you want to set up its subviews in code:
class StreamSectionHeaderView: UITableViewHeaderFooterView {
// Make these IBOutlets if you design StreamSectionHeaderView in a XIB.
var beatAuthorLabel = UILabel(frame: CGRectMake(55, 5, 200, 40))
var profilePictureImageView = UIImageView(frame: CGRectMake(5, 5, 40, 40))
var dateLabel = UILabel(frame: CGRectMake(225, 5, 200, 40))
init(frame: CGRect) {
profilePictureImageView.layer.borderWidth = 0
profilePictureImageView.layer.masksToBounds = false
profilePictureImageView.layer.borderColor = UIColor.blackColor().CGColor
profilePictureImageView.layer.cornerRadius = profilePictureImageView.frame.height/2
profilePictureImageView.clipsToBounds = true
profilePictureImageView.layer.masksToBounds = true
profilePictureImageView.image = UIImage(named: "imgres")
beatAuthorLabel.font = UIFont(name: beatAuthorLabel.font.fontName, size: 14)
dateLabel.font = UIFont(name: dateLabel.font.fontName, size: 8)
contentView.addSubview(beatAuthorLabel)
contentView.addSubview(dateLabel)
contentView.addSubview(profilePictureImageView)
contentView.backgroundColor = UIColor(red: 179/255, green: 194/255, blue: 191/255, alpha:1)
textLabel!.textColor = UIColor.whiteColor()
alpha = 1
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
Then, in your table view controller:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
// blah blah blah other stuff
tableView.registerClass(StreamSectionHeaderView.self, forHeaderFooterViewReuseIdentifier: "Header")
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableHeaderFooterViewWithIdentifier("Header") as! StreamSectionHeaderView
if let userPicSection = list[section] as? NSDictionary {
if let artist = userPicSection["artist"] as? NSDictionary {
if let profilePic = artist["profile_pic"] as? String {
header.profilePictureImageView.downloadImageFrom(link: profilePic, contentMode: UIViewContentMode.ScaleAspectFit)
}
}
}
if let nameSection = list[section] as? NSDictionary {
if let name = nameSection["artist"] as? NSDictionary {
if let adminName = name["admin_name"] as? NSString {
print(adminName)
header.beatAuthorLabel.text = adminName as String
}
}
}
if let created = list[section] as? NSDictionary {
if let date = created["created_at"] as? String {
header.dateLabel.text = date as String
}
}
return header
}
}

Resources