Dynamic Type does not work with tableView.dequeueReusableCell(withIdentifier:) - xcode

I'm experiencing a quite strange behaviour for my UITableViewCells with style .subtitle regarding Dynamic Type. When using
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DesignElementCell", for: indexPath) //Dynamic Type does not work properly in this case
cell.textLabel?.text = "Test"
cell.detailTextLabel?.text = "Test"
return cell
}
the output looks like
As you can see the header text is scaled fine, while cell labels are not. When using
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .subtitle, reuseIdentifier: "DesignElementCell")
cell.textLabel?.text = "Test"
cell.detailTextLabel?.text = "Test"
return cell
}
Everything works fine:
The strangest thing in the first case is, that when I change dynamic type size in settings and head back to my app, suddenly everything seems to work as long as I'm not popping my ViewController. Does anyone experienced something similar? Have a nice day :)

First, check if you registered cell, and set delegate&dataSource of tableView in ViewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.register(Cell.self, forCellReuseIdentifier:"CellIdentifier")
Then, define rowHeight & estimatedRowHeight of tableView in ViewDidLoad()
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 150

Related

swift 3: UITable cell multiple lines issue

So Im attempting to create a multiple line text for the suitable cell detailedTitle however when I set the cell.numberOfLines = 0 I get multiple lines but without correct spacings for the cells. I have also tried calling cellAutoDimentions but it made no difference
cell.detailTextLabel?.numberOfLines = 0
I Get the following result when I run that code in my program
enter image description here
as you can see the text if getting pushed out of the cell's bounds in this case I'm talking about the top and bottom not the right side, that issue i know how to fix by changing the CGRect. Also the code doesn't allow for more than 2 lines
UPDATE:
The following is the entire section of my code
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itorStorage.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.messageField.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! MessageCustomCell
cell.backgroundColor = LightBlue
cell.textLabel?.text = itorStorage[indexPath.row].name
cell.textLabel?.textColor = .white
cell.detailTextLabel?.text = itorStorage[indexPath.row].text
cell.detailTextLabel?.textColor = .white
cell.pic.image = itorStorage[indexPath.row].image
cell.timeStamp.text = itorStorage[indexPath.row].time
cell.detailTextLabel?.numberOfLines = 0
cell.detailTextLabel?.lineBreakMode = .byWordWrapping
return cell
}
override init() {
super.init()
messageField.delegate = self
messageField.dataSource = self
messageField.tableFooterView = UIView(frame: CGRect.zero)
messageField.rowHeight = UITableViewAutomaticDimension
messageField.allowsSelection = false
self.messageField.register(MessageCustomCell.self, forCellReuseIdentifier: "Cell")
ratingView.didFinishTouchingCosmos = didTouchCosmos
}
I think you need to implement estimatedHeightForRowAt as well as setting rowHeight to UITableViewAutomaticDimension. Something like this:
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
}
override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 120.0
}

Swift 1.2 - List type undeclared

In my TableViewController i have this line of code
override func tableView(tableView: UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
In this block i try to get a list of objects
let list = frc.objectAtIndexPath(indexPath) as! List
But i get this warning:
Use of undeclared type "List"
Anybody knows how to deal with it?
This is the full code:
var frc: NSFetchedResultsController = NSFetchedResultsController()
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",
forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
let list = frc.objectAtIndexPath(indexPath) as! list
cell.textLabel?.text = list.name
cell.detailTextLabel?.text = list.url
return cell
}
Any help is welcome!!
Greetings and Thanks
In the tutorial, Jason creates an entity called "List" in his Data Model file and then creates a class called List.
The following link starts the video just after he creates this file.
https://youtu.be/GeM7Zw12wbM?t=5m30s
You may have named your entity differently.
I named mine Record, since I'm storing records.
So my code will look like the following:
var frc: NSFetchedResultsController = NSFetchedResultsController()
override func tableView(tableView: UITableView,
cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell",
forIndexPath: indexPath) as! UITableViewCell
// Configure the cell...
// ALL occurrences of "list" are instead "record"
// ALL occurrences of "List" are instead "Record"
let record = frc.objectAtIndexPath(indexPath) as! Record
cell.textLabel?.text = record.name
cell.detailTextLabel?.text = record.url
return cell
}

Registering a Nib

I would like to set the values of detail labels in the View Controller file using an array with index path.row .
In a previous post:
[link][1]
someone helpfully suggested I use
var nib = UINib(nibName: "YourCellSubclass", bundle: nil)
tableView.registerNib(nib, forCellReuseIdentifier: "cell")
however I'm new to using this and came across an error:
Cannot invoke registerNib with an argument list of type 'UINib, forCellReuseIdentifier: 'String'
My best guess would be, instead of this:
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
Should be:
var cell: YourSubClass = self.tableView.dequeueReusableCellWithIdentifier("cell") as YourSubClass
This compiles in Xcode 7:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! MyCellSubclass
return cell
}
If you have multiple kinds of cells, you can go with:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let aCell = table.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
if let myCell = aCell as? MyCellSubclass {
return myCell
}
return aCell
}

UITableView with 3 custom cells but 1 different

I have a TableView and I have created custom cells for that TableView with images, labels..etc, But I want one cell to be different than the others with It's own content ( cells will get their data from a backend).
So how to create 2 different types of cells in the same TableView, and how to arrange them, for example put 1 type of cell between 2 others ?
Edit: My UITableView Class:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let myCell: CellTableViewCell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as! CellTableViewCell
let otherCell: OtherCellTableViewCell = tableView.dequeueReusableCellWithIdentifier("otherCell", forIndexPath: indexPath) as! OtherCellTableViewCell
// Configure the cell...
return myCell
}
If you're using a storyboard, just drag another UITableViewCell into the table view to be used as a prototype. Give it a unique and subclass (if necessary). In -tableView:cellForRowAtIndexPath: dequeue either the cell you're currently dequeueing, or this new one.
If you're not using a storyboard you'll need to either
-registerClass:forHeaderFooterViewReuseIdentifier: or
-registerNib:forHeaderFooterViewReuseIdentifier: to make your other cell style available to the table view.
Here's a modified version of your code that should work:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if condition {
let myCell: CellTableViewCell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as! CellTableViewCell
// Configure the cell...
return myCell
}
else {
let otherCell: OtherCellTableViewCell = tableView.dequeueReusableCellWithIdentifier("otherCell", forIndexPath: indexPath) as! OtherCellTableViewCell
// Configure the cell...
return otherCell
}
}

Xcode - cellForRowAtIndexpath - initialising cell

What's the difference between this:
var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
And this:
var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
They both seem t work fine for me.
PS: I know this seems to be an amateur question but i'm beginner in Xcode, so no reason to be a smug.
When you write :
var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
You are initializing a new cell using its constructor.
And when you write :
var cell = self.tableView.dequeueReusableCellWithIdentifier("cell")
You are dequeuing a cell, so you are assuming your cell with the identifier cell has been already registered in the tableView.
Typically, if the cell was designed in Interface Builder and set as a prototype cell or if you have registered your cell for reuse using the method self.tableView.registerClass(MyCell.classForCoder(), forCellReuseIdentifier: "cell") you won't need to use the constructor because it is already initialized in the tableView.
But if your cell is designed programmatically such as creating UILabel, UIImage or whatever components, you will have to use the constructor instead, and then use the dequeue method.
So, if you have to use the constructor (because you're initializing everything by code) your code will look like this :
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
}
cell.cellLabel.text = "Hello world"
cell.cellImage.image = UIImage(named: "funny_cat.jpg")
return cell
}
But if your cell was registered for reuse or if it is a prototype cell you will just have to use
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
cell.cellLabel.text = "Hello world"
cell.cellImage.image = UIImage(named: "funny_cat.jpg")
return cell
}
I think the best place to look how tableview work, you should look the official documentation here : Table View Programming Guide for iOS

Resources