Automated Row height in table cell - ios

I am trying to expand my cell when there is extra text inputed. I do not want "..." at the end I would like the cell to automatically expand. I have taken these two steps below but it is not working.
Step 1
self.tableView.dataSource = self
self.tableView.delegate = self
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
Step 2
messageLabel.numberOfLines = 0
For some reason my cell is not expanding what am I doing wrong?
import UIKit
import Foundation
struct postStruct {
let username : String!
let message : String!
let photoURL : String!
}
class GeneralChatroom: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate {
#IBOutlet weak var messageTextField: UITextField!
#IBOutlet weak var tableView: UITableView!
var generalRoomDataArr = [postStruct]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
tableView.estimatedRowHeight = 44
tableView.rowHeight = UITableViewAutomaticDimension
}
#IBAction func backButtonPressed(_ sender: UIButton) {
self.performSegue(withIdentifier: "BackToRoom", sender: nil)
}
//Message Send button is pressed data uploaded to firebase
#IBAction func sendButtonPressed(_ sender: UIButton) {
let message : String = self.messageTextField.text!
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return generalRoomDataArr.count // your number of cell here
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
//Set message label to display message
let messageLabel = cell?.viewWithTag(2) as! UILabel
messageLabel.text = generalRoomDataArr[indexPath.row].message
messageLabel.numberOfLines = 0
// your cell coding
return cell!
}
}//END CLASS
UPDATE:
I have the current constraints but my dynamic cell growth is not working. My cell is still showing "..." Can anyone help me understand why? I tried reset to suggested constraints but it is not working.

Make sure you've auto layout for the custom UITableViewCell. Change the estimatedRowHeight, try this:
tableView.estimatedRowHeight = 200

You can use the delegate method of UITableView:
func tableView(_ tableView: UITableView,heightForRowAt indexPath: IndexPath) -> CGFloat
{
return .AutomaticDimension
}
func tableView(_ tableView: UITableView,estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
{
return 60
}
But first you must set the autolayout constraint for the label w.r.t to the content view of TableViewCell.

Swift 2.3
// MARK: - TableViewDelegate Setup
extension NotificationVC : UITableViewDelegate,UITableViewDataSource {
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
}

Related

how to add header view to each of custom tableViewCells in swift

I have two custom TableViewCells. So first TableViewCell is like a recent list, it can become longer. but second cell is always stays at bottom. so i need to add UILabel that hold's secondTableViewCell. the result that i need.
import UIKit
class bagPage: UIViewController, UITableViewDelegate, UITableViewDataSource {
var itemsName: [String] = []
var itemsPhoto: [UIImage] = []
// these arrays will defined in other view controller
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row < itemsName.count{
return 165
}else{
return 50
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6 + itemsName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < itemsName.count{
let cell = tableView.dequeueReusableCell(withIdentifier: "bagTableViewCell") as? bagTableViewCell
cell?.itemName.text = itemsName.last
cell?.itemPhoto.image = itemsPhoto.last
return cell!
}
if indexPath.row == itemsName.count {
let cellTwo = tableView.dequeueReusableCell(withIdentifier: "extraBagPageTableView") as? extraBagPageTableView
// here i'm hiding views in first row
cellTwo?.textLabel?.text = "These are products that u can add to your cell"
return cellTwo!
}else{
let cellTwo = tableView.dequeueReusableCell(withIdentifier: "extraBagPageTableView") as? extraBagPageTableView
return cellTwo!
}
}
}
This is another attempt at providing a solution. Is this what you are looking for?
Here is a link to the project
https://drive.google.com/file/d/1XlSF4fGiNzOqQHauiNo7TuFhKUTrFbsJ/view?usp=sharing
Let me know if you need more help
Good evening, so I followed your image and made the code follow your convention of 1 tableview section, 2 difference cells. I tried to use your naming convention. Note I had to swap around the height values, you had them wrong way round.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var itemsName: [String] = ["Helmet", "Gloves", "Bindings", "Goggles", "Kneepads", "Boots", "Snowboard"]
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1 + itemsName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < itemsName.count{
let bagTableViewCell = tableView.dequeueReusableCell(withIdentifier: "BagTableViewCell") as? BagTableViewCell
bagTableViewCell?.productsLabel.text = itemsName[indexPath.row]
return bagTableViewCell!
} else {
let extraBagPageTableView = tableView.dequeueReusableCell(withIdentifier: "ExtraBagPageTableView") as? ExtraBagPageTableView
return extraBagPageTableView!
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath.row < itemsName.count {
return 50
} else {
return 165
}
}
}
And the tableview cells. Please note the second cell has a bad name.
class BagTableViewCell: UITableViewCell {
#IBOutlet weak var additionalProductsLabel: UILabel!
#IBOutlet weak var productsLabel: UILabel!
#IBOutlet weak var productImage: UIImageView!
}
class ExtraBagPageTableView: UITableViewCell {
}
And altogether it looks like this
And the project can be found here. (I set the permissions correctly this time :) )
TableCellWithLabel Project

What is the correct way to display random images on table view cell

I was trying to display random images on table view cell but when i scroll down and up images positions are changed.
I just added image on cell
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
let imagesArr = ["img1","img2","img3","img4"]
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDataSource,UITabBarDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let randomNumber = Int.random(in: 0...3)
let cell = tableView.dequeueReusableCell(withIdentifier: "ImageCell") as! ImageCell
cell.ImageView.image = UIImage(named: self.imagesArr[randomNumber])
return cell
}
}
I expect to get images where they were before scroll down and up
If you want to set the image once and for all, you can do the following:
class MyCell: UICollectionViewCell {
func awakeFromNib() {
super.awakeFromNib()
let randomNumber = Int.random(in: 0...3)
let imagesArr = ["img1","img2","img3","img4"]
ImageView.image = UIImage(named: imagesArr[randomNumber])
}
}
if random images should be changed if only you leave the page, then add random number in the viewDidLoad()
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
let imagesArr = ["img1","img2","img3","img4"]
var randomNumber = 0
override func viewDidLoad() {
super.viewDidLoad()
randomNumber = Int.random(in: 0...3)
}
}
extension ViewController: UITableViewDataSource,UITabBarDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ImageCell") as! ImageCell
cell.ImageView.image = UIImage(named: self.imagesArr[randomNumber])
return cell
}

How to show info on table view

Im trying to load a array of strings in a table view but the view does not recognize the array.
I have an array called Playlists (declared as global on ThirdViewController) with objects from class Playlist. When I use it on every other table view I can access every object and use it on the table view (I'm using it on ThirdViewController), but on AddToPlaylist view I can't use it. I think I'm using correctly the cells and func for table views.
This happens when I press the button "AƱadir" on player view. It should load the table view with the array info.
Here is the project (develop branch): tree/develop
import UIKit
class AddToPlaylist: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var myTableViewPlaylist: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Playlists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "hola", for: indexPath)
cell.textLabel?.text = Playlists[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
Playlists[indexPath.row].songs.append(songName)
performSegue(withIdentifier: "addedSong", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
myTableViewPlaylist.delegate = self
myTableViewPlaylist.dataSource = self
myTableViewPlaylist.reloadData()
}
}
Here is the declaration of Playlists array:
import UIKit
import AVFoundation
var favorites:[String] = []
var Playlists:[Playlist] = []
var selecPlaylist = 0
var firstOpen2 = true
class ThirdViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var myTableView2: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//print(Playlists.count)
return Playlists.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = Playlists[indexPath.row].name
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selecPlaylist = indexPath.row
performSegue(withIdentifier: "segue", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
myTableView2.delegate = self
myTableView2.dataSource = self
if firstOpen2{
crear()
firstOpen2 = false
}
myTableView2.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func crear(){
let pl1 = Playlist(name: "Prueba")
pl1?.addSong(song: songs[0])
Playlists.append(pl1!)
let pl2 = Playlist(name: "Prueba2")
pl2?.addSong(song: songs[1])
Playlists.append(pl2!)
}
}
let cell = tableView.dequeueReusableCell(withIdentifier: "yourIdentifier") as! UITableViewCell
cell.textLabel?.text = Playlists[indexPath.row].name
return cell

Swift 3.0 Textfield in a TableViewCell not showing up

I am trying to display a textfield on a tableview using a custom cell. I think I have set up the delegation protocol properly, but when loaded, the tableview doesn't show the textfield. I have added a textfield into the customcell, set the class to CustomCell, and changed the identifier to "Cell", but I am not sure what else I am missing.
view controller with tableview:
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Hello")
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomCell
cell.cellDelegate = self
cell.contentView.bringSubview(toFront: cell.textField)
cell.textField.delegate = self as? UITextFieldDelegate
cell.textField.text = "Test"
return cell
}
func didPressTextField(indexPath: IndexPath) {
print("textfield was tapped")
}
custom cell VC:
protocol CustomCellDelegate : class {
func didPressTextField(indexPath: IndexPath)
}
class CustomCell: UITableViewCell {
weak var cellDelegate: CustomCellDelegate?
var indexPath: IndexPath!
override func awakeFromNib() {
super.awakeFromNib()
self.cellDelegate = nil
// Initialization code
}
#IBOutlet weak var textField: UITextField!
#IBAction func textFieldWasTapped(_ sender: UITextField) {
self.cellDelegate?.didPressTextField(indexPath: indexPath)
}
Your data source is empty.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// data is not containing any value
return data.count
}
Check data.count it should have some data and also if that is custom cell with XIB then you need to register cell in view didload
self.tableView.register(UINib(nibName: "Your Cell XIB name", bundle: nil),
forCellWithReuseIdentifier: "Cell")
Check your data.count. it must return value greater than 0 otherwise your tableView is showing with 0 rows and nothing is display in tableView.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// debug at this point check what is value of data.count its must be greater than 0
return data.count
}

How to exchange information between 2 table view controllers in Swift? [duplicate]

This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 6 years ago.
I'm new to Swift. I have two table view controllers, one with static cells and one with dynamic ones. I basically want to let a user select his marital status on the second table view controller and send his choice back to the first table view controller (and display his selection on the cell "Marital Status"). Here is a screenshot of my storyboard:
Storyboard
Current code on second table view controller:
import UIKit
class SecondTableViewController: UITableViewController {
let maritalStatusArray: [String] = ["Single", "Married"]
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return maritalStatusArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MaritalStatusCell", for: indexPath)
cell.textLabel?.text = maritalStatusArray[indexPath.row]
return cell
}
}
My guess is that I have to add a segue from the dynamic cell of the second view controller back to the first one. Is that right ?
Supposing this is the way to do it, I have afterwards to update the text of the static label to include the choice made by the user. Any ideas ?
There few ways by which you can implement the callback functionality to pass data.
Delegate
Using Block CallBack
Post Notification
But I would suggest to use delegate which is best way, Post Notification is also a way but I do not want to prefer.
You can use custom delegate to do this:
ViewController.swift:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SecondViewControllerProtocol {
#IBOutlet weak var userInfoTableView: UITableView!
var userInfoArray: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
userInfoArray = ["Marital Status","Canton","Commune","Religion"]
self.userInfoTableView?.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let userInfoCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
userInfoCell.textLabel?.text = userInfoArray[indexPath.row]
if indexPath.row == 0{
userInfoCell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
}
return userInfoCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0{
let secondVC = storyboard?.instantiateViewController(withIdentifier: "SecondViewControllerIdentifier") as! SecondViewController
secondVC.statusDelegate = self
self.navigationController?.present(secondVC, animated: true, completion: nil)
}
}
func changeMaritalStatus(type: String){
let maritalStatusCell = userInfoTableView.cellForRow(at: IndexPath(row:0 , section:0))
maritalStatusCell?.textLabel?.text = String("Marital Status: \(type)")
}
}
SecondViewController.swift:
import UIKit
protocol SecondViewControllerProtocol {
func changeMaritalStatus(type: String)
}
class SecondViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var maritalStatusTableView: UITableView!
var maritalStatusArray: [String] = []
var statusDelegate : SecondViewControllerProtocol? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
maritalStatusArray = ["Single","Married","Divorced"]
self.maritalStatusTableView.register(UITableViewCell.self, forCellReuseIdentifier: "maritalStatuscell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let maritalStatusInfoCell = tableView.dequeueReusableCell(withIdentifier: "maritalStatuscell", for: indexPath)
let infoLabel: UILabel = UILabel.init(frame: CGRect(x: 10, y: 5, width: 250, height: 50))
infoLabel.text = maritalStatusArray[indexPath.row]
maritalStatusInfoCell.addSubview(infoLabel)
return maritalStatusInfoCell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
statusDelegate?.changeMaritalStatus(type: maritalStatusArray[indexPath.row])
self.dismiss(animated: true, completion: nil)
}
}
GitHub link:
https://github.com/k-sathireddy/CustomDelegatesSwift
Output:-

Resources