Tableview disappears when scrolling - ios

I have a tableView that displays hidden cells when the user scrolls. Not sure why this behavior is happening.
In viewDidLoad()
watchListTable = UITableView(frame: CGRect(x: self.view.frame.width * 0.25, y: 0, width: self.view.frame.width * 0.75, height: 300)) //height = 200
watchListTable.isHidden = true
watchListTableFrame = CGRect(x: self.view.frame.width * 0.25, y: 0, width: self.view.frame.width * 0.75, height: 300)
watchListTableFrameHide = CGRect(x: self.view.frame.width * 0.25, y: 0, width: self.view.frame.width * 0.75, height: 0)
watchListTable.register(UITableViewCell.self, forCellReuseIdentifier: "MyCell")
watchListTable.register(UITableViewCell.self, forCellReuseIdentifier: "closeCell")
watchListTable.dataSource = self
watchListTable.delegate = self
watchListTable.CheckInterfaceStyle()
watchListTable.roundCorners(corners: .allCorners, radius: 8)
watchListTable.backgroundColor = .systemGray6
//remove the bottom line if there is only one option
watchListTable.tableFooterView = UIView()
view.addSubview(watchListTable)
Once the user taps on a button, the table expands in an animatable fashion.
//watchlist won't animate properly on the initial setup. So we set it to be
hidden, then change the frame to be 0, unhide it, and then animate it. Only will
be hidden on the initial setup.
if(watchListTable.isHidden == true)
{
watchListTable.isHidden = false
watchListTable.frame = watchListTableFrameHide
}
UIView().animateDropDown(dropDown: watchListTable, frames:
self.watchListTableFrame)
watchListTable.reloadData()
In func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
if(indexPath.row >= watchListStocks.count)
{
let cell = tableView.dequeueReusableCell(withIdentifier: "closeCell",
for: indexPath as IndexPath)
cell.selectionStyle = .none
cell.textLabel?.text = indexPath.row == watchListStocks.count + 1 ?
"Close List" : "Create New Watchlist"
cell.textLabel?.textColor = .stockOrbitTeal
cell.textLabel?.textAlignment = .center
cell.backgroundColor = .systemGray6
cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right:
.greatestFiniteMagnitude)
return cell
}
else
{
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for:
indexPath as IndexPath)
cell.selectionStyle = .none
if(indexPath.row == 0)
{
cell.layer.cornerRadius = 8
cell.layer.maskedCorners = [.layerMinXMinYCorner,
.layerMaxXMinYCorner]
}
else
{
cell.layer.cornerRadius = 8
cell.layer.maskedCorners = [.layerMinXMaxYCorner,
.layerMaxXMaxYCorner]
cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right:
.greatestFiniteMagnitude)
cell.directionalLayoutMargins = .zero
}
let label = UITextView()
label.frame = CGRect(x: 0, y: 0, width: cell.frame.width * 0.45, height:
cell.frame.height)
label.text = watchListStocks[indexPath.row].listName
label.textColor = .stockOrbitTeal
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.medium)
label.backgroundColor = .systemGray5
label.delegate = self
label.tag = indexPath.row
cell.addSubview(label)
cell.backgroundColor = .systemGray5
cell.layer.cornerRadius = 8
return cell
}
When I scroll, all cells are hidden. I see that they are created in cellForRowAt, however, they do not appear on my screen. Why are the cells being hidden? I have searched all over stackoverflow.

You shouldn't add subviews inside cellForRowAt. When you call dequeueReusableCell, at first it'll create new cells, but when you start scrolling it'll start returning cells that were dismissed earlier, means they already have UITextView subview, and you're adding one more on top of that.
cell returned by dequeueReusableCell doesn't have to have final size already, that's why you can't use cell.frame.width to calculate your subview size, I think that's may be the reason you can't see it.
What you need to do: create a UITableView subclass, something like this:
class MyCell: UITableViewCell {
let label = UITextView()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupCell()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupCell()
}
func setupCell() {
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.medium)
label.backgroundColor = .systemGray5
contentView.addSubview(label)
}
override func layoutSubviews() {
super.layoutSubviews()
label.frame = CGRect(x: 0, y: 0, width: contentView.frame.width * 0.45, height: contentView.frame.height)
}
}
Here you're adding a subview during initialisation only once and update label frame each time cell size gets changed. Don't forget to add this class to your cell in the storyboard and let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath as IndexPath) as! MyCell, so you can set delegate to text field, etc.
If this won't help, check out View Hierarchy to see what's actually going on there

So after many hours, I figured it out...
I had called this function in viewDidLoad()
watchListTable.roundCorners(corners: .allCorners, radius: 8)
Which made my table hidden after I scrolled. I removed this line of code, and the table is now completely visible when scrolling.

Related

Swift - Data not displayed properly when using tableView.dequeueReusableCell

When certain buttons are pressed in the app, their name, start and end time that they were pressed are displayed in a UITableView.
This worked fine when using a custom UITableViewCell but after setting up tableView.dequeueReusableCell instead, the UITableView is showing the first cell as a white empty cell when it is meant to show data. If more data is added, the first input which wasn't visible is now shown but the last input is missing/hidden.
I have found similar questions and implemented what seemed the main culprit but it didn't work for me.
timelineTableView.contentInsetAdjustmentBehavior = .never
timelineScrollViewContainer.contentInsetAdjustmentBehavior = .never
timelineTableView.contentOffset = .zero
I also tried to change the section height but to no avail either.
Worth mentioning that the data is not displaying properly in the UITableView but is still saving properly in the plist.
The UITableView is loaded during the ViewDidLoad as mentioned in other questions as it seems the issue of the error for some.
Doeanyonene have another solution? thanks for the help
cellForRowAt method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == timelineTableView {
//let cell = TimelineCell(frame: CGRect(x: 0, y: 0, width: 100, height: 40), title: "test", startTime: "test", endTime: "test", rawStart: "") // Used previously before using dequeueReusableCell
var cell: TimelineCell = tableView.dequeueReusableCell(withIdentifier: timelineCellId, for: indexPath) as! TimelineCell
if let marker = markUpPlist.arrayObjects.filter({$0.UUIDpic == endClipSelectedMarkerUUID}).first {
cell = TimelineCell(frame: CGRect(x: 0, y: 0, width: 100, height: 40), title: "test", startTime: "test", endTime: "test", rawStart: "")
cell.backgroundColor = marker.colour
cell.cellLabelTitle.text = marker.name
cell.cellUUID.text = marker.UUIDpic
if let timeline = chronData.rows.filter({$0.rowName == marker.name}).first {
if let start = timeline.clips.last?.str {
cell.cellStartTime.text = chronTimeEdited(time: Double(start))
cell.cellStartRaw.text = String(start)
}
if let end = timeline.clips.last?.end {
cell.cellEndTime.text = chronTimeEdited(time: Double(end))
}
}
}
return cell
}
TimelineCell.swift
class TimelineCell : UITableViewCell {
var cellLabelTitle: UILabel!
var cellStartTime: UILabel!
var cellEndTime: UILabel!
var cellStartRaw: UILabel!
var cellUUID: UILabel!
init(frame: CGRect, title: String , startTime: String, endTime: String, rawStart: String) {
super.init(style: UITableViewCell.CellStyle.default, reuseIdentifier: "timelineCellId")
backgroundColor = UIColor(red: 29/255.0, green: 30/255.0, blue: 33/255.0, alpha: 1.0)
cellLabelTitle = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
cellLabelTitle.translatesAutoresizingMaskIntoConstraints = false
cellLabelTitle.textColor = UIColor.black
addSubview(cellLabelTitle)
cellLabelTitle.widthAnchor.constraint(equalToConstant: 80).isActive = true
cellLabelTitle.heightAnchor.constraint(equalToConstant: 30).isActive = true
cellLabelTitle.centerYAnchor.constraint(equalTo: self.centerYAnchor, constant: 0).isActive = true
cellLabelTitle.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
cellStartTime = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
cellStartTime.translatesAutoresizingMaskIntoConstraints = false
cellStartTime.textColor = UIColor.black
addSubview(cellStartTime)
cellStartTime.widthAnchor.constraint(equalToConstant: 80).isActive = true
cellStartTime.heightAnchor.constraint(equalToConstant: 30).isActive = true
cellStartTime.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0).isActive = true
cellStartTime.leftAnchor.constraint(equalTo: cellLabelTitle.rightAnchor, constant: 10).isActive = true
cellEndTime = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
cellEndTime.translatesAutoresizingMaskIntoConstraints = false
cellEndTime.textColor = UIColor.black
addSubview(cellEndTime)
cellEndTime.widthAnchor.constraint(equalToConstant: 80).isActive = true
cellEndTime.heightAnchor.constraint(equalToConstant: 30).isActive = true
cellEndTime.centerYAnchor.constraint(equalTo: centerYAnchor, constant: 0).isActive = true
cellEndTime.leftAnchor.constraint(equalTo: cellStartTime.rightAnchor, constant: 10).isActive = true
cellStartRaw = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
cellUUID = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
addSubview(cellStartRaw)
addSubview(cellUUID)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
}
Create tableview
timelineTableView.frame = CGRect(x: 0, y: 0, width: sideView.frame.width, height: sideView.frame.size.height)
timelineTableView.delegate = self
timelineTableView.dataSource = self
timelineTableView.register(TimelineCell.self, forCellReuseIdentifier: timelineCellId)
timelineTableView.translatesAutoresizingMaskIntoConstraints = false
timelineTableView.separatorStyle = .none
timelineTableView.backgroundColor = Style.BackgroundColor
timelineTableView.contentInsetAdjustmentBehavior = .never
timelineScrollViewContainer.contentInsetAdjustmentBehavior = .never
timelineScrollViewContainer.addSubview(timelineTableView)
timelineTableView.contentOffset = .zero
So recapitulating, using the line below shows the data properly but the cells aren't reused properly.
let cell = TimelineCell(frame: CGRect(x: 0, y: 0, width: 100, height: 40), title: "test", startTime: "test", endTime: "test", rawStart: "")
Using the code below show a blank cell first and data not displayed properly but the cells are reused properly.
var cell: TimelineCell = tableView.dequeueReusableCell(withIdentifier: timelineCellId, for: indexPath) as! TimelineCell
Change cellForRowAt to look like this. I'm guessing as to how your chronData structure relates to the source table, so it's mostly using your original logic.
You need to blank out fields that should be empty, as otherwise they will retain state as you scroll.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell: TimelineCell = tableView.dequeueReusableCell(withIdentifier: timelineCellId, for: indexPath) as! TimelineCell
let marker = markUpPListFiltered
cell.backgroundColor = marker.colour
cell.cellLabelTitle.text = marker.name
cell.cellUUID.text = marker.UUIDpic
if let timeline = chronData.rows.filter({$0.rowName == marker.name}).first {
if let start = timeline.clips.last?.str {
cell.cellStartTime.text = chronTimeEdited(time: Double(start))
cell.cellStartRaw.text = String(start)
}
else
{
cell.cellStartTime.text = ""
cell.cellStartRaw.text = ""
}
if let end = timeline.clips.last?.end {
cell.cellEndTime.text = chronTimeEdited(time: Double(end))
}
else
{
cell.cellEndTime.text = ""
}
}
return cell
}
It assumes there is an array for your filtered sorted data called markupPListFiltered. Prepare this in viewDidLoad or somewhere else. You haven't shown the other datasource methods so I'll assume you can change these as needed, e.g.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return markupPListFiltered.count
}
TimelineCell needs the c'tor to have the data removed. You should consider using a storyboard to design your cells and link up the widgets with the outlets (see any of the hundreds of tutorials on table views, I'd recommend Ray Wenderlich as a good starter source).

How do I add subviews to a custom UICollectionViewCell

I have a custom UICollectionViewCell class where I want to add subviews.
My cell class: The SetUpView() method will add all the subvies I need.
import Foundation
import UIKit
class RecipeCell: UICollectionViewCell {
var RecipeImg: UIImage!
var StarRatingImg: UIImage!
var RecipeTitleText = ""
var RecipeTextDescription = ""
var View: UIView!
var ImageContainer: UIImageView!
var FavIcon: UIImageView!
var StarRatingContainer: UIImageView!
var KCAL: UILabel!
var RecipeTitle: UITextView!
var RecipeText: UITextView!
func SetUpView()
{
//DropDown!.backgroundColor = UIColor.blueColor()
self.translatesAutoresizingMaskIntoConstraints = false
//View for recipe
View = UIView(frame: CGRectMake(0, 0, self.frame.width, self.frame.height))
View.backgroundColor = UIColor.whiteColor()
//Recipe image
ImageContainer = UIImageView(frame: CGRectMake(0, 0, View.frame.width, View.frame.height/2))
ImageContainer.image = RecipeImg
ImageContainer.contentMode = .ScaleToFill
//Recipe favorit icon
FavIcon = UIImageView(frame: CGRectMake(ImageContainer.frame.width - 35, 5, 30, 30))
FavIcon.image = UIImage(named: "LikeHeart")
//Star rating image
StarRatingContainer = UIImageView(frame: CGRectMake(10, ImageContainer.frame.height + 5, ImageContainer.frame.width - 20, (View.frame.height/2) * (1/5)))
StarRatingContainer.image = StarRatingImg
StarRatingContainer.contentMode = .ScaleAspectFit
//RecipeTitle container
RecipeTitle = UITextView(frame: CGRectMake(10, StarRatingContainer.frame.height + ImageContainer.frame.height + 10, View.frame.width - 20, 30))
RecipeTitle.font = UIFont(name: "OpenSans-Semibold", size: 12)
//RecipeTitle.backgroundColor = UIColor.redColor()
RecipeTitle.editable = false
RecipeTitle.text = RecipeTitleText
RecipeTitle.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
//RecipeText container
RecipeText = UITextView(frame: CGRectMake(10, StarRatingContainer.frame.height + ImageContainer.frame.height + RecipeTitle.frame.height + 15, View.frame.width - 20, 50))
RecipeText.font = UIFont(name: "OpenSans", size: 12)
//RecipeText.backgroundColor = UIColor.grayColor()
RecipeText.editable = false
RecipeText.text = RecipeTextDescription
RecipeText.textContainerInset = UIEdgeInsetsMake(0, 0, 0, 0)
//KCAL label
KCAL = UILabel(frame: CGRectMake(15, StarRatingContainer.frame.height + ImageContainer.frame.height + RecipeTitle.frame.height + RecipeText.frame.height + 20, 200, 20))
KCAL.text = "420 KCAL. PER. PORTION"
KCAL.font = UIFont(name: "OpenSans-Bold", size: 10)
KCAL.textColor = UIColor(CGColor: "#dc994a".CGColor)
//Adding the views
self.addSubview(View)
View.addSubview(ImageContainer)
View.addSubview(KCAL)
View.addSubview(StarRatingContainer)
View.addSubview(RecipeTitle)
View.addSubview(RecipeText)
ImageContainer.addSubview(FavIcon)
View.bringSubviewToFront(ImageContainer)
}
}
I have a UICollectionView which uses the custom cell class.
I create my UICollectionView in viewDidLoad()
// Create Collection view
layout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0)
layout.itemSize = CGSize(width: screenWidth/MenuViewConst - 1, height: screenWidth - 1)
layout.minimumInteritemSpacing = 1
layout.minimumLineSpacing = 1
collectionView = UICollectionView(frame: CGRect(x: 0, y: 105, width: self.view.frame.width, height: self.view.frame.height - 150), collectionViewLayout: layout)
collectionView?.tag = 5
collectionView!.dataSource = self
collectionView!.delegate = self
collectionView!.registerClass(RecipeCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
collectionView!.backgroundColor = UIColor.lightGrayColor()
collectionView!.contentInset.top = 0
In cellForItemAtIndexPath delegate I set up the UICollectionView to use my custom cell class. But I can't call the SetUpView() method from my custom cell class here, because that will just keep adding subviews on subviews. I can't figure out how to add the subviews to the UICollectionViewCell before entering the delegate. Hope you guys can help - Thank you
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as! RecipeCell
let recipe = self.RecipeArr[indexPath.row]
cell.backgroundColor = UIColor.grayColor()
cell.layer.borderColor = UIColor.whiteColor().CGColor
cell.layer.borderWidth = 0.5
cell.RecipeImg = UIImage(named: "Burger")
cell.StarRatingImg = UIImage(named: "StarRating")
cell.RecipeTitleText = recipe["name"].string!
cell.RecipeTextDescription = recipe["instruction"].string!
//BAD IDEA!
//cell.SetUpView()
print("new cell")
return cell
}
You need to use init(frame: CGRect) inherited function in the UICollectionViewCell .
class RecipeCell: UICollectionViewCell {
var imageView : UIImageView?
override init(frame: CGRect) {
super.init(frame: frame)
//initialize all your subviews.
imageView = UIImageView()
}
}
also don't forget to register your custom class in the viewDidLoad function
collectionView!.registerClass(RecipeCell.self, forCellWithReuseIdentifier: "CollectionViewCell")
and your collectionview delegate would be like this
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CollectionViewCell", forIndexPath: indexPath) as! RecipeCell
cell.imageView.image = UIImage(named:"yourImage.png")
}

UITableViewCell redrawing on scroll

I have a UITableView that contains cells with a slider and two labels, each time a slider goes out of view it appears to be drawn again on top of the current content.
Here is a gif explaining what I mean.
http://i.imgur.com/4dYtyJy.gifv
And here is the relevant code.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellIdentifier: String = "\(indexPath.row) - \(indexPath.section)"
var cell: UITableViewCell! = self.tableView.dequeueReusableCellWithIdentifier(CellIdentifier)
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: CellIdentifier)
}
let label = UILabel(frame: CGRect(x: 16.0, y: 16.0, width: 300, height: 30.0))
let percentageLabel = UILabel(frame: CGRect(x: 16.0, y: 0, width: 200.0, height: 30.0))
let slider = CustomUISlider(frame: CGRect(x: 16.0, y: 55.0, width: 300.0, height: 20.0))
slider.maximumTrackTintColor = Global().turqTint
slider.minimumTrackTintColor = Global().blueTint
slider.minimumValue = 0.0
slider.maximumValue = 1.0
slider.value = 0.0
slider.tag = indexPath.row
slider.setThumbImage(UIImage(named: "sliderThumbImage"), forState: .Normal)
slider.addTarget(self, action: "sliderValueChanged:", forControlEvents: .ValueChanged)
label.text = Array(selectedTypes)[indexPath.row].1
percentageLabel.text = "\(slider.value)"
percentageLabel.tag = indexPath.row
cell.tintColor = Global().tintColor
cell.addSubview(label)
cell.addSubview(slider)
cell.addSubview(percentageLabel)
return cell
}
I have had a similar problem. As Horst said in the comments, putting that snippet inside the block will do the trick:
if (cell == nil)
{
// Code that draws frames
}
If you insist to go with your way, you would like to have something more like
(Note: "\(indexPath.row) - \(indexPath.section)") this will create different CellIDs for every cell. What you would like to have is some common CellID to be able to benefit from the reuse logic of the TableView:
//Global constants for the View tags
let textLabelTag = 1
let percentageLabelTag = 2
let sliderTag = 3
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellIdentifier: String = "SomeUniqueID"
var cell: UITableViewCell! = self.tableView.dequeueReusableCellWithIdentifier(CellIdentifier)
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: CellIdentifier)
self.createUIforCell(cell);
}
self.configureCell(cell, indexPath: indexPath)
return cell
}
Create the UI components for the cell and add them as subviews. This method will be called only once if the cell doesn't exist:
func createUIforCell(cell: UITableViewCell) {
let textLabel = UILabel(frame: CGRect(x: 16.0, y: 16.0, width: 300, height: 30.0))
textLabel.tag = textLabelTag
cell.addSubview(textLabel)
let percentageLabel = UILabel(frame: CGRect(x: 16.0, y: 0, width: 200.0, height: 30.0))
percentageLabel.tag = percentageLabelTag
cell.addSubview(percentageLabel)
let slider = CustomUISlider(frame: CGRect(x: 16.0, y: 55.0, width: 300.0, height: 20.0))
slider.tag = sliderTag
slider.maximumTrackTintColor = Global().turqTint
slider.minimumTrackTintColor = Global().blueTint
slider.minimumValue = 0.0
slider.maximumValue = 1.0
slider.setThumbImage(UIImage(named: "sliderThumbImage"), forState: .Normal)
slider.addTarget(self, action: "sliderValueChanged:", forControlEvents: .ValueChanged)
cell.addSubview(slider)
}
Update the UI with the correct data:
func configureCell(cell: UITableViewCell, indexPath: NSIndexPath) {
let textLabel: UILabel = cell.viewWithTag(textLabelTag) as! UILabel
textLabel.text = Array(selectedTypes)[indexPath.row].1
let slider: CustomUISlider = cell.viewWithTag(sliderTag) as! CustomUISlider
slider.value = 0.0
let percentageLabel: UILabel = cell.viewWithTag(percentageLabelTag) as! UILabel
percentageLabel.text = "\(slider.value)"
}
Note: It'll be cleaner if you've your own UITableViewCell subclass where the UI to be created (either in the code or in .xib)
You should subclass UITableViewCell and override prepeareForReuse method. With it you can set your cell to default mode.
-(void)prepareForReuse {
[super prepareForReuse];
//Reset your cell here to default state.
}

Create Custom Dynamic Prototype Cells programmatically

I am having an issue trying to create Dynamic Prototype Cells programmatically. This is my first time trying this approach. I have always created them through storyboard.
I have my ViewController.swift file which contains the following
var noteListTableView: UITableView = UITableView()
noteListTableView.frame.origin.x = 0.0
noteListTableView.frame.origin.y = kNAV_BAR_HEIGHT
noteListTableView.frame.size.width = kDEVICE_WIDTH
noteListTableView.frame.size.height = kDEVICE_HEIGHT - kNAV_BAR_HEIGHT
noteListTableView.dataSource = self
noteListTableView.delegate = self
self.view.addSubview(noteListTableView)
Also in the file, I have included the appropriate TableView delegate and Data source functions
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return GlobalDataController.notesDB.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var aNote: NoteItem = GlobalDataController.notesDB[indexPath.row] as NoteItem
if var cell: NoteListTVCell = noteListTableView.dequeueReusableCellWithIdentifier(kReuseCellNoteList) as? NoteListTVCell {
cell.noteTitle.text = "Title"
cell.noteContentSummary.text = "Content Summary"
cell.noteDate.text = "May 20"
return cell
}
else{
var cell: NoteListTVCell = NoteListTVCell(style: UITableViewCellStyle.Default, reuseIdentifier: kReuseCellNoteList)
cell.noteTitle.text = "Title"
cell.noteContentSummary.text = "Content Summary"
cell.noteDate.text = "May 20"
return cell
}
}
(1) The IF-STATEMENT always seems to fail, that is why I added the else statement as per some example I found online for Obj-C.
(2) When the ELSE is triggered, the program always crashes trying to assign the cell.* values, saying it encountered a nil value.
EDIT: NoteListTVCell
class NoteListTVCell: UITableViewCell {
var noteTitle: UILabel!
var noteContentSummary: UILabel!
var noteDate: UILabel!
var cellMargin: CGFloat = kPadding * 3
override func awakeFromNib() {
super.awakeFromNib()
noteTitle = UILabel(frame: CGRect(x: cellMargin, y: kPadding, width: kDEVICE_WIDTH - cellMargin - kPadding, height: 30.0))
noteTitle.backgroundColor = kColorTransparent
noteTitle.font = UIFont(name: kFont02, size: 20.0)
noteTitle.textColor = Scripts.hexColor(0x000000, alpha: 0.8)
noteTitle.text = "Title"
self.addSubview(noteTitle)
/* Note Content Summary
-----------------------------------------------------------------------------------------*/
var noteContentSummaryY: CGFloat = noteTitle.frame.origin.y + noteTitle.frame.size.height
noteContentSummary = UILabel(frame: CGRect(x: cellMargin, y: noteContentSummaryY, width: kDEVICE_WIDTH - cellMargin - kPadding, height: 20.0))
noteContentSummary.backgroundColor = kColorTransparent
noteContentSummary.font = UIFont(name: kFont02, size: 14.0)
noteContentSummary.textColor = Scripts.hexColor(0x000000, alpha: 0.4)
noteContentSummary.text = "This is a summary..."
self.addSubview(noteContentSummary)
/* Note Date
-----------------------------------------------------------------------------------------*/
noteDate = UILabel(frame: CGRect(x: kDEVICE_WIDTH - 100.0 - kPaddingx2, y: kPadding, width: 100.0, height: 20.0))
noteDate.backgroundColor = kColorTransparent
noteDate.font = UIFont(name: kFont02, size: 10.0)
noteDate.textColor = Scripts.hexColor(kColorThemeBlue, alpha: 1.0)
noteDate.textAlignment = NSTextAlignment.Right
noteDate.text = "May 8, 2:14 AM"
self.addSubview(noteDate)
}
}
You haven't override the init method in your custom cell, but anyway it will call super init method, if you don't provide. Put your cell initialisation code in init method instead of awakeFromNib method.
Try this below.
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//Do your cell set up
noteTitle = UILabel(frame: CGRect(x: cellMargin, y: kPadding, width: kDEVICE_WIDTH - cellMargin - kPadding, height: 30.0))
noteTitle.backgroundColor = kColorTransparent
noteTitle.font = UIFont(name: kFont02, size: 20.0)
noteTitle.textColor = Scripts.hexColor(0x000000, alpha: 0.8)
noteTitle.text = "Title"
self.addSubview(noteTitle)
/* Note Content Summary
-----------------------------------------------------------------------------------------*/
var noteContentSummaryY: CGFloat = noteTitle.frame.origin.y + noteTitle.frame.size.height
noteContentSummary = UILabel(frame: CGRect(x: cellMargin, y: noteContentSummaryY, width: kDEVICE_WIDTH - cellMargin - kPadding, height: 20.0))
noteContentSummary.backgroundColor = kColorTransparent
noteContentSummary.font = UIFont(name: kFont02, size: 14.0)
noteContentSummary.textColor = Scripts.hexColor(0x000000, alpha: 0.4)
noteContentSummary.text = "This is a summary..."
self.addSubview(noteContentSummary)
/* Note Date
-----------------------------------------------------------------------------------------*/
noteDate = UILabel(frame: CGRect(x: kDEVICE_WIDTH - 100.0 - kPaddingx2, y: kPadding, width: 100.0, height: 20.0))
noteDate.backgroundColor = kColorTransparent
noteDate.font = UIFont(name: kFont02, size: 10.0)
noteDate.textColor = Scripts.hexColor(kColorThemeBlue, alpha: 1.0)
noteDate.textAlignment = NSTextAlignment.Right
noteDate.text = "May 8, 2:14 AM"
self.addSubview(noteDate)
}
Do this in viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
noteListTableView = UITableView(frame: self.view.frame, style: UITableViewStyle.Plain)
noteListTableView.dataSource = self
noteListTableView.delegate = self
self.view.addSubview(noteListTableView)
noteListTableView.registerClass(NoteListTVCellTableViewCell.self, forCellReuseIdentifier: kReuseCellNoteList)
// Do any additional setup after loading the view, typically from a nib.
}
You need to register your custom tableViewCell class in viewDidLoad:
notelistTableView.registerClass(NoteListTVCell.self, forCellReuseIdentifier: kReuseCellNoteList)
Documentation
When designing the prototype in InterfaceBuilder this is done automatically. It is required when you design your cell in code.

Custom UIImageView added to UItableview cell doesnot shift on on x-axis?

I am trying to give some margin on x-axis for a imageView that is set inside a tableView cell. But the imageView does not move. And I also tried same for a label. It does shift to the value I gave.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
// cell.textLabel?.font = UIFont(name: label.font.fontName, size: 22)
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("myCell") as UITableViewCell
// cell.imageView?.image = UIImage(named: self.cellImgs[indexPath.row])
cell.textLabel?.text = self.cellTxtArrs[indexPath.row]
cell.textLabel?.textAlignment = NSTextAlignment.Right
cell.textLabel?.textColor = UIColor.whiteColor()
cell.backgroundColor = UIColor(red: 0.000, green: 0.400, blue: 0.404, alpha: 1.00)
cell.selectionStyle = UITableViewCellSelectionStyle.None
// var videoImgView:UIImageView = UIImageView(frame: CGRectMake(50, 10, 20, 30.0))
// let videoImage = UIImage(named: "accounts")
// videoImgView = UIImageView(image: videoImage)
// cell.contentView.addSubview(videoImgView)
var newLabel = UILabel(frame: CGRectMake(80, 0, 80, 30.0))
newLabel.text = "hello all"
newLabel.textColor = UIColor.redColor()
cell.contentView.addSubview(newLabel)
return cell
}
I have created a table view as
var tblView : UITableView = UITableView()
tblView.frame = CGRectMake(0, 168, 320-50 , 448)
tblView.separatorColor = UIColor.clearColor()
tblView.scrollEnabled = false
tblView.rowHeight = 39
self.addSubview(tblView)
tblView.delegate = self
tblView.dataSource = self
tblView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "myCell")
1) your code will cell.contentView.addSubview everytime that cellForRowAtIndexPath is called. You are not reusing cell properly .
2) Subclass UITableViewCell and add your "logic View code" inside there (right place to do it)
3) look at this: http://www.objc.io/issue-1/lighter-view-controllers.html
Please try to use this one i hope it helps you.
videoImgView = UIImageView(image: videoImage)
videoImgView.frame = CGRectMake(100, 10, 20, 30.0)
cell.contentView.addSubview(videoImgView)

Resources