I have a custom cell class called CurrentFilesCell with the setting code below
class CurrentFileCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var statusImage: UIImageView!
var currentContent: AircraftContent! {
didSet{
setStyles(Constants.appStyleSetting)
nameLabel.text = currentContent.contentName
dateLabel.text = currentContent.contentStatus
}
}
Within my CurrentFilesViewController I simply set it within cellForRowAtIndexPath
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CurrentFileCell", forIndexPath: indexPath) as? CurrentFileCell
cell?.currentContent = content
return cell!
}
I believe I also have everything linked correctly, as I have done something similar to this in other classes, both with cells and vc's.
My problem is that It does not load anything when run, there is no default text and no updated text after it should have been set. Here is an image showing the linkage
http://imgur.com/qlK4d5O
I'm really not sure what is going on and why this isn't working. I have tried deleting it and recreating but I must be missing something.
EDIT
Here is a picture of the debugger showing that the cell's currentContent is not empty. This is taken right before the return cell! is executed.
http://imgur.com/O250qXq
Did you register this cell in table view? If not than dqueRqusableCellWithIdentifier will return nil value...
You can register it using UITableView function "registerNib: forCellReuseIdentifier:"
In the storyboard, you must define subclass of the prototype table cell.
And then, you must define identifier of the prototype table cell as "CurrentFileCell".
Then you will show the content of the table when the app will be run.
Related
first of all i'm saying straight forward I know this is "duplicate" and and this is my 2nd time asking the same question - the problem is that my first one has been closed without me understanding the problem so please if someone wants to close this question again first let me understand what am I doing wrong. The solution I got last time was not relevant so if I could get addressed specifically that would be great!
I am trying to create a custom cell on tableview from an array. when I append any filed on my custom cell I get unexpected nil on all of the fileds and I have no idea why
this is my custom cell:
class CustomMovieCell: UITableViewCell {
#IBOutlet weak var title: UILabel!
#IBOutlet weak var rating: UILabel!
#IBOutlet weak var releaseYear: UILabel!
#IBOutlet weak var genre: UILabel!
var imageBackground: String!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
and this is my UITableView cellForRowAtIndexPath method:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MovieCell", for: indexPath) as! CustomMovieCell
let movieFetched = Movie(title: moviesArray[indexPath.row].title, image: moviesArray[indexPath.row].image, rating: moviesArray[indexPath.row].rating, releaseYear: moviesArray[indexPath.row].releaseYear, genre: moviesArray[indexPath.row].genre)
print(movieFetched)
cell.title.text? = movieFetched.title
cell.rating.text? = String(movieFetched.rating)
cell.releaseYear.text? = String(movieFetched.releaseYear)
cell.genre.text? = String(movieFetched.genre[0])
return cell
}
what am I missing? when appending ANY of the files I get unexpectedly found nil while unwrapping optional value - I did not know UIlabel as IBOutlet are optional? even-though they are not optional in my custom cell class.
when debugging I can see that all values of the cell - title, image, rating, releaseYear and genre are nil when trying to assign them a value - so I really have no idea what to do at this point. I have deleted and re-created the cell from scratch and it did not make any differents.
As I already stated - I know this is "duplicate". please though - do not close it before you help me because I did not get any answer the last time, I got directed to a wall-of-text page that did not help me understand my issue. The other "duplicate" pages are like a general "what are optional values" kind of question and do not help me with this specific issue.
edit:
I have uploaded this project to github if it helps anyone help me to figure out this issue
https://github.com/alonsd/MoviesApi
You've connected the custom cell class with 2 cells. One is in xib and another one is in this UIViewController. This UIViewController's prototype cell doesn't have these labels. So it will be nil and it will crash
Delete the prototype cell from MoviesViewController in storyboard. And add this in MoviesViewController viewDidLoad
tableView.register(UINib(nibName: "TableViewCell", bundle: nil), forCellReuseIdentifier: "MovieCell")
Change tableView cellForRowAt method as follows
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MovieCell") as! TableViewCell
cell.title.text = moviesArray[indexPath.row].title
cell.rating.text = String(moviesArray[indexPath.row].rating)
cell.releaseYear.text = String(moviesArray[indexPath.row].releaseYear)
cell.genre.text = String(moviesArray[indexPath.row].genre[0])
return cell
}
I have a Table Bar where i have 3 separate MVC. The first MVC is a UITableView where i can search for a location and it will display 10 day forecast. The second MVC also a UITableView stores my favourite locations. I can tap on the location and it will bring me another UITableView that displays the 10 day forecast just like the first tab bar. However i get an "Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value" I'm using a custom prototype cell just like the first tab bar view and it works great there.
The code for my first tab bar mvc looks like:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "WeatherDataCell", for: indexPath)
let weatherCell = timeSeries[indexPath.row]
if let wc = cell as? WeatherTableViewCell {
wc.timeSeries = weatherCell
}
return cell
}
The custom prototype cell looks something like:
class WeatherTableViewCell: UITableViewCell {
#IBOutlet weak var WeatherImageView: UIImageView!
#IBOutlet weak var WeatherTimeLabel: UILabel!
#IBOutlet weak var WeatherTemperatureLabel: UILabel!
#IBOutlet weak var WeatherWindLabel: UILabel!
#IBOutlet weak var WeatherPrecipitationLabel: UILabel!
var timeSeries : TimeSeries? {
didSet {
updateUI()
}
}
func updateUI() {
for parameters in timeSeries!.parameters {
if parameters.name == "t" {
let temperature = parameters.values[0]
WeatherTemperatureLabel.text? = "\(temperature) °C" // <- works for the first MVC but crashes on the second MVC even though i can print out the temperature
}
}
}
The func in the seconds MVC basically looks the same as the first one so i don't understand why its crashing, it should have data.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DetailedWeatherCell", for: indexPath) as! WeatherTableViewCell
let weatherCell = timeSeries[indexPath.row]
let wc = cell
wc.timeSeries = weatherCell
return cell
}
added additional code for clarity (my FavoriteDetailedTableViewController class):
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(WeatherTableViewCell.self, forCellReuseIdentifier: "DetailedWeatherCell")
}
I think you forgot to change identifier of prototype cell in FavoritedDetailedTableViewController. In this TableViewController change it to
and it should work.
Second you maybe forgot to set your cell class here
Also delete this line from viewDidLoad
self.tableView.register(WeatherTableViewCell.self, forCellReuseIdentifier: "DetailedWeatherCell")
2 Viewcontrollers can not reuse the same prototype cell which had been created by one of two viewcontrollers
WeatherTableViewCell can't have 2 layouts in mvc1, mvc2
=> You have to create your customer cell in xib file and register a cell for UITableViewCell reuse.
I have a custom cell with some simple labels and a UIImage. Everything appears to be set correctly, and stepping through the debugger shows that everything is getting a value and even using the print in the debugger shows that the labels have text. However my table view is still empty when executed. I have been looking at this for too long and cannot figure out the problem.
Here is the cell code
class CurrentFileCell: UITableViewCell {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var statusImage: UIImageView!
#IBOutlet weak var dateLabel: UILabel!
var currentContent: AircraftContent! {
didSet{
setStyles(Constants.appStyleSetting)
self.nameLabel.text = currentContent.contentName
self.dateLabel.text = currentContent.contentStatus
self.statusImage.image = UIImage(named: "color_label_circle_green")
}
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
private func setStyles(settings: StyleSettings) {
let tableFont = UIFont(name: settings.bodyFont, size: CGFloat(settings.tableFontSize))
nameLabel.font = tableFont
dateLabel.font = tableFont
// Text color
let tableFontColor = settings.tableFontColor
nameLabel.textColor = tableFontColor
dateLabel.textColor = tableFontColor
}
Here is the ViewController code with a tableview inside.
class CurrentFilesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var content: AircraftContent?
#IBOutlet weak var currentFiles: UILabel!
#IBOutlet weak var downloadingLabel: UILabel!
#IBOutlet weak var readyLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.content = loadContent()
setStyles(Constants.appStyleSetting)
//self.tableView.reloadData()
// Do any additional setup after loading the view.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CurrentFileCell", forIndexPath: indexPath) as? CurrentFileCell
cell?.currentContent = content
return cell!
}
func loadContent() -> AircraftContent {
return (NSKeyedUnarchiver.unarchiveObjectWithFile(AircraftContent.ArchiveURL.path!) as? AircraftContent)!
}
private func setStyles(settings: StyleSettings) {
let titleFont = UIFont(name: settings.bodyFont, size: CGFloat(settings.titleFontSize))
let key = UIFont(name: settings.bodyFont, size: CGFloat(settings.tableFontSize))
currentFiles.font = titleFont
downloadingLabel.font = key
readyLabel.font = key
// Text color
let titleFontColor = settings.titleFontColor
currentFiles.textColor = titleFontColor
downloadingLabel.textColor = titleFontColor
readyLabel.textColor = titleFontColor
}
Here are some images showing the debug location where the cell is not empty, and also printing out the label which has a value, but isn't being shown during simulation.
http://imgur.com/a/dBkpe
This is an image showing the prototype cell. The cell has the correct class set as well as the identifier.
http://imgur.com/PKtFTeQ
Lastly another image showing that the prototype cell is linked to the labels within the CurrentFileCell.
http://imgur.com/nW0QUjM
Any help at all with this would be appreciated. I have tried recreating everything but continue to be stumped as it seems like everything is how it should be.
You have to implement the 'heightForRowAtIndexPath' method for the table view
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let height:CGFloat = 75
return height
}
You may consider registering the custom class as it does not appear that you did. You can do that by using the following code in the viewDidLoad of your View Controller.
tableView.registerClass(CurrentFileCell.self, forCellReuseIdentifier: "cell")
If you are using an external nib you will want to use registerNib instead like so:
tableView.registerNib(UINib(name:"ReplaceWithYourNibName", bundle: nil), forCellReuseIdentifier: "ReuseIdentifier")
Of course, replace ReplaceWithYourNibName and ReuseIdentifier with the appropriate values. In addition, if your nib is in a different bundle specify that instead of nil (nil defaults to the main bundle).
However, do not use both registerClass and registerNib as whichever one you call last will be used and they were designed to be mutually exclusive. Whenever you make a custom UITableViewCell you must use either of the two for it to work unless you have set it explicitly in the storyboard.
Also, you could instead, use prototype cells to define your custom cell, which would, I believe, automatically register the cell. But only if you did not use prototype cells make sure to use registerClass or registerNib.
Good luck! Hope this helps!
If your cell is a static cell, then you need to comment out these methods in UITableViewDataSource:
/* override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
} */
I had the same issue.
Data has values and cell rows are showing empty.
I figured it by adding
contentView.addSubview(titleLabel)
where cell values are being set.
I have an array of UIImageViews that I want to display to the screen. However, I can't seem to be able to do so. I declared my array of UIImageViews like so:
class EventCell: UITableViewCell, CellDelegate{
#IBOutlet var eventName: UILabel!
#IBOutlet var eventLocation: UILabel!
#IBOutlet var attendeesImages: [UIImageView]!
}
And I have a function that displays the EventCell contents like so:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//Dequeue a "reusable" cell
let cell = tableView.dequeueReusableCellWithIdentifier(eventCellIdentifier) as! EventCell
setCellContents(cell, indexPath: indexPath)
return cell
}
//Set contents of Event Cell.. self.events is a global array
//which have information that EventCell objects need to display
func setCellContents(cell:EventCell, indexPath: NSIndexPath!){
let item = self.events[indexPath.section]
var count = 0
cell.eventName.text = item.eventName()
cell.eventLocation.text = item.eventLocation()
cell.attendeesImage.removeAll(keepCapacity: false)//Remove old images before adding new
for value in item.attendeesImage {
let newImageView = UIImageView(image : value)
newImageView.clipsToBounds = true
newImageView.layer.cornerRadius = newImageView.frame.size.width / 2
cell.attendeesImage.append(newImageView)
println("Count inside: \(cell.attendeesImage.count)")
}
}
I printed out the count of the cell.attendeesImage to ensure that no extraneous images were being added and it seemed to prove correct. However, I have no idea why my images are not displaying. I made sure to hook the cell.attendeesImage as an IBCollection in my Storyboard (since it is an Array) in my EventCell. Any ideas for why this isn't showing up? Thanks!
You are using wrong the collection outlet "attendeesImages".
When the view is loaded, the array attendeesImages are created and initialized with the image views you have created in interface builder. But then, if you remove all that references, you have lost the link between the outlets and the real views. The new image views you are creating are not the ones in the cell. They are still subviews of the cell, but now you have not a iboutlet references to them.
The solution: don't remove the values from the array. Just modify the image in each image view.
I would like to keep the content of a UITableView cell in a separate file as I do in Objective-c even in my TodayExtension Swift table in order to wire it to the storyboard. Yet when I try to do it, it complaints it cannot find the class of the cell; this is the function I use:
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
println(indexPath)
let cell = tableView.dequeueReusableCellWithIdentifier(
TableViewConstants.cellIdentifier,
forIndexPath: indexPath) as! TodayCell
let entry = busCollection[indexPath.row]
cell.bus=entry.bus
cell.destination=entry.destination;
return cell
}
todayCell is the class in another file it reports it cannot find:
import UIKit
class TodayCell: UITableViewCell {
#IBOutlet var bus: UILabel!
#IBOutlet var stopAddress: UILabel!
#IBOutlet var destination: UILabel!
}
Importing the file, even if not needed according the the Swift documentation, moved the error in the import statement.
Programmatically:
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(todayCell.self, forCellReuseIdentifier: "todayCell")
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("todayCell", forIndexPath: indexPath) as! todayCell
// Setup
return cell
}
This should do it.
Storyboard:
If you're using prototypes, then you just have to set the prototype class to todayCell and an identifier. This identifier is used when you're creating the cell in tableView.dequeueReusableCellWithIdentifier()
I found the problem: Xcode forgot to add the new TodayCell file to the list of compile sources when I added it to the project. Once I manually did it everything worked fine - I had a funny horror trip in a list of errors in the MKStoreManager library, but all of them went away upon returning to the last commit.