Custom UITableViewCell does not conform to protocol UITableViewDataSource? - ios

I followed this post and put inside my custom UITableViewCell SummaryCell the UITableView detailTableView
But now I'm getting the error:
Type 'SummaryCell` does not conform to protocol `UITableViewDataSource`
If anyone could tell what I'm doing wrong & how to fix this I would greatly appreciate it!
Code for SummmaryCell:
class SummaryCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var dayOfWeek: UILabel!
#IBOutlet weak var totalSpent: UILabel!
#IBOutlet weak var totalSpentView: UIView!
#IBOutlet weak var heightOfMainView: NSLayoutConstraint!
#IBOutlet weak var detailTableView: UITableView!
var data: [Expense] = [Expense]()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
detailTableView.delegate = self
detailTableView.dataSource = self
//create data array
let calendar = NSCalendar.currentCalendar()
let dateComponents = NSDateComponents()
dateComponents.day = 14
dateComponents.month = 5
dateComponents.year = 2015
dateComponents.hour = 19
dateComponents.minute = 30
let date = calendar.dateFromComponents(dateComponents)
data = [Expense(amountSpent: 60), Expense(amountSpent: 20, date: date!), Expense(amountSpent: 40, date: date!, function: Function.Social, category: Category.Fun, subcategory: Subcategory.Events)]
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("detailCell") as! DetailTableViewCell
return cell
}
}
What my summaryCell looks like :

It is generally considered bad practice to make your UITableViewCell class conform to the UITableViewDataSource and UITableViewDelegate protocols.
I would strongly recommend to set these both to a view controller containing a table view and could imagine that this probably causes your error.

To follow up to return false's answer, a cell should only be responsible for its own views. It shouldn't have a property for its tableView. It's generally a bad design for the cell to need to know or control anything about a view in its superview hierarchy.
Also if you consider the unlikely possibility that the reusable cell that happened to be the delegate were to be deinitialized, the tableView would no longer have a delegate.

Related

Can't pass data via segue

I make app with news feed which has to open on other ViewController. But can't pass data via segue.
Viewcontroller with newsfeed
class SecondViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var titlenews = ""
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "newsfeedCell", for: indexPath) as! NewsFeedCell
cell.newsfeed_title.text = self.news?[indexPath.item].headline
cell.newsfeed_topic.text = self.news?[indexPath.item].topic
cell.newsfeed_time.text = timetime(from: (self.news?[indexPath.item].time)!)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("tableview")
let vc = storyboard?.instantiateViewController(withIdentifier: "newsBody") as? NewsBody
vc?.labeltext = (self.news?[indexPath.item].headline)!
print((self.news?[indexPath.item].headline)!)
self.navigationController?.pushViewController(vc!, animated: true)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.news!.count
} //number of rows
#IBOutlet weak var tableview: UITableView!
var news: [Newsfeed]? = []
override func viewDidLoad() {
super.viewDidLoad()
getJSON()
}
func getJSON(){
///Here all do right
}
}
Viewcontroller which has to receive data from news feed
class NewsBody: UIViewController {
#IBOutlet weak var testLabel: UILabel!
var labeltext = ""
override func viewDidLoad() {
super.viewDidLoad()
print(labeltext)
testLabel.text = labeltext
}
}
print(labeltext) shows that NewsBody receive empty value or nothing.
But print((self.news?[indexPath.item].headline)!) inside of SecondViewController shows that I try to push proper value.
What I do incorrect between this actions? What wrong with segue and pass of data?
It seems that instantiateViewController(withIdentifier: "newsBody") triggers view load under the hood. It should not (in theory) but it might do just that in your case.
This means that viewDidLoad() will be called before the vc?.labeltext = (self.news?[indexPath.item].headline)! is executed.
I'd recommend you to do the following.
class NewsBody: UIViewController {
#IBOutlet weak var testLabel: UILabel!
var labeltext: String? {
didSet { updateUI() }
}
override func viewDidLoad() {
super.viewDidLoad()
updateUI()
}
private func updateUI() {
testLabel.text = labeltext
}
}
This way if you set the labeltext property after the view is loaded, it will still trigger the UI update. And if you set the labeltext property before the view is loaded, as soon as viewDidLoad() is called.
BTW, you are not using segues here. But even if you do, you can easily use the same method as I proposed, because it allows you to stop thinking about whether property updates will update the UI.
Also please note that I made the property optional. It will allow you to avoid force casts and just do
vc?.labeltext = self.news?[indexPath.item].headline
UILabel.text is also an optional String property, so they will play well together.

Swift -> my prototype cell (UITableViewCell) doesn't show in my UIViewController with a UITableView

My storyboard looks like this
and my code is the following
UIViewController
class DownLoadSoundsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
// MARK: View Controller Properties
let viewName = "DownLoadSoundsViewController"
#IBOutlet weak var visualEffectView: UIVisualEffectView!
#IBOutlet weak var dismissButton: UIButton!
#IBOutlet weak var downloadTableView: UITableView!
// MARK: Properties
var soundPacks = [SoundPack?]() // structure for downloadable sounds
override func viewDidLoad() {
super.viewDidLoad()
downloadTableView.dataSource = self
downloadTableView.delegate = self
downloadTableView.register(DownLoadTableViewCell.self, forCellReuseIdentifier: "cell")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberOfSoundPacks
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let method = "tableView.cellForRowAt"
//if (indexPath as NSIndexPath).section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "downloadTableViewCell", for: indexPath) as! DownLoadTableViewCell
cell.backgroundColor = UIColor.green
if soundPacks[(indexPath as NSIndexPath).row]?.price == 0 {
cell.soundPackPriceUILabel.text = "FREE"
} else {
cell.soundPackPriceUILabel.text = String(format: "%.2", (soundPacks[(indexPath as NSIndexPath).row]?.price)!)
}
//cell.textLabel?.text = soundPacks[(indexPath as NSIndexPath).row]?.soundPackTitle
cell.soundPackTitleUILabel.text = soundPacks[(indexPath as NSIndexPath).row]?.soundPackTitle
cell.soundPackAuthorUILabel.text = soundPacks[(indexPath as NSIndexPath).row]?.author
cell.soundPackShortDescription.text = soundPacks[(indexPath as NSIndexPath).row]?.shortDescription
cell.soundPackImage.image = UIImage(named: "Placeholder Icon")
DDLogDebug("\(viewName).\(method): table section \((indexPath as NSIndexPath).section) row \((indexPath as NSIndexPath).row))")
return cell
//}
}
UItableViewCell
class DownLoadTableViewCell: UITableViewCell {
#IBOutlet weak var soundPackImage: UIImageView!
#IBOutlet weak var soundPackTitleUILabel: UILabel!
#IBOutlet weak var soundPackAuthorUILabel: UILabel!
#IBOutlet weak var soundPackShortDescription: UILabel!
#IBOutlet weak var soundPackPriceUILabel: UILabel!
let gradientLayer = CAGradientLayer()
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
}
}
But I get the following;
I am sure I am doing something small incorrectly, but as of yet can't figure it out. Looked through many examples included my own code where I have gotten this working before.
Not a single one of my settings for the tableview are getting invoked except the number of cells. But everything in;
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{...}
is not working.
Help is appreciated.
I think you need to reload the tableView after getting data from Firebase
self.saveMixesTableView.reloadData()

Custom Cell Labels in UITableView Does Not Populate

On my storyboard is a Tab Bar Controller with two view controllers. The first view controller has a UITableView, and the second view controller is used to collect data which will be displayed in table view format on the first view controller.
For this, I have created four swift files:
TARISKTREATMENT.swift - contains the class TARISKTREATMENT that's linked to the first view controller (the one with the UITableView)
TAADDRISKTREATMENT.swift - contains the class TAADDRISKTREATMENT that's linked to the second view controller.
TREATMENTS.swift - Struct that's used to collect data entered on second view controller.
CUSTOMTREATMENTCELL.swift - UITableViewCell class for the custom cell.
The second view controller collects the data from the user perfectly, and when I run print commands, I can see that the data is actually in the struct.
For some reason, the code from TARISKTREATMENT.swift does not populate the custom cell.
What am I doing wrong here?
CODE: TARISKTREATMENT.swift (View controller 1 with UITableView - the one that's not working...)
import UIKit
class TARISKTREATMENT: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var TreatmentsTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
TreatmentsTableView.dataSource = self
TreatmentsTableView.delegate = self
TreatmentsTableView.reloadData()
}//END - viewDidLoad
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TreatmentsManager.newTreatments.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let IndividualCell = TreatmentsTableView.dequeueReusableCellWithIdentifier("TreatmentCell", forIndexPath: indexPath) as! CUSTOMTREATMENTCELL
IndividualCell.outletLabel_TreatmentPackageName.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPackageName
IndividualCell.outletLabel_TreatmentDescription.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPackageDetail
IndividualCell.outletLabel_TreatmentResponsiblePerson.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentResponsiblePerson
IndividualCell.outletLabel_TreatmentDTGCompleted.text = String(TreatmentsManager.newTreatments[indexPath.row].varTreatmentDTGCompleted)
let varSelectPriorityPic = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPriority
switch varSelectPriorityPic {
case "HIGH":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityHigh
case "MEDIUM":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityMedium
case "LOW":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityLow
default:
break
}
return IndividualCell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
if (editingStyle == UITableViewCellEditingStyle.Delete){
TreatmentsManager.newTreatments.removeAtIndex(indexPath.row)
TreatmentsTableView.reloadData()
}
}
}
CODE: TREATMENTS.swift
import UIKit
var TreatmentsManager: classTreatmentsManager = classTreatmentsManager()
struct structTreatment {
var varTreatmentPackageName : String
var varTreatmentPackageDetail : String
var varTreatmentResponsiblePerson : String
var varTreatmentPriority : String
var varTreatmentDTGCompleted : NSDate
}
class classTreatmentsManager: NSObject {
var newTreatments = [structTreatment]()
func funcAddTreatment(varTreatmentPackageName: String, varTreatmentPackageDetail: String, varTreatmentResponsiblePerson: String, varTreatmentPriority: String, varTreatmentDTGCompleted: NSDate){
newTreatments.append(structTreatment(varTreatmentPackageName: varTreatmentPackageName, varTreatmentPackageDetail: varTreatmentPackageDetail, varTreatmentResponsiblePerson: varTreatmentResponsiblePerson, varTreatmentPriority: varTreatmentPriority, varTreatmentDTGCompleted: varTreatmentDTGCompleted))
}
}
CODE: CUSTOMTREATMENTCELL.swift
import UIKit
class CUSTOMTREATMENTCELL: UITableViewCell {
#IBOutlet weak var outletImage_TreatmentPriority: UIImageView!
#IBOutlet weak var outletLabel_TreatmentPackageName: UILabel!
#IBOutlet weak var outletLabel_TreatmentDescription: UILabel!
#IBOutlet weak var outletLabel_TreatmentResponsiblePerson: UILabel!
#IBOutlet weak var outletLabel_TreatmentDTGCompleted: UILabel!
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 uploaded a small video to show what's (not) happening here.
Your assistance is appreciated - thanks!
Everything is fine in your code. What you miss is reloading the data :
override func viewWillAppear() {
super.viewWillAppear()
TreatmentsTableView.reloadData()
}

iOS Swift Dequeued Reusable Cell not showing up

I followed a tutorial earlier to get the basics of the Storyboard down and I'm using that code as a reference to write the app I'm working on. I want to test my prototype cell layout, but even though I set a value to the array at viewDidLoad it still refuses to show anything.
import UIKit
class DetailViewController: UIViewController {
var cards = [Card]()
#IBOutlet weak var cardsTableView: UITableView!
#IBOutlet weak var detailDescriptionLabel: UILabel!
var detailItem: AnyObject? {
didSet {
// Update the view.
self.configureView()
}
}
func configureView() {
// Update the user interface for the detail item.
if let detail: AnyObject = self.detailItem {
if let label = self.detailDescriptionLabel {
label.text = detail.description
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cards.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//példányosítunk egy cellát
let cell = tableView.dequeueReusableCellWithIdentifier("CardCell", forIndexPath: indexPath) as CardCell
//kivesszük a sor adatait a listából
let card : Card = self.cards[indexPath.row]
cell.setCardNumber(card.number)
cell.layer.cornerRadius = 8
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
self.cards = [Card(number: 123456789,type: 1)]
dispatch_async(dispatch_get_main_queue(), {
self.cardsTableView.reloadData()
})
self.configureView()
}
}
I started from a Master-Detail structure and I set the class of the Detail Scene to DetailViewController and the class and identifier of the Prototype to CardCell
class Card{
let number: Int
let type: Int
init(number: Int, type: Int){
self.number = number
self.type = type
}
}
import UIKit
class CardCell: UITableViewCell {
#IBOutlet weak var cardNumber: UILabel!
func setCardNumber(number: Int){
cardNumber.text = String(number)
}
}
I'm sure it's something basic, but I've been messing with this for the second day now. Any suggestions are appreciated.
you have to set the dataSource for the table view, i guess the delegate methods get never called.
Additionally add UITableViewDataSource, not necessary but more declarative than just the implementation
class DetailViewController: UIViewController, UITableViewDataSource {

Changing table from tableviewcontroller to regular view controller

Sorry if this kind of question isn't welcome here but I'd appreciate the help. I have a fully functioning table now set up but I did it using the TableViewController in storyboard. I now realize I cannot change the size of the view using that item and it doesn't fit well on the screen as is. I understand I need to use a regular view controller and add the table view manually. I can do that but I spent hours getting the table to work properly and I'm afraid to break it. Can someone walk me through transitioning between the two?
Here is the storyboard
Here is the view controller code
import UIKit
class CharacterTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var characterTableView: UITableView!
var characterArray: [Character] = [Character]()
override func viewDidLoad() {
super.viewDidLoad()
self.characterSetup()
}
func characterSetup() {
var admiralSwiggins = Character(name: "Admiral Swiggins", abilities: "Stun, Blind, Shield, Damage Over Time, Area of Effect", characterImage: "admiral.png")
var ayla = Character(name: "Ayla", abilities: "Area of Effect, Damage Over Time, Fly, Lifesteal, Shield, Slow", characterImage: "ayla.png")
var clunk = Character(name: "Clunk", abilities: "Lifesteal, Area of effect, Ensnare, Slow, Launch String", characterImage: "clunk.png")
characterArray.append(admiralSwiggins)
characterArray.append(ayla)
characterArray.append(clunk)
}
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell:CharacterTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("Cell") as CharacterTableViewCell
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor.redColor()
}
let character = characterArray[indexPath.row]
cell.nameLabel.text = character.name
cell.abilityLabel.text = character.abilities
cell.characterImage.image = UIImage(named: character.characterImage)
return cell
}
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
}
}
And here is the cell
import UIKit
class CharacterTableViewCell: UITableViewCell {
#IBOutlet var nameLabel: UILabel!
#IBOutlet var abilityLabel: UILabel!
#IBOutlet var characterImage: UIImageView!
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
}
}

Resources