Dynamic Tableview inside a Static tableview Cell - ios

I wanna populate a dynamic tableview inside a static tableview cell, by the same class for both of these.
As you can see in the picture under the cell 'GRE Test Information'.
I'm using the code inside the the class named as MenuController, which is a tableview controller.
class MenuController: UITableViewController,MFMailComposeViewControllerDelegate {
#IBOutlet weak var tablle: UITableView!
var items = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
items = ["A "," BB "]
tablle.delegate = self
tablle.dataSource = self
self.tablle.registerClass(MainTableViewCell.self, forCellReuseIdentifier: "cellNew")
}
// Table Data Source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)
-> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellNew", forIndexPath: indexPath) as! MainTableViewCell
print("Aasim Khaan")
cell.customCell01.text = items[indexPath.row]
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
But it's not populating that at runtime, and says
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier cellNew - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
However I'm using the same identifier named as cellNew both in the code and storyboard.

Well after astonishing efforts regarding this one, I've found the solution.
Concerning the following:
Swift: TableView within Static UITableViewCell
Where the problem solver says : As far as I can determine by experimenting with this, you can't use the same UITableViewController as the data source and delegate of both table views. With a static table view, you're not supposed to implement the data source methods at all. The strange thing is, even if I disconnect the data source and delegate connections between my static table view and the table view controller, that table view still calls numberOfRowsInSection in my table view controller class. If I explicitly set the data source to nil in code, that stops it from calling the data source methods, but the embedded dynamic table view also fails to call them, so this structure doesn't work.
However, you can get around this by using a different object to be the data source and delegate of your embedded dynamic table view. Make an IBOutlet for your embedded table view, and set its data source and delegate to this new object (The class is DataSource in this example, and it's a subclass of NSObject).
I've modified my code in this way now :
import Foundation
import UIKit
import MessageUI
class DataSource: NSObject, UITableViewDataSource, UITableViewDelegate {
var items : [String] = ["GRE Test Structure ","GRE Score "]
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2;
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cellNew", forIndexPath: indexPath) as! MainTableViewCell
cell.customCell01.text = items[indexPath.row]
return cell
}
}
class MenuController: UITableViewController,MFMailComposeViewControllerDelegate {
#IBOutlet var tablle0: UITableView!
#IBOutlet weak var tablle: UITableView!
var dataSource = DataSource()
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem =
self.editButtonItem()
tablle.delegate = dataSource
tablle.dataSource = dataSource
}
}
Now it works exactly fine.

in viewDidLoad
// First Register the UITableViewcell class from nib
let cellNib = UINib(nibName: "MainTableViewCell", bundle: bundle)
self.tableView.registerNib(cellNib, forCellReuseIdentifier:"cellNew")
Then Check with below screeshots
STEP 1: Select MainTableViewCell from Identity Inspector-Custom Class-Click Class Drop Down arrow.It shows you list.From that you can click the MainTableViewCell
STEP 2:Once you click that it shows the name with selected table view cell.

While the existing answers explain how you can do this, they don't address whether you should do this. From the example you provided, it seems that all you need is a single UITableView with multiple dynamic cell types. Each cell type can specify its contentInsets to indent the content as needed.

Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'unable to dequeue a cell
with identifier cellNew - must register a nib or a class for the
identifier or connect a prototype cell in a storyboard'
However I'm using the same identifier named as cellNew both in the
code and storyboard.
You're getting this error because you are dequeing/retrieving the prototype cell from the wrong table!
The line in your cellForRowAtIndexPath should be:
let cell = tablle.dequeueReusableCellWithIdentifier("cellNew", forIndexPath: indexPath) as! MainTableViewCell
Having said that, even once that is working, asking a tableViewController to act as data source and delegate for both a static and a dynamic table causes problems later.

Related

Content of a cell in static tableview isn't shown SWIFT 3

Here is my implementation of tableView(_:cellForRowAt:):
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let index = indexPath.section
let weekDay = WeekDays.day(at: index)
if self.availability.numberOfTimeslots(for: weekDay) == 0 {
let cell = NotSelectedCell(style: .default, reuseIdentifier: nil)
return cell
}
return UITableViewCell()
}
Here is my code for my custom table view cell:
class NotSelectedCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.backgroundColor = .red
self.textLabel?.numberOfLines = 0
self.textLabel?.textAlignment = .center;
self.textLabel?.text = "Not Available"
}
}
I've also tried initializing custom cell cell = NotSelectedCell() the result is the same. The content isn't shown. dataSource or viewDelegate aren't the problem as I'm working with UITableViewController.
Here's an image
The problem is awakeFromNIB "prepares the receiver for service after it has been loaded from an Interface Builder archive, or nib file." But you're instantiating this programmatically, so that method isn't called. You could theoretically move the code to init(style:reuseIdentifier:), make sure to call super in your implementation, and do any additional customization after that point.
But, you generally wouldn't programmatically instantiate cells when using static cells. (It's the point of static cells, that IB takes care of everything for you.) You generally don't implement UITableViewDataSource at all when using static cells.
I would advise using dynamic table and have two cell prototypes, one with reuse identifier of "NotAvailable" and one with "Available" (or whatever identifiers you want). Then programmatically instantiate the cell with the appropriate identifier. (By the way, this also has the virtue that your cell with "NotAvailable" can be designed entirely in IB, and no code is needed, for that cell at least.) This way, the storyboard takes care of instantiating the appropriate cell.
So, here I have two cell prototypes in my dynamic table, one for "not available" and one for "available":
Then the code would look at the model to figure out which to instantiate:
// for the complicated cell where I want to show details of some window of availability, add IBOutlets for that cell's labels
class AvailableCell: UITableViewCell {
#IBOutlet weak var startLabel: UILabel!
#IBOutlet weak var stopLabel: UILabel!
#IBOutlet weak var doctorLabel: UILabel!
}
// some super simple model to represent some window of availability with a particular doctor in that office
struct Availability {
let start: String
let stop: String
let doctor: String
}
class ViewController: UITableViewController {
let days = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
let available = ...
override func numberOfSections(in tableView: UITableView) -> Int {
return days.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return available[days[section]]?.count ?? 1
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return days[section]
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// see if there are any available windows for the given day, if not, return "not available" cell
guard let availabilities = available[days[indexPath.section]] else {
return tableView.dequeueReusableCell(withIdentifier: "NotAvailable", for: indexPath)
}
// otherwise, proceed with the more complicated "Available" cell where I have to populate various labels and the like
let cell = tableView.dequeueReusableCell(withIdentifier: "Available", for: indexPath) as! AvailableCell
let availability = availabilities[indexPath.row]
cell.startLabel.text = availability.start
cell.stopLabel.text = availability.stop
cell.doctorLabel.text = availability.doctor
return cell
}
}
And that would yield:
Now, clearly, I just whipped up a super primitive model, and didn't do any UI design in the "available" cell prototype other than inserting three labels. But it illustrates the idea: If your dynamic table has multiple unique cell designs, just implement cell prototypes for each with unique identifiers and instantiate the appropriate one. And this way, you enjoy full cell reuse, minimize how much visual design you have to do programmatically, etc.
You are not supposed to use the cellForRow:atIndexPath method when using static cells. The cells are static, so the loading flow is different. What i'd suggest is to connect the cells individually from the interface builder to your view controller.
STILL, if you want to do it this way you have to get your cells by calling "super" since that's the class who is actually generating your static cells.
UITableView with static cells without cellForRowAtIndexPath. How to set clear background?
EDIT:
I just noticed that this is wrong:
if self.availability.numberOfTimeslots(for: weekDay) == 0 {
let cell = NotSelectedCell(style: .default, reuseIdentifier: nil)
return cell
}
You have to use the "dequeueReusable" method or something. Then again, these are STATIC Cells, so you should just be linking the cells directly from the interface builder.

iOS Swift 2.0: Use of unsolved identifier 'UITableviewCell'

I was following a coding tutorial of making a simple app, everything looked and worked okay at first but after a while I ran into an error says:
use of unresolved identifier 'UITableViewCell'.
The tutorial's code worked fine in its video and I wrote the exact same code however it was an error on my computer. I guess it's the matter of different versions of Xcode.
Here is my code:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.tableView.dataSource = self
self.tableView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
**let cell = UITableviewCell()**
*//Where the error message is at. //*
return cell
}
}
The error message is at the line:
let cell = UITableViewCell()
I cannot comment on the answer posted by Stefan Salatic but you have to indeed use dequeable cells but to add to that, you should not forget to set the identifier in the main.storyboard to the CellIdentifier you used to create dequeable cell.
let cell = tableView.dequeueReusableCellWithIdentifier("Identifier", forIndexPath: indexPath) as UITableViewCell
In the storyboard go to the TableViewController -> Attribute Inspector -> Identifier and set it to:
Identifier
If you have an array of data you can fill the cell using:
cell!.textLabel?.text = data[indexPath.row]
You should dequeue UITableViewCells. Something like this
let cell = tableView.dequeueReusableCellWithIdentifier("CellIdentifier", forIndexPath: indexPath) as UITableViewCell
You want to reuse cells, not create a new one each time. This is the preferred way of doing it.

Nothing appearing in UITableView cell

I am working on an app that needs to display five different images inside of five different tableview cells. This is the storyboard that I have for the cell.
This is the code I have inside of the tableviewcontroller.
class MasterViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
var returnTable = 1
var icons: [String] = ["settings", "calendar", "classes", "envelope", "grades"]
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return icons.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! HomeScreenCells
var image : UIImage = UIImage(named: icons[indexPath.row])!
cell.icon.image = image
return cell
}
I also have a custom class for the tableviewcells. Also, I have the correct reuse identifier for the cell. Still, the image does not appear. Not only does the image not appear, nothing appears. When I change the background, the background does not change in the simulator. This is all I get in the simulator.
I have the classes linked up correctly for the split view controller. I have no idea why nothing is appearing in the table. Any help would be appreciated.
I think your problem may be that you have the number of sections set to 0. Either set it to 1, or leave out the block of code completely.
As stated above, return 1 in number of sections (or the number of cells you need). And if your custom cell class has a .xib, you also need to register it, sometimes after you init the tableview
tableView.registerNib( UINib(nibName: "HomeScreenCells", bundle: nil), forCellReuseIdentifier: "Cell")

Swift Custom UITableViewCell not displaying data

I am new to Swift, and iOS development in general. I am attempting to create a custom UITableViewCell. I have created the cell in my main storyboard on top of a UITableView that is inside a UIViewController. When I loaded one of the default cells, I was able to populate it with data. However, now that I am using a custom cell, I cannot get any data to appear in the table. I have gone through all kinds of tutorials and questions posted on the internet, but I can't figure out why it is not working. Any help would be appreciated.
Here is my code for the UIViewController that the tableview resides in.
import UIKit
class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tblView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//self.tblView.registerClass(UITableViewCell.self, forCellReuseIdentifier : "Cell")
self.tblView.registerClass(CustomTableViewCell.self, forCellReuseIdentifier : "Cell")
tblView!.delegate = self
tblView!.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataMgr.data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : CustomTableViewCell = self.tblView.dequeueReusableCellWithIdentifier("Cell", forIndexPath : indexPath) as! CustomTableViewCell
var values = dataMgr.data[indexPath.row]
cell.newTotalLabel?.text = "\(values.newTotal)"
cell.winLoseValueLabel?.text = "\(values.newTotal - values.currentTotal)"
cell.dateLabel?.text = "5/17/2015"
return cell
}
}
I have stepped through the program where it is assigning values to the cell variables. The variable 'values' is being populated with data, but when stepping over the assignment lines to the cell variables, I found that they are never assigned. They all remain nil.
When you make a custom cell in the storyboard, don't register the class (or anything else). Just be sure to give the cell the same identifier in the storyboard that you pass to dequeueReusableCellWithIdentifier:forIndexPath:.

How to fix "nib but didn't get a UITableView" error?

Why I get this error?
Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: '-[UITableViewController
loadView] loaded the "pB1-re-lu8-view-o7U-YG-E7m" nib but didn't get a
UITableView.'
here is my code:
class FriendListTableViewController: UITableViewController{
var objects = NSMutableArray()
var dataArray = [["firstName":"Debasis","lastName":"Das"],["firstName":"John","lastName":"Doe"],["firstName":"Jane","lastName":"Doe"],["firstName":"Mary","lastName":"Jane"]]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table View
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
let object = dataArray[indexPath.row] as NSDictionary
(cell.contentView.viewWithTag(10) as! UILabel).text = object["firstName"] as? String
(cell.contentView.viewWithTag(11) as! UILabel).text = object["lastName"] as? String
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return false
}
my storyboard is like this:
I have face same issue once upon time, and So stupid mistake it was, I have subclass the UITableViewController, where I have added UITableView in UIViewController
From your storyboard Image, it may be solved if you use UIViewController instead of UITableViewController, Just try that way can solve your issue,like
class FriendListTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
SWIFT 2 UPDATE
I tried #Viralsavaj's answer but it didn't work for me until I "hooked up" the tableView as an outlet from the storyboard in the ViewController.
like this: #IBOutlet weak var tableView: UITableView!
Also add this to your class as #Viralsavaj mentioned:
class TableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
I used specifically this link help as well: How to reference tableView from a view controller during a segue
Just drag your tableView into the ViewController and make it an outlet. Then you can reference its properties such as self.tableView.reloadData().
This property as well as others that referenced the tableView were giving me errors until I added the tableView as a referencing outlet.
Hope this helps those in the future.
I had this issue with Swift 2, Xcode 7.2, I changed a View Controller I dragged to my Storyboard to a custom UITableViewController class, I then dragged a Table View onto the View Controller. I didn't realize I placed it as a child of the View that was part of the original View Controller I dragged onto the Storyboard.
I simply deleted the View and added the Table View again as the first child of the Super View.

Resources