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, ...
Related
I have been searching for some time now and have developed a massive headache trying to solve this problem. Basically, I would like to have a parent tableView mainTableView to contain a tableViewCell that includes a label and another tableView innerTableView. This problem is not as simple as I had hoped.
If there is a better way to implement what I want with different components, please let me know.
Otherwise, I have tried to simplify the code to its bare bones with simple data. Please assume I have correctly connected all my outlets properly. I have 3 swift files for this simplified version. ViewController.swift is the main VC that holds the mainTableView. MainTableViewCell.swift is the main cell that will hold a label and a tableView innerTableView in it. InnerTableViewCell is the final cell that will be associated with the innerTableView. In this cell, there is only a label. I have been successful in creating this first layer and the mainNameLabel.text shows up properly on the main storyboard. However, I have configured MainTableViewCell to the best of my knowledge and have come short to success. The innerTableView does not appear on the main storyboard.
Below, I will provide the code of each swift file:
ViewController.swift
//
// ViewController.swift
// NestedTableViews
//
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var mainTableView: UITableView!
//fake data
var arr = ["Hello", "Hi", "Whats up", "How's it going"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
mainTableView.delegate = self
mainTableView.dataSource = self
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainTableViewCell") as! MainTableViewCell
let word = arr[indexPath.row]
cell.mainNameLabel.text = word
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
}
MainTableViewCell.swift
//
// MainTableViewCell.swift
// NestedTableViews
//
import UIKit
class MainTableViewCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var mainNameLabel: UILabel!
#IBOutlet weak var innerTableView: UITableView!
var innerArr = ["How are you?", "How are you doing?", "What's the matter?"]
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
innerTableView.dataSource = self
innerTableView.delegate = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "InnerTableViewCell") as! InnerTableViewCell
let innerWord = innerArr[indexPath.row]
cell.innerNameLabel.text = innerWord
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return innerArr.count
}
}
InnerTableViewCell
//
// InnerTableViewCell.swift
// NestedTableViews
//
import UIKit
class InnerTableViewCell: UITableViewCell {
#IBOutlet weak var innerNameLabel: 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
}
}
Here is what the storyboard looks like in this current state:
What is it that I am doing wrong? I could ask 100 questions but regardless, I am still very stuck here. How do I get the nested tableView innerTableView to appear and with the proper data?
Thank you in advance
I spent hours of trying to fix this, but my simple app still displays the basic cell type instead of my prototype cell. I'm aware of using the identifier and registering after loading up the view, but it still displays the basic cells with just one label.
Here is my code so far:
My prototype is using this UITableViewCell:
class CoinTableViewCell: UITableViewCell {
#IBOutlet weak var coinIcon: UIImageView!
#IBOutlet weak var coinTitleLabel: UILabel!
#IBOutlet weak var holdings: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
UITableViewController:
class CoinTableViewController: UITableViewController {
var coins = ["Coin1","Coin2","Coin3"]
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(CoinTableViewCell.self, forCellReuseIdentifier: "currency_cell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return coins.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:CoinTableViewCell! = self.tableView.dequeueReusableCell(withIdentifier: "currency_cell", for: indexPath) as! CoinTableViewCell
let coinName = coins[indexPath.row]
cell.coinTitleLabel?.text = coinName
return cell!
}
}
I would be so grateful if someone is able the help me out with this!
You are creating your custom cell directly on the tableview in the storyboard, right ?
If this is the case then you don't need to register the cell in your viewDidLoad as the storyboard takes care of that. You just deque it and it's good to go.
If you register it manually you just override what the storyboard did and end up getting a regular cell as the cell gets instantiated from the code instead of getting instantiated from the storyboard.
Cheers
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")
var leadername = ["1","2","3","4"]
var districts = ["Delhi","Kerala"]
override func viewDidLoad() {
leadTableSetup()
super.viewDidLoad()
}
func leadTableSetup(){
LeadTableView.delegate = self
LeadTableView.dataSource = self
self.LeadTableView.register(UINib(nibName: "LeaderBoardTableViewCell", bundle: nil), forCellReuseIdentifier: "leadCell")
}
func numberOfSections(in tableView: UITableView) -> Int {
return 5
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 14
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "leadCell") as! LeaderBoardTableViewCell
// Set text from the data model
cell.areaLbl.text = districts[indexPath.row]
cell.leaderNameLbl.text = leadername[indexPath.row]
return cell
}
I have declared two strings and I need to display these strings in the labels in my custom collection view cell that I have created. How can I achieve this? I need to display "leadername" string in one label and "districts" label in another label.
Go with this demo, Shared Demo
After the demo, If you still face any problem then let me know.
Now Listen Here
I think you need output something like this,
Follow the steps: -
Create a new viewcontroller(says, CustomTableVC) in your storyboard and one UITableView(give constraints and delegate to its own class), take outlet of UItableView (says, tblMyCustom)
Now press CLT+N for new file and do like this below image, Subclass - UItableViewCell and also tick on XIB option.
Open our xib file, add new UIView (says myView, as you see highted in below image), in this myView add two labels
Now take outlet of these two labels in its customCell class
class CustomTableCell: UITableViewCell {
#IBOutlet var lblLeaderNo: UILabel!
#IBOutlet var lblDistict: 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
}
}
Now back to your Viewcontroller Class
import UIKit
class CustomTableVC: UIViewController , UITableViewDelegate, UITableViewDataSource{
#IBOutlet var tblMyCustom: UITableView!
var leaderno : [String]!
var distict : [String]!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.tblMyCustom.register(UINib(nibName: "CustomTableCell", bundle: nil), forCellReuseIdentifier: "customCell")
self.leaderno = ["1", "2", "3", "4"]
self.distict = ["Delhi","Kerala", "Haryana", "Punjab"]
// above both array must have same count otherwise, label text in null
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return leaderno.count;
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
var customCell: CustomTableCell! = tableView.dequeueReusableCell(withIdentifier: "customCell") as? CustomTableCell
customCell.lblLeaderNo.text = self.leaderno[indexPath.row]
customCell.lblDistict.text = self.distict[indexPath.row]
return customCell
}
}
above all is code of VC, it is not getting settle down here in single code format, I dont know why.
Now, follow these steps you get output as i show you image in starting of the procedure.
I'm just getting started with Swift and I'm having some weird issues with a custom UITableViewCell. The issue is I needed to have a white background inside each table cell as seen here.
I have created a custom UITableViewCell class and created IBOutlets for a image, label and button as shown below:
import UIKit
class LocationTableViewCell: UITableViewCell {
#IBOutlet var locationImageView: UIImageView!
#IBOutlet var locationButton: UIButton!
#IBOutlet var locationLabel: 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
}
My view controller code is:
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
#IBOutlet var locationTableView: UITableView!
var skiLocation = Location(name: "Banff", picture: UIImage(named: "ski.jpeg")!)
var tundraLocation = Location(name: "Yellowknife", picture: UIImage(named: "tundra.jpeg")!)
var beachLocation = Location(name: "Cancun", picture: UIImage(named: "beach.jpeg")!)
var locations: [Location] = []
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return locations.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: LocationTableViewCell = tableView.dequeueReusableCellWithIdentifier("location", forIndexPath: indexPath) as! LocationTableViewCell
cell.locationLabel.text = self.locations[indexPath.row].name
cell.locationImageView.image = self.locations[indexPath.row].picture
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.locations = [skiLocation, tundraLocation, beachLocation]
self.locationTableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I have approached this problem by making a UIView inside of each table view and then placing the button, label and image inside the UIView. This was just to get the white background. However, when I run my code everything shows as expected, except there is no UILabel and the UIButton is stylized as per storyboard. When I try to change the background of the label, or the button via storyboard, nothing changes. No label and just the generic button. The weird part is I am able to set the images to the UIImageView via the ViewController class.
Any thoughts?
EDIT: Here is the link to the storyboard view. I have used the identifier field in the storyboard view to link the cell.
You have UITableViewDataSource But UITableViewDelegateis missing.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var locationTableView: UITableView!
var skiLocation = Location(name: "Banff", picture: UIImage(named: "ski.jpeg")!)
var tundraLocation = Location(name: "Yellowknife", picture: UIImage(named: "tundra.jpeg")!)
var beachLocation = Location(name: "Cancun", picture: UIImage(named: "beach.jpeg")!)
var locations: [Location] = []
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return locations.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: LocationTableViewCell = tableView.dequeueReusableCellWithIdentifier("location", forIndexPath: indexPath) as! LocationTableViewCell
cell.locationLabel.text = self.locations[indexPath.row].name
cell.locationImageView.image = self.locations[indexPath.row].picture
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.locations = [skiLocation, tundraLocation, beachLocation]
self.locationTableView.dataSource = self
self.locationTableView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}