TableView Determine Third Cell From Top - swift

I constantly am trying to determine the third cell from the top of my table view. Basically, what that means is, the third cell from the top will always look different from all the others (i.e. the text color will change etc.).
I figured since the cells are reused, I would always be able to access the third cell like this:
    
if (indexPath.row == 2) {
    
    }
Unfortunately, it doesn't seem to be working like that. When I go ahead and print the indexPath.row the numbers continue to increase all the way from 0 to 12... Now this is understandable since it is that cells row, but how may I go about accessing the third row always from the top. Here is the original approach I took:
    
override func scrollViewDidScroll(scrollView: UIScrollView) {
    
        let indexPath: NSIndexPath = self.tableView.indexPathsForVisibleRows![0]
            
        if (indexPath.row == 2) {
          // Print or whatever
    
            }
        }
    }
So how can I go about accessing the third row always from the top of the tableView?
Thank you!

Here is an example project. I tried running it in the simulator and it seems to work fine.
Here is a screenshot of XCode so you can see Main.Storyboard.
Also here is a copy of the code in ViewController.swift:
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
var indexOfThirdVisible: Int!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
self.navigationController?.navigationBar.barStyle = .BlackTranslucent
self.navigationController?.navigationBar.tintColor = UIColor.orangeColor()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func scrollViewDidScroll(scrollView: UIScrollView) {
let indexPath = self.tableView.indexPathsForVisibleRows![0]
indexOfThirdVisible = indexPath.row + 2
let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexOfThirdVisible, inSection: indexPath.section)) as! TableViewCell
cell.label.textColor = UIColor.orangeColor()
let cellAbove = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexOfThirdVisible - 1, inSection: indexPath.section)) as! TableViewCell
let cellBelow = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: indexOfThirdVisible + 1, inSection: indexPath.section)) as! TableViewCell
cellAbove.label.textColor = UIColor.whiteColor()
cellBelow.label.textColor = UIColor.whiteColor()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 100
}
// heightForRowAtIndexPath
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
// configure cell
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell")!
return cell
}
}
Here is TableViewCell.swift:
import UIKit
class TableViewCell: UITableViewCell {
#IBOutlet weak var label: 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
}
}
Sorry if the indentation is messed up.
Have a good day and let me know if you need any more help!

I just implemented only logic, you can customise it little bit according to you.
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
let indexPath : NSIndexPath = (tv.indexPathsForVisibleRows as! NSArray).objectAtIndex(0) as! NSIndexPath
let thirdRow = indexPath.row + 2
if thirdRow <= dataArr.count{// dataArr is your no of rows
let thirdIndexPath = NSIndexPath(forRow: thirdRow, inSection: 0)
let cell = tv.cellForRowAtIndexPath(thirdIndexPath)
// ---- here you can perform any task with third cell----
}
}
And please let me know if anything is wrong

Related

toggle button with boolean in UITableView Swift

I would like to add a boolean toggle to know whether the button has been pressed (will save this value to core data (also would like to save cell data to core data if true and delete from core data if false)) I am not sure how to do this. any help would be greatly appreciated. if all the code from the view controller is required leave a comment and I will do so (I have setup xcdatamodel already).
#IBAction func buttonTapped(_ sender:UIButton) {
var superView = sender.superview
while !(superView is UITableViewCell) {
superView = superView?.superview
}
let cell = superView as! UITableViewCell
if let indexpath = tableView.indexPath(for: cell){
print(indexpath)
}
}
Well I build a simple project and I figured something out using protocols,
First you define a protocol like this:
protocol cellDidRequestSaving {
func saveOrDelete(indexpath : Int)
}
First in your cell you define you button like this :
class TableViewCell: UITableViewCell {
var delegate: cellDidRequestSaving?
var indexPath = 0 //come from the parent
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
}
#IBAction func didTap(_ sender: Any) {
// this protocol defined in the parent
delegate?.saveOrDelete(indexpath: indexPath)
}
}
now in you tableViewController you use the protocol like this:
class TableViewController: UITableViewController, cellDidRequestSaving {
var cellStat = [Int:Bool]()
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
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 3
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.indexPath = indexPath.row
cell.delegate = self
// Configure the cell...
return cell
}
func saveOrDelete(indexpath: Int) {
if let status = cellStat[indexpath], status {
print(indexpath, "delete")
cellStat[indexpath] = !status
}
else {
print(indexpath, "save")
cellStat[indexpath] = true
}
}
This is a simple project but you can get the hole idea about how to do it. Also, notice the protocol definition and usage so you wont miss anything.
and the out put is this
Add a property to your custom cell, for example:
var indexPath: IndexPath = IndexPath(row: -1, section: -1) //The -1 just know when it is not set yet
And in cellForRow in your tableView:
cell.indexpath = indexPath
Supposing that buttonTapped is defined in your custom cell class:
#IBAction func buttonTapped(_ sender:UIButton) {
print(indexpath)
}
Add a delegate method to your cell - (void)myCell:(MyCell *)cell didTapButton:(UIButton *)button
So then in your VC you can work backwards from the cell object.
- (void)myCell:(MyCell *)cell didTapButton:(UIButton *)button
{
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
MyObject *object = [self.dataSource objectAtIndexPath:indexPath];
// Do something with the knowledge that the button in the cell for the object was tapped...
// For example
object.tapped = YES;
[object.managedObjectContext save:NULL];
}
Just need to convert to swift ;)

Selecting row in tableview, removes custom cell

I have a Viewcontroller with a Searchbar at the top with a tableview below. The tableview has a custom cell with 2 labels in it. My problem is that when i run the app and i select a row/cell everything inside the cell disappears. I then force the blank cell outside the visible area of the tableview, so it will be re-used. That's when everything inside the cell is back. Does anyone know why it behaves like this?
My Custom cell class (ContactCell.swift):
import UIKit
class ContactCell: UITableViewCell {
#IBOutlet var lblContactName: UILabel!
#IBOutlet var lblContactTitle: 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 ViewDidLoad function:
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
My Delegate and Datasource:
extension contactsTabelViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("contactCell", forIndexPath: indexPath) as! ContactCell
if let label = cell.lblContactName{
label.text = "This is a name"
}
if let label3 = cell.lblContactTitle{
label3.text = "This is a title"
}
return ContactCell()
}
}
The problem that caused this problem was that i returned ContactCell() instead of the variable cell
Solution was:
Change this:
return ContactCell()
to this:
return cell
in the cellForRowAtIndexPath function.

How to make a segue by a tableViewDelegate

I'd like to create a segue from a tableViewDelegate cell to an other view. This is my code:
import UIKit
class CoriViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
#IBOutlet var tableView: UITableView!
var elencoCori : SquadraModel! //This var contains label and array
override func viewDidLoad()
{
super.viewDidLoad()
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
InterfaceManager.sharedInstance.putBlurBackgroundToTableView(self.view, tableView: self.tableView)
self.tableView.tableFooterView = UIView(frame:CGRectZero)
self.tableView.backgroundColor = UIColor.clearColor()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.elencoCori.cori.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell : UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
let coro = elencoCori.cori[indexPath.row]
cell.textLabel?.text = coro.marker
cell.backgroundColor = UIColor.clearColor()
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
return cell
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)
{
self.performSegueWithIdentifier("toDettaglioController", sender: self)
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
Now the problem: how I could set a prepareForSegue that send to the secondView? In other circumstances I would have solved the problem like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if segue.identifier == "toDettaglioController"
{
if let indexPath = tableView.indexPathForSelectedRow()
{
let controller = segue.destinationViewController as! Dettaglio controller
controller.coro = elencoCori.cori[indexPath.row]
}
}
}
but I know the this doesn't work and I have to use a delegate method. So can everyone help me with a step-by-step guide?
On your didSelectRowAtIndexPath method call performSegueWithIdentifier and pass the indexPath as your sender.
Then in prepareForSegue you can do if let indexPath = sender as NSIndexPath and setup your controller.
Suppose you have One UITableViewController-T and Two UIViewControllers-A and B.
Now suppose you want to go from T to A when cell 0 is clicked, and go from T to B when cell 1 is clicked.
Step 1 : Connect segue from T to A and name that segue "segueToA"
Step 2 : Connect segue from T to B and name that segue "segueToB"
Step 3 : Got to didSelectRowAtIndexPath in T and put if-else
if(indexPath.row == 0){
self.performSegueWithIdentifier("segueToA", sender: nil)
}else{
self. performSegueWithIdentifier("segueToB", sender: nil)
}
That's it.
Update: Here is a Sample Project.

creating an action when tableView cell in swift touched or clicked

I a tableView class that displays a text in cells. I need to be able to touch/click text in a cell and create an action (display the next table view) based on the text in the cell clicked. Class is as follows:
import UIKit
class SecondViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
let textCellIdentifier = "TextCell"
let catRet = XnYCategories.mainCats("sport")
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
// MARK: UITextFieldDelegate Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return catRet.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! UITableViewCell
let row = indexPath.row
cell.textLabel?.text = catRet[row]
return cell
}
// MARK: UITableViewDelegate Methods
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let row = indexPath.row
println(catRet[row])
}
}
I would like to add upon Linus answer, as it has deprecated in latest Swift addition.
Swift 4:
In the myCell add this Recogniser,
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(yourVC.yourfuncName))
myCell.addGestureRecognizer(tapGesture)
In the same VC, implement your function,
func yourfuncName(){
//Do whatever you want here
}
If you have a hard-coded amount of cells, you can create a UIGestureRecognizer and add it to the cell created:
let tapGesture = UITapGestureRecognizer(target: self, action: "tapped:")
myCell.addGestureRecognizer(tapGesture)
In it's target you can do whatever you want to do.
You can get your cell using
let currentCell = tableView.cellForRowAtIndexPath(indexPath) as UITableViewCell
To get your text you could use
var selectedText = currentCell.textLabel?.text

creating custom tableview cells in swift

I have a custom cell class with a couple of IBOutlets. I have added the class to the storyboard. I have connected all my outlets. my cellForRowAtIndexPath function looks like this:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as SwipeableCell
cell.mainTextLabel.text = self.venueService.mainCategoriesArray()[indexPath.row]
return cell
}
Here is my custom cell class:
class SwipeableCell: UITableViewCell {
#IBOutlet var option1: UIButton
#IBOutlet var option2: UIButton
#IBOutlet var topLayerView : UIView
#IBOutlet var mainTextLabel : UILabel
#IBOutlet var categoryIcon : UIImageView
init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
}
When I run the app, all my cell are empty. I have logged out self.venueService.mainCategoriesArray() and it contains all the correct strings. I have also tried putting an actual string equal to the label, and that produces the same result.
What am I missing? Any help is appreciated.
Custom Table View Cell Example
Tested with Xcode 9 (edit also tested on 11 / 12 Beta 2) and Swift 4 (edit: also tested on 5.2)
The asker of the original question has solved their problem. I am adding this answer as a mini self contained example project for others who are trying to do the same thing.
The finished project should look like this:
Create a new project
It can be just a Single View Application.
Add the code
Add a new Swift file to your project. Name it MyCustomCell.swift. This class will hold the outlets for the views that you add to your cell in the storyboard.
import UIKit
class MyCustomCell: UITableViewCell {
#IBOutlet weak var myView: UIView!
#IBOutlet weak var myCellLabel: UILabel!
}
We will connect these outlets later.
Open ViewController.swift and make sure you have the following content:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// These strings will be the data for the table view cells
let animals: [String] = ["Horse", "Cow", "Camel", "Sheep", "Goat"]
// These are the colors of the square views in our table view cells.
// In a real project you might use UIImages.
let colors = [UIColor.blue, UIColor.yellow, UIColor.magenta, UIColor.red, UIColor.brown]
// Don't forget to enter this in IB also
let cellReuseIdentifier = "cell"
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
// number of rows in table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.animals.count
}
// create a cell for each table view row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:MyCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! MyCustomCell
cell.myView.backgroundColor = self.colors[indexPath.row]
cell.myCellLabel.text = self.animals[indexPath.row]
return cell
}
// method to run when table view cell is tapped
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
}
}
Setup the storyboard
Add a Table View to your view controller and use auto layout to pin it to the four sides of the View Controller. Then drag a Table View Cell onto the Table View. And then drag a View and a Label onto the Prototype cell. (You may need to select the Table View Cell and manually set the Row Height to something taller in the Size inspector so that you have more room to work with.) Use auto layout to fix the View and the Label how you want them arranged within the content view of the Table View Cell. For example, I made my View be 100x100.
Other IB settings
Custom class name and Identifier
Select the Table View Cell and set the custom class to be MyCustomCell (the name of the class in the Swift file we added). Also set the Identifier to be cell (the same string that we used for the cellReuseIdentifier in the code above.
Hook Up the Outlets
Control drag from the Table View in the storyboard to the tableView variable in the ViewController code.
Do the same for the View and the Label in your Prototype cell to the myView and myCellLabel variables in the MyCustomCell class.
Finished
That's it. You should be able to run your project now.
Notes
The colored views that I used here could be replaced with anything. An obvious example would be a UIImageView.
If you are just trying to get a TableView to work, see this even more basic example.
If you need a Table View with variable cell heights, see this example.
This is for who are working custom cell with .xib
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let identifier = "Custom"
var cell: CustomCell! = tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomCel
if cell == nil {
tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: identifier)
cell =tableView.dequeueReusableCellWithIdentifier(identifier) as? CustomCell
}return cell}
I have the same problem.
Generally what I did is the same as you.
class dynamicCell: UITableViewCell {
#IBOutlet var testLabel : UILabel
init(style: UITableViewCellStyle, reuseIdentifier: String) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
and in the uitableviewcell method:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell :dynamicCell = tableView.dequeueReusableCellWithIdentifier("cell") as dynamicCell
cell.testLabel.text = "so sad"
println(cell.testLabel)
return cell;
}
and yeah the tableview shows nothing! But guess what, it actually shows something...because the log I get from the println(cell.testLabel) shows that all the Labels are actually displayed out.
BUT! their Frames is strange, which have something like this:
frame = (0 -21; 42 21);
so it has a (0,-21) as (x,y), so that means the label just appears at somewhere outside the bound of the cell.
so I try to add adjust the frame manually like this:
cell.testLabel.frame = CGRectMake(10, 10, 42, 21)
and sadly, it doesn't work.
---------------update after 10 min -----------------
I DID IT.
so, it seems that the problem comes from the Size Classes.
Click on your .storyboard file and go to the File Inspector Tab
UNCHECK THE Size Classes checkbox
and finally, my "so sad"Label comes out!
Thanks for all the different suggestions, but I finally figured it out. The custom class was set up correctly. All I needed to do, was in the storyboard where I choose the custom class: remove it, and select it again. It doesn't make much sense, but that ended up working for me.
Last Updated Version is with xCode 6.1
class StampInfoTableViewCell: UITableViewCell{
#IBOutlet weak var stampDate: UILabel!
#IBOutlet weak var numberText: UILabel!
override init?(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init(coder aDecoder: NSCoder) {
//fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Details
Xcode Version 10.2.1 (10E1001), Swift 5
Solution
import UIKit
// MARK: - IdentifiableCell protocol will generate cell identifier based on the class name
protocol Identifiable: class {}
extension Identifiable { static var identifier: String { return "\(self)"} }
// MARK: - Functions which will use a cell class (conforming Identifiable protocol) to `dequeueReusableCell`
extension UITableView {
typealias IdentifiableCell = UITableViewCell & Identifiable
func register<T: IdentifiableCell>(class: T.Type) { register(T.self, forCellReuseIdentifier: T.identifier) }
func register(classes: [Identifiable.Type]) { classes.forEach { register($0.self, forCellReuseIdentifier: $0.identifier) } }
func dequeueReusableCell<T: IdentifiableCell>(aClass: T.Type, initital closure: ((T) -> Void)?) -> UITableViewCell {
guard let cell = dequeueReusableCell(withIdentifier: T.identifier) as? T else { return UITableViewCell() }
closure?(cell)
return cell
}
func dequeueReusableCell<T: IdentifiableCell>(aClass: T.Type, for indexPath: IndexPath, initital closure: ((T) -> Void)?) -> UITableViewCell {
guard let cell = dequeueReusableCell(withIdentifier: T.identifier, for: indexPath) as? T else { return UITableViewCell() }
closure?(cell)
return cell
}
}
extension Array where Element == UITableViewCell.Type {
var onlyIdentifiables: [Identifiable.Type] { return compactMap { $0 as? Identifiable.Type } }
}
Usage
// Define cells classes
class TableViewCell1: UITableViewCell, Identifiable { /*....*/ }
class TableViewCell2: TableViewCell1 { /*....*/ }
// .....
// Register cells
tableView.register(classes: [TableViewCell1.self, TableViewCell2.self]. onlyIdentifiables)
// Create/Reuse cells
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (indexPath.row % 2) == 0 {
return tableView.dequeueReusableCell(aClass: TableViewCell1.self, for: indexPath) { cell in
// ....
}
} else {
return tableView.dequeueReusableCell(aClass: TableViewCell2.self, for: indexPath) { cell in
// ...
}
}
}
Full Sample
Do not forget to add the solution code here
import UIKit
class ViewController: UIViewController {
private weak var tableView: UITableView?
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
}
}
// MARK: - Setup(init) subviews
extension ViewController {
private func setupTableView() {
let tableView = UITableView()
view.addSubview(tableView)
self.tableView = tableView
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
tableView.register(classes: [TableViewCell1.self, TableViewCell2.self, TableViewCell3.self].onlyIdentifiables)
tableView.dataSource = self
}
}
// MARK: - UITableViewDataSource
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int { return 1 }
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 20 }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch (indexPath.row % 3) {
case 0:
return tableView.dequeueReusableCell(aClass: TableViewCell1.self, for: indexPath) { cell in
cell.textLabel?.text = "\(cell.classForCoder)"
}
case 1:
return tableView.dequeueReusableCell(aClass: TableViewCell2.self, for: indexPath) { cell in
cell.textLabel?.text = "\(cell.classForCoder)"
}
default:
return tableView.dequeueReusableCell(aClass: TableViewCell3.self, for: indexPath) { cell in
cell.textLabel?.text = "\(cell.classForCoder)"
}
}
}
}
Results
Uncheck "Size Classes" checkbox works for me as well, but you could also add the missing constraints in the interface builder. Just use the built-in function if you don't want to add the constraints on your own. Using constraints is - in my opinion - the better way because the layout is independent from the device (iPhone or iPad).
It is Purely swift notation an working for me
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cellIdentifier:String = "CustomFields"
var cell:CustomCell? = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as? CustomCell
if (cell == nil)
{
var nib:Array = NSBundle.mainBundle().loadNibNamed("CustomCell", owner: self, options: nil)
cell = nib[0] as? CustomCell
}
return cell!
}
[1] First Design your tableview cell in StoryBoard.
[2] Put below table view delegate method
//MARK: - Tableview Delegate Methods
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return <“Your Array”>
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
var totalHeight : CGFloat = <cell name>.<label name>.frame.origin.y
totalHeight += UpdateRowHeight(<cell name>.<label name>, textToAdd: <your array>[indexPath.row])
return totalHeight
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell : <cell name>! = tableView.dequeueReusableCellWithIdentifier(“<cell identifier>”, forIndexPath: indexPath) as! CCell_VideoCall
if(cell == nil)
{
cell = NSBundle.mainBundle().loadNibNamed("<cell identifier>", owner: self, options: nil)[0] as! <cell name>;
}
<cell name>.<label name>.text = <your array>[indexPath.row] as? String
return cell as <cell name>
}
//MARK: - Custom Methods
func UpdateRowHeight ( ViewToAdd : UILabel , textToAdd : AnyObject ) -> CGFloat{
var actualHeight : CGFloat = ViewToAdd.frame.size.height
if let strName : String? = (textToAdd as? String)
where !strName!.isEmpty
{
actualHeight = heightForView1(strName!, font: ViewToAdd.font, width: ViewToAdd.frame.size.width, DesignTimeHeight: actualHeight )
}
return actualHeight
}
Set tag for imageview and label in cell
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return self.tableData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("imagedataCell", forIndexPath: indexPath) as! UITableViewCell
let rowData = self.tableData[indexPath.row] as! NSDictionary
let urlString = rowData["artworkUrl60"] as? String
// Create an NSURL instance from the String URL we get from the API
let imgURL = NSURL(string: urlString!)
// Get the formatted price string for display in the subtitle
let formattedPrice = rowData["formattedPrice"] as? String
// Download an NSData representation of the image at the URL
let imgData = NSData(contentsOfURL: imgURL!)
(cell.contentView.viewWithTag(1) as! UIImageView).image = UIImage(data: imgData!)
(cell.contentView.viewWithTag(2) as! UILabel).text = rowData["trackName"] as? String
return cell
}
OR
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "imagedataCell")
if let rowData: NSDictionary = self.tableData[indexPath.row] as? NSDictionary,
urlString = rowData["artworkUrl60"] as? String,
imgURL = NSURL(string: urlString),
formattedPrice = rowData["formattedPrice"] as? String,
imgData = NSData(contentsOfURL: imgURL),
trackName = rowData["trackName"] as? String {
cell.detailTextLabel?.text = formattedPrice
cell.imageView?.image = UIImage(data: imgData)
cell.textLabel?.text = trackName
}
return cell
}
see also TableImage loader from github
The actual Apple reference documentation is quite comprehensive
https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/CreateATableView.html#//apple_ref/doc/uid/TP40015214-CH8-SW2
Scroll down until you see this part