Xcode (Swift) error - use of undeclared type 'CustomCell' - ios

I've been learning table views from tutorials on YouTube. I was following every step told in the video, and did everything the same as the author of this tutorial, but for some reason I got a strange error - I've heard that it's about old version of Xcode used in the tutorial - I'm working on the latest one.
Debugger tells that "CustomCell" is undeclared.
Every help will be appreciated!
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayOfCwiczenia.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: CustomCell = tableView.dequeueReusableCellWithIdentifier("Cell") as CustomCell
let person = arrayOfCwiczenia[indexPath.row]
cell.setCell(cwiczenia.nazwa, imageName: cwiczenia.obrazek)
return cell
}

CustomCell looks to be a subclass of UITableViewCell
Looks like they left out the part where you need to create it
Create a new file called CustomCell and make sure it's base class is UITableViewCell

You must have a file where you define the behaviour of the custom cell - if that's not called 'CustomCell' then it won't be declared.
Just make sure that you have the same name when you define the class and when you use it.

I would suggest looking at Apple's walkthrough on how to implement a table view. It has step by step instructions with pictures. If you scroll down the the Design Custom Table Cells section I think you will be able to see how to link the custom cell to a file properly

Your tutorial should have mentioned all the details, but here it goes...
You need to define a subclass of UITableViewCell named CustomCell:
import UIKit
class CustomCell: UITableViewCell
{
// Your custom properties/methods.outlets/etc.
}
(typically, in a source file named CustomCell.swift, but this is not compulsory)
If you are using a storyboard, you need to set the class of your prototype cells to "CustomCell" in the identity inspector (third tab from the left on the right inspector pane - the one with the icon that looks like a newspapaer):
Also, In the attributes inspector (fourth tab from the right, icon looks like a slider), set the cell's identifier (in the case of your code, "Cell"):
If you are not using a storyboard, you need instead to register the custom cell class and identifier programmatically:
func viewDidLoad()
{
tableView.registerClass(CustomCell.self, forCellReuseIdentifier: "Cell")
// other setup...
}

I had this same error. Tried cleaning and building which worked but the main issue seemed to just be saving the CustomCell which then becomes recognised by the compiler and removes the error.
Its not limited to cells I've had it with other custom classes before as well. Good one to know about though!

Related

How to left/right-align custom UITableView cell

I’m coding a “chatbot” app, and to hold the message bubbles I have a UITableView and a custom message-bubble shaped cell. Here’s what it looks like so far:
All the cells will look the same, except I’d like every other cell to be, say, half the width of the table and alternating right/left aligned. How could I do this programmatically?
The better way - to create two classes InMessageCell, OutMessageCell, and add all properties (like aligning of all elements) hide inside of this cell. Both cell will have the same width, but all bubbles will be moved on one or other side. It may inheritance from the main class MessageCell, so all logic may stay in main class, but UI part - splitted up.
Two straightforward ways of achieving this by using custom table view cells:
Have two different cell classes. They can share much of their implementation (e.g. by class heritage), but differ in their layout (one is left aligned, one right aligned). For each row in your table, decide which cell you need to use, and dequeue the appropriate one.
Have one cell class whose layout can be toggled when it's being dequeued. (How exactly this toggle looks like depends of course on how you chose to layout your cell. It could e.g. be that you exchange the constant to an autolayout constraint you reference via #IBOutlet, the switching of a background image, or changing the alignment property of a stack view, among many others.)
Both ways depend on making a decision which cell flavor to use in your UITableViewDataSource's tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) function.
Here is a slightly abstract example using the first method. In your UITableViewDataSource:
enum ChatCellAlignment {
case left
case right
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellAlignment: ChatCellAlignment = self.cellAlignmentForIndexPath(indexPath) // you need to implement something like this
var identifier = "Default"
switch cellAlignment {
case .left:
identifier = "LeftAlignedBubbleCell"
case .right:
identifier = "RightAlignedBubbleCell"
}
let cell = self.tableView.dequeueReusableCell(withIdentifier: identifier)
if let cell = cell as? ChatBubbleCell { // assuming your custom cell classes all inherit from a "ChatBubbleCell"
cell.set(text: self.textForIndexPath(indexPath))
... // whatever setup you need to do on your custom cell
}
return cell
}
You can give the table view cell a value to know it. Then you can use autolayout (SnapKit) to make it align left or right

Swift Custom Cell creating your own Cell with labels

I've just started to use Swift as a prorgamming language and i've run into a problem with Custom cells.
When i try to create custom cells, and then go forward and try to design them the way i need them ( with Style set to Custom ) everything looks good. Now i don't know how to put specific data into them, since all tutorials i found used the style option "basic" where they only have a text label to which they assign their data.
Now for me, when i "control drag" my labels into my code, i give them specific names such as "dateLabel" or "sourceLabel" in order to insert the data correctly.
now i'm not sure, and couldn't find any answers that worked, on how to recall my custom made labels so that i can assign my data to them...
Maybe someone of you could help me with this, since i'm pretty sure it's a simple problem but i coudln't find any resources to this ^^
hopefully the font isn't to small, i just wanted you guys to see the erros i get.
I used the following tutorial as a guide line, since it was the only one that worked just the way this guy did it: https://www.youtube.com/watch?v=0qE8olxB3Kk
I checked the identifier and he is set correctly and i can't find anything online on how i have to properly refer to my own labels with their correct names.
any help would be appreciated :)
Try the following steps:
Create a custom table view cell class that extends UITableViewCell. In my example, the custom table view cell class is called MyCustomTableViewCell.
Update your storyboard's cell so that it uses your custom table view cell class. Go to the Identity Inspector and set the Class value to the name of your custom table view cell class.
Update your storyboard's cell and give it a reuse identity value. Go to the Attributes Inspector and set the Identifier value. For example, I gave my cell an Identifier value of MyCustomCell.
Control drag the cell's labels into your new custom table view cell class (i.e., the MyCustomTableViewCell class).
Once you have done the above steps, you will be able to access the labels when you dequeue your cell in the tableView:cellForRowAtIndexPath: method. As the code snippet below shows, you will need to: 1) get the cell using the reuse identifier you established in the steps above and 2) cast to your custom table view cell class.
For example, here's what your custom table view cell would look like if you named it MyCustomTableViewCell. This is after you created the class and control dragged your labels into this class.
class MyCustomTableViewCell: UITableViewCell {
#IBOutlet weak var categoryLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var sourceLabel: UILabel!
#IBOutlet weak var titleLabel: UILabel!
}
Your ViewController could look like this:
// NOTE: I subclassed UITableViewController since it provides the
// delegate and data source protocols. Consider doing this.
class ViewController: UITableViewController {
// You do NOT need your UILabels since they moved to your
// custom cell class.
// ...
// Omitting your other methods in this code snippet for brevity.
// ...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Use your cell's reuse identifier and cast the result
// to your custom table cell class.
let article = tableView.dequeueReusableCellWithIdentifier("MyCustomCell", forIndexPath: indexPath) as! MyCustomTableViewCell
// You should have access to your labels; assign the values.
article.categoryLabel?.text = "something"
article.dateLabel?.text = "something"
article.sourceLabel?.text = "something"
article.titleLabel?.text = "something"
return article
}
}

Strange UITableView error: "Assertion Failure" on dequeuing static cells in storyboard

I am getting this error: *** Assertion failure in -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:] with static cells.
My code is in Swift (the reuse identifiers are strings set as constants in the file):
...
private let topTableViewCellIdentifier = "topTableViewCell"
private let bottomTableViewCellIdentifier = "bottomTableViewCell"
...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let reuseIdentifier = (indexPath.section == 0) ? topTableViewCellIdentifier : bottomTableViewCellIdentifier
let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath)
return cell
}
I have searched stack overflow for this error, and found a bunch of answers all basically saying the same thing: make sure the reuse identifier is the same as the one for the cell in the storyboard.
However, in my case, it is.
I have confirmed this repeatedly, and have cut and pasted from one to the other repeatedly in order to ensure this is the case. Xcode clearly indicates that the correct value is being set. I have cleaned. I have even restarted. I have done everything I can think of, and it does not see the cells in the storyboard. They are set as static, and The correct class is being set in the inspector (though that should be clear by the fact that it gets the correct value)
Any thoughts or assistance would be appreciated. I am using El Capitan and Xcode 7.
If you are attempting to use a static layout for a table view, you typically do not implement tableView:cellForRowAtIndexPath:, the UITableViewController does this for you. It is invalid to call the dequeueReusableCellWithIdentifier:forIndexPath: method for a statically configured UITableView (as the error indicates).
Make sure your UITableView is set to Dynamic Prototypes

Custom header of table view with IB

I would like to create a custom header for a table view section with interface builder. I cannot use the method titleForHeaderInSection because i need to display two labels. I used this instructions: Customizing Header and Footer of TableView in iOS8 but it does not work.
What I have done so far:
Create a custom class CustomTableCell which inherits from UITableViewCell
class CustomTableCell: UITableViewCell {
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var dateDescriptionLabel: UILabel!
}
Create a dynamic prototype cell in storyboard
Add an identifier
Connect the labels to the custom UITableViewCell
Implement viewForHeaderInSection
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCellWithIdentifier("CustomTableCell") as CustomTableCell
headerCell.backgroundColor = UIColor.cyanColor()
headerCell.dateLabel.text = "Test date"
headerCell.dateDescriptionLabel.text = "Test date description"
return headerCell
}
When i run the app the section appears one second and then moves under the table cells and I get an error: no index path for table cell being reused.
What is wrong with this solution? I downloaded the project from the tutorial I have linked and it works there.
Your problem has its roots in how UIKit handles UITableViews.
To make sure table views are fast and responsive, even with a large amount of cells, the cells are re-used.
By calling tableView.dequeueReusableCellWithIdentifier("CustomTableCell") you are asking the tableView to give you a cell to reuse.
A lot of people have been using the reusable cells to design their headers/footers in Storyboards. Ever since iOS 7 Beta 5 this may lead to errors. This answer explains the situation well: What is the meaning of the “no index path for table cell being reused” message in iOS 6/7?
To design your own custom header/footer views I don't recommend using UITableViewCells. Instead you should create and design a custom UIView directly in your code. If you want to use Interface Builder you could create a .xib or create a view in your Storyboard that is not a subview of the actual controller's view.

Swift MVC Design With Multiple Table Views

So I have the main view of my controller that has a table view. This table view will be displaying many different custom classes that subclass UITableViewCell. Some of these cells will ALSO have table views inside of them.
My problem is that I do not know what class I should assign to to be the UITableViewDelegate in this sort of situation for the table view in the table view cell. My intial thought was to make it the cell view class:
class MyTableViewCell: TableViewCell {
#IBOutlet var tableView: UITableView!;
var messages: Array<String>?;
//called by parent tableview when cellForRowAtIndexPath is called in main controller
//to initialize view with dynamic properties at run time
override func render(obj: MyObject) {
messages = obj.getMessages();
}
}
extension MyTableViewCell: UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages == nil ? 0 : messages!.count;
}
}
This is problematic because I have no where to register my nib files to the table view:
nib = UINib(nibName: "MyTableViewCell", bundle: nil);
self.tableView.registerNib(nib!, forCellReuseIdentifier: "custom");
Also, I feel like making a view a table view data source is violating MVC principles. What is the best way to go about with my table views within table view cells?
The UITableView within a UITableCell was indeed implemented in Pulse as described by genalipsis. In Obj-C,there is a full tutorial plus posted code located here for UITableView within a UITableCell:
http://iosstuff.wordpress.com/2011/06/29/adding-a-uitableview-inside-a-uitableviewcell/
http://iosstuff.wordpress.com/2011/06/29/creating-pulse-style-scrolling-horizontally-scrolling-uitableview-as-a-subview-of-uitableviewcell/
The was done in Xcode 4. I am not sure if this will work in Xcode 6.1 but it does describe a methodology.
I think an even more descriptive and easier to follow tutorial was posted at Ray Wenderlich's site here:
http://www.raywenderlich.com/4680/how-to-make-an-interface-with-horizontal-tables-like-the-pulse-news-app-part-1
http://www.raywenderlich.com/4723/how-to-make-an-interface-with-horizontal-tables-like-the-pulse-news-app-part-2
Create a regular UITableView
Create a custom UITableViewCell
Add a rotated UITableView as a subview of our UITableViewCell
Create another custom UITableViewCell for our articles
Rotate our custom cell and use it for our horizontal table view
While the tuorial was from 2011, some of the comments are very recent, so the approach must still work.
There is also a github project that references a stack overflow discussion from earlier this year:
https://github.com/hefgi/TableViewInTableViewCell
If you open the project, the storyboard file for the iPhone is instructive (Main_iPhone.storyboard):
A table view inside of a table view has been done before. One of the first iPad Apps, Pulse, used this strategy to allow uses to scroll vertically between RSS feeds and horizontally, within each cell, between RSS entries. That is, the embedded table view was rotated and the cells inside it where also rotated so that their orientation allowed reading.
For usability reasons, you will probably want to follow a similar pattern, else it might be difficult to scroll.
Tentative architecture: MainTableViewController is the controller for the table view that contains sub table views. SubTableViewController is the controller for the table views contained within the cells of the MainTableViewController. This approach lets you use TableViewControllers in the "standard" fashion
class MainTableViewController: TableViewController {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//dequeue a cell or create an instance of a cell
//create instances of SubTableViewController or change the data source for indexPath
//add the view of SubTableViewController to the cell's view hierarchy
//make necessary view adjustments depending on orientation, etc.
}
Not a standard setup, so I would expect that a few further hacks will be necessary.

Resources