Why can I not cast this cell to a class that inherits from cell in swift? - ios

I am creating a TableView in swift using the UITableViewCOntroller, which I have done in several other apps, however this time when I try to cast my cell to the custom cell class I get the error that it cannot be cast.
Here is my code:
class CollapseNoteViewController: UITableViewController {
let titleArray = ["Troy and Abed", "Shirly and Annie", "Pierce and Ben"]
let noteArray = ["The best", "Pretty cool", "The worst"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titleArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// This is where I get the error
let cell = tableView.dequeueReusableCell(withIdentifier: K.reuseIdentifier, for: indexPath) as! NoteTableViewCell
cell.titleLabel?.text = titleArray[indexPath.row]
cell.textLabel?.text = noteArray[indexPath.row]
return cell
}
}
class NoteTableViewCell: UITableViewCell {
#IBOutlet weak var cardView: UIView!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var mainTextLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
}
The full error text:
Could not cast value of type 'UITableViewCell' (0x1eccdbb70) to 'CollapseANote.NoteTableViewCell' (0x104d3ced8).
Could not cast value of type 'UITableViewCell' (0x1eccdbb70) to 'CollapseANote.NoteTableViewCell' (0x104d3ced8).
2021-02-18 10:36:47.613801-0500 CollapseANote[639:74162] Could not cast value of type 'UITableViewCell' (0x1eccdbb70) to 'CollapseANote.NoteTableViewCell' (0x104d3ced8).
Where I set the class for the prototype cell:
Where I set the class for TableViewController:

You nest to table cells and set the class name to the inner one that's why ist's not visible here
Drag the inner one to out like
Then delete the NoteItemCell
It's up to you to leave it if it represents another different cell

Related

What can I do to access this Table View within a View Controller?

I have checked out the other posts but I'm not sure next steps here. Here's what I have currently. Do I need to add a tableView variable somewhere else? Connect something differently?
class LookbookPostViewController: UIViewController {
#IBOutlet weak var titleLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.text = postArray[myIndex].title
// Do any additional setup after loading the view.
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
#IBOutlet weak var tableView: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
return postArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "postViewCell", for: indexPath) as! LookbookPostViewCell
cell.postLabel.text = postArray[indexPath.row].title
print(postArray)
return cell
}
/
}
I then have this set up for my connections, but can't seem to get the Table View to recognize any data I'm trying to output.
I also have `class LookbookPostViewCell: UITableViewCell {
#IBOutlet weak var postLabel: UILabel!
}
`
I was able to solve this by changing:
class LookbookPostViewController: UIViewController
to
class LookbookPostViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
and then right clicking and making the delegate and datasource, the View Controller, like in this photo here.

Datepicker won't display in custom UITableViewCell class

I try to keep a separate custom cell class, but somehow the datepicker I dragged into it from storyboard refuses to show up after I ran it.
import UIKit
class eventViewController: UIViewController,UITextViewDelegate,UIScrollViewDelegate,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var timeTableView: UITableView!
#IBOutlet weak var eventText: UITextView!
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.eventText.delegate = self
self.scrollView.delegate = self
self.timeTableView.delegate = self
self.timeTableView.dataSource = self
self.timeTableView.register(startDateCell.self, forCellReuseIdentifier: "startDateCell")
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "startDateCell", for: indexPath) as! startDateCell
//cell.startDatePicker.date = Date()
//cell.text = "anything"
return cell
}
}
class startDateCell: UITableViewCell {
#IBOutlet weak var startDatePicker: UIDatePicker!
}
I have the outlet connected to my datePicker in the custom cell and I also defined my custom cell class to be startDateCell in inspector, and I registered my custom cell in my view controller. It will throw a runtime error saying the datepicker is nil.
Can somebody explain why it isn't showing up?
Can you remove the following code from viewDidLoad() and ensure you have set reuse identifier of custom tableviewcell as "startDateCell" in storyboard and try again?
self.timeTableView.register(startDateCell.self,
forCellReuseIdentifier: "startDateCell")

How to modify the properties of only one custom cell of a table view?

I want to have a table view cell that contains a button that increments a label by 1 everytime that button is pressed. So if the button is pressed, the label displays: "1,2,3,4", etc. And I want each cell row to be independent from each other, meaning I only want the increment button in cell row 3 to modify the label of cell row 3 and same for cell row 4 and so on.
However my current code functionality does the following:
When I press the increment button it changes the label for all cells not just the label the button is pressed in (I don't want this).
When I scroll the table view all the labels change even when I haven't pressed the button in that row (I want don't want this either, I only want the label to change if its corresponding increment button has been pressed).
Can anyone help get my code or help me construct some code to help me achieve my goals?
Thanks in advance all help is highly appreciated!
My code:
import UIKit
var bookieFlavors = ["Chocolate Chip", "Sugar w/o icing", "Sugar w/ icing", "Peanut Butter", "Honey", "Shortbread", "Ginger", "Double Chocolate", "Macadamie Nut", "Oatmeal Raisin", "Snickerdoodle"]
var labelAmount = Int()
class FlavorsController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var flavorTable: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return bookieFlavors.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! FlavorTableCell
//flavor label configuration
cell.flavorLabel.text = bookieFlavors[indexPath.row]
//amount configuration
cell.bookieAmount.text = "= \(amount)"
return cell
class FlavorTableCell: UITableViewCell {
#IBOutlet weak var flavorLabel: UILabel!
#IBOutlet weak var bookieButton: UIButton!
#IBAction func bookieButton(_ sender: UIButton) {
for _ in 1...15 {
bookieAmount.text = "= \(String(describing: amount))"
}
labelAmount += 1
}
#IBOutlet weak var bookieAmount: UILabel!
You can not add button action in the tableview cell to do this. Please check below code for the solution.
import UIKit
class FlavorsController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var bookieFlavors = ["Chocolate Chip", "Sugar w/o icing", "Sugar w/ icing", "Peanut Butter", "Honey", "Shortbread", "Ginger", "Double Chocolate", "Macadamie Nut", "Oatmeal Raisin", "Snickerdoodle"]
var labelAmount = [Int]() // To keep track of the amount in each cell
#IBOutlet weak var flavorTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
for item in self.bookieFlavors {
self.labelAmount.append(0) //Initialise with default value
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return bookieFlavors.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! FlavorTableCell
//flavor label configuration
cell.flavorLabel.text = bookieFlavors[indexPath.row]
//amount configuration
cell.bookieAmount.text = "= \(self.labelAmount[indexPath.row])"
cell.bookieButton.tag = indexPath.row
cell.bookieButton.addTarget(self, action: #selector(bookieButton(_:)), for: .touchUpInside)
return cell
}
//To configure the button click and according changes
#IBAction func bookieButton(_ sender: UIButton) {
self.labelAmount[sender.tag] = self.labelAmount[sender.tag] + 1
let cell = self.flavorTable.cellForRow(at: IndexPath(row: sender.tag, section: 0)) as? FlavorTableCell
cell?.bookieAmount.text = "= \(self.labelAmount[sender.tag])"
}
}
class FlavorTableCell: UITableViewCell {
#IBOutlet weak var flavorLabel: UILabel!
#IBOutlet weak var bookieButton: UIButton!
#IBOutlet weak var bookieAmount: UILabel!
}

Split View Controller - Custom UITableViewCell

I am trying to add a custom UITableViewCell to my Split View Controller Master. When I run my app the cells don't appear, although they do carry the information as confirmed by a println statement. After some research I found out that only standard UITableViewCells are generated.
The Table ViewController has the Data Source and Delegate connected via the Storyboard and the UITableViewCell has a custom Class with Identifier.
The TableView & TableViewCell are in the same ViewController.
The TableViewCell reusable identifier is "ArtistCell" and it's class is ArtistCell.
import UIKit
import MediaPlayer
class ArtistsMasterTableViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
var artistsQuery:MPMediaQuery!
var artists:NSArray!
var artistAlbums:NSArray!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
artistsQuery = MPMediaQuery.artistsQuery()
artists = artistsQuery.collections
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return artists.count
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println(artists[indexPath.row].items)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ArtistCell", forIndexPath: indexPath) as! ArtistCell
cell.backgroundColor = UIColor.clearColor()
var rowItem:MPMediaItem = artists.objectAtIndex(indexPath.row).representativeItem
if let artwork = rowItem.valueForProperty(MPMediaItemPropertyArtwork) as? MPMediaItemArtwork {
cell.artistImage!.image = artwork.imageWithSize(cell.artistImage.bounds.size)
}
cell.artistNameLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
// artistCell.albumsLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
// artistCell.songsLabel.text = rowItem.valueForProperty(MPMediaItemPropertyArtist) as? String
return cell
}
The custom cell:
class ArtistCell: UITableViewCell {
#IBOutlet weak var artistImage: UIImageView!
#IBOutlet weak var artistNameLabel: UILabel!
#IBOutlet weak var albumsLabel: UILabel!
#IBOutlet weak var songsLabel: UILabel!
}
Here are some Storyboard screenshots:
Great question. From what I've seen the way to implement this is to create a custom xib file that you dequeue. Here is the best article on the subject in objective-c: https://medium.com/#musawiralishah/creating-custom-uitableviewcell-using-nib-xib-files-in-xcode-9bee5824e722
Essentially, you do the following:
Setup your table just like you have minus the reusable cell
Create a custom xib file and make it look like your prototype cell (you can simply do this by making an empty object and dragging a tableviewcell onto the storyboard
Make sure to set the class type of the xib to ArtistCell in the Identity Inspector
Create a custom class ArtistCell to hook the xib up to
Use this code when you are setting up your cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as? ArtistCell
if cell == nil{
tableView .registerNib(UINib(nibName: "ArtistCell", bundle: nil), forCellReuseIdentifier: "cell")
cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as? ArtistCell
}
cell?.nameLabel.text = "Hello World"
return cell!
}
Here's a screen cap just in case:
This code has been fully tested and works for me. FYI. :-) Hope this helps!
Cheers!
Rob Norback

Troubleshooting Custom UITableView Cell [Swift]

I have created a custom UITableView cell in my Storyboard that looks like this:
I hooked it up to my UITableViewCell class like this:
import UIKit
class StatusCell: UITableViewCell {
#IBOutlet weak var InstrumentImage: UIImageView!
#IBOutlet weak var InstrumentType: UILabel!
#IBOutlet weak var InstrumentValue: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Finally I attempted to initialize the UITableView from my UIViewController as such:
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var TableView: UITableView!
let Items = ["Altitude","Distance","Groundspeed"]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.Items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: StatusCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as StatusCell!
cell.InstrumentType?.text = Items[indexPath.row]
cell.InstrumentValue?.text = "150 Km"
cell.InstrumentImage?.image = UIImage(named: Items[indexPath.row])
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
However, when I attempt to run the program I get an EXC_BAD_INSTRUCTION error:
What could I have done wrong? Any help would be appreciated!
The debugger output shows that cell is nil, meaning it could not be instantiated. Furthermore, you are forcing an unwrapping of the optional (using the !) which causes the app to crash on the nil value.
Try to change your cellForRowAtIndexPath method like so (notice the dequeueReusableCellWithIdentifier method):
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as StatusCell
cell.InstrumentType.text = Items[indexPath.row]
cell.InstrumentValue.text = "150 Km"
cell.InstrumentImage.image = UIImage(named: Items[indexPath.row])
return cell
}
Assuming that your custom tableViewCell class is correctly set up and the outlets are bound, there is no need to check for optionals.
Place a breakpoint on the let cell = ... line and step through the code. Check if cell gets initialized and is not nil.
And please: Do not use upper case names for properties and variables (your outlets, Items array...) as upper case names are for classes, structs, ...

Resources