Tableview cell randomly place string in empty textview - swift

In my swift code below there is a add button pressed to add another tableview cell. The problem is that in the sixth tableview cell that is added the number 1 is just randomly there and this problem would repeat every time another cell is added. You can see what I am talking about in the gif below. What I am looking for in a answer is just getting the cell added with nothining in the text view.
import UIKit
/*
*/
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
var addBTN = UIButton()
var arr = [nil] as [Any?]
var currentIndex = 0
var arrayValues = [Int]()
var index = Int()
var pic = UIImageView()
var cellCount = 0
var tableview = UITableView()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 118
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTv
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
[addBTN].forEach{
$0.translatesAutoresizingMaskIntoConstraints = false
view.addSubview($0)
}
tableview.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height * 0.8)
addBTN.frame = CGRect(x: view.frame.width / 2, y: view.frame.height * 0.8, width: view.frame.width / 2 , height: view.frame.height / 5)
addBTN.backgroundColor = .systemTeal
view.addSubview(tableview)
tableview.register(CustomTv.self, forCellReuseIdentifier: "cell")
tableview.delegate = self
tableview.dataSource = self
pic.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height )
addBTN.addTarget(self, action: #selector(newCell), for: .touchDown)
addBTN.setTitle("New cell", for: .normal)
}
#objc func newCell(){
cellCount += 1 // update the value
arr.append(1)
tableview.beginUpdates()
tableview.insertRows(at: [IndexPath(row: arr.count - 1, section: 0)], with: .automatic) /// animate the insertion
tableview.endUpdates()
}
}
class CustomTv: UITableViewCell {
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width , height: 110))
view.backgroundColor = .green
return view
}()
lazy var txt : UITextField = {
let btn = UITextField(frame: CGRect(x: 150-25, y: 60, width: 100 , height: 50))
btn.backgroundColor = .orange
return btn
}()
override func layoutSubviews() {
backView.clipsToBounds = true
backView.frame = CGRect(x: 0, y: 6, width: bounds.maxX , height: 110)
addSubview(backView)
backView.addSubview(txt)
}
}

implement the prepareForReuse method inside the cell class
and within the method clear the text field
override func prepareForReuse() {
// clear the text field
}

Related

delete tableviewcell from button within inside the cell

I want my swift code to delete the tableview cell within the cell using the blue button. You can see a example of what I am trying to below in the gif. I also have a indexPath selection var. You should probably have to delete it in the deleteCell func also I assume you would use a tag. All the code is in below no need for storyboard.
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource, UIImagePickerControllerDelegate & UINavigationControllerDelegate {
var arr = [1,1,3,3]
var tableview = UITableView()
var selectedIndexPath = IndexPath(row: 0, section: 0)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 118
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! customtv
return cell
}
#objc func deleteCell(){
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableview.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height * 0.8)
view.addSubview(tableview)
tableview.register(customtv.self, forCellReuseIdentifier: "cell")
tableview.delegate = self
tableview.dataSource = self
}
}
class customtv: UITableViewCell {
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width , height: 110))
view.backgroundColor = .green
return view
}()
lazy var btn : UIButton = {
let btn = UIButton(frame: CGRect(x: 50, y: 6, width: 100 , height: 110))
btn.backgroundColor = .blue
return btn
}()
override func layoutSubviews() {
backView.clipsToBounds = true
backView.frame = CGRect(x: 0, y: 6, width: bounds.maxX , height: 110)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(animated, animated: true)
addSubview(backView)
backView.addSubview(btn)
}
}
Here's my solution:
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource, CustomTvCellDelegate, UIImagePickerControllerDelegate & UINavigationControllerDelegate {
var cellCount = 2
var tableview = UITableView()
var selectedIndexPath = IndexPath(row: 0, section: 0)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellCount // use a variable here so you can change it as you delete cells, else it will crash
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 118
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomTv
cell.delegate = self
return cell
}
func deleteCell(_ customTV: CustomTv, location: CGPoint) {
// put the button location in an index path array
var deleteArray = [IndexPath]()
if let indexPath = tableview.indexPathForRow(at: location) {
deleteArray.append(indexPath)
}
cellCount -= 1 // update the row count as you delete a cell
// delete the row using the delete array with a fade animation
tableview.deleteRows(at: deleteArray, with: .fade)
}
override func viewDidLoad() {
super.viewDidLoad()
tableview.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height * 0.8)
view.addSubview(tableview)
tableview.register(CustomTv.self, forCellReuseIdentifier: "cell")
tableview.delegate = self
tableview.dataSource = self
}
}
// you need to declare a cell delegate that will let your tableview know when the button was tapped on the cell
protocol CustomTvCellDelegate: AnyObject {
func deleteCell(_ customTV: CustomTv, location: CGPoint)
}
class CustomTv: UITableViewCell { // it's good form to Pascal case your class name ;)
weak var delegate: CustomTvCellDelegate? // make that delegate a property of your cell
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width , height: 110))
view.backgroundColor = .green
return view
}()
lazy var btn : UIButton = {
let btn = UIButton(frame: CGRect(x: 50, y: 6, width: 100 , height: 110))
btn.backgroundColor = .blue
return btn
}()
override func layoutSubviews() {
backView.clipsToBounds = true
backView.frame = CGRect(x: 0, y: 6, width: bounds.maxX , height: 110)
// moved these calls here instead of on setSelected(_selected:animated:)
addSubview(backView)
backView.addSubview(btn)
btn.addTarget(self, action:#selector(self.deleteCell), for: .touchUpInside)
}
#objc func deleteCell(sender: UIButton){
// let your cell delegate (tableview) know what the button got tapped, you need to pass the button here)
let buttonLocation = sender.superview?.convert(sender.frame.origin, to: nil) ?? CGPoint.zero
delegate?.deleteCell(self, location: buttonLocation)
}
}

Adding a Table View Cell when a button is pressed

I want my swift code to add a another tableview cell when the button is pressed. Right now there are 2 tableview cells. The button is the orange button that when pressed should add a 3rd green tabview cell. The func to add the 3rd cell is addCell. Look at numberOfRowsInSelection as well for the area where 2 cells are defined.
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource, UIImagePickerControllerDelegate & UINavigationControllerDelegate {
var arr = [1,1,3,3]
var tableview = UITableView()
var arrayThatStartsEmptyImage = [UIImage]()
var currentIndex = 0
var startBtnpress = UIButton()
var selectedIndexPath = IndexPath(row: 0, section: 0)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 2
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 118
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! customtv
return cell
}
#objc func addCell(){
//add 3 cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
tableview.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height * 0.8)
startBtnpress.frame = CGRect(x: 0, y: view.frame.height * 0.8, width: view.frame.width / 2 , height: view.frame.height / 5)
view.addSubview(tableview)
view.addSubview(startBtnpress)
startBtnpress.backgroundColor = .orange
tableview.register(customtv.self, forCellReuseIdentifier: "cell")
tableview.delegate = self
tableview.dataSource = self
}
}
class customtv: UITableViewCell {
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width , height: 110))
view.backgroundColor = .green
return view
}()
override func layoutSubviews() {
backView.clipsToBounds = true
backView.frame = CGRect(x: 0, y: 6, width: bounds.maxX , height: 110)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(animated, animated: true)
addSubview(backView)
}
}
This has been asked a lot before...
Instead of returning a hardcoded value inside tableView(_:numberOfRowsInSection:), you want to return the number of items in your data source (which I'm assuming is arr).
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
Then, simply add a row with
func addRowToEnd() {
arr.append(5) /// not sure what the numbers mean though...
tableView.beginUpdates()
tableView.insertRows(at: [IndexPath(row: arr.count - 1, section: 0)], with: .automatic) /// animate the insertion
tableView.endUpdates()
}

add together all of the labels in tableview cells

i want my swift code to add together all of the tableview cells together and convert it from a string to a int. The code should be called from the view did load func. The total should be 3 when all of the labels are added together. Look at my comment in view did load for more info. The code does not use storyboards.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var numberOfRows = 3
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { numberOfRows }
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 118 }
var tableView = UITableView()
var selectedIndexPath = IndexPath(row: 0, section: 0)
override func viewDidLoad() {
super.viewDidLoad()
setTableVIew()
//print the sum of the labels added togther on the tableview cells
}
func setTableVIew(){
let VCframe = view.frame
let height = VCframe.height * 0.8
let widthx = VCframe.width
tableView.frame = CGRect(x: 10, y: 0, width: widthx - 20, height: height)
tableView.delegate = self
tableView.dataSource = self
view.addSubview(tableView)
tableView.register(customtv.self, forCellReuseIdentifier: "cell")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! customtv
cell.lbl.text = "\(indexPath.row)"
return cell
}
}
class customtv: UITableViewCell {
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width , height: 110))
view.backgroundColor = .green
print(self.frame.width)
return view
}()
override func layoutSubviews() {
backView.clipsToBounds = true
backView.frame = CGRect(x: 0, y: 6, width: bounds.maxX , height: 110)
}
lazy var lbl : UILabel = {
let press = UILabel(frame: CGRect(x: 0, y: 3, width: 120 , height: 50))
press.backgroundColor = .yellow
press.text = String("1")
return press
}()
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(animated, animated: true)
addSubview(backView)
backView.addSubview(lbl)
}
}
Here's how you do this:
override func viewDidLoad() {
super.viewDidLoad()
setTableView()
calculateSum()
}
func calculateSum() {
var sum = 0
for row in 0..<numberOfRows {
let indexPath = IndexPath(row: row, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! CustomTableViewCell
sum += Int(cell.label.text ?? "") ?? 0
}
print(sum)
}
Note: Make the class and object names consistent eg: lbl -> label and customtv -> CustomTableViewCell as I've given above. Even the method names setTableVIew -> setTableView. It would be best if you use SwiftLint.

Print indexpath row on label in each table view cell

In my swift code below each table view cell features a label. In that label I want to print the index path row. So in cell one the label should be 1 in cell to it should read 2. I tried to code cell.textLabel?.text = "(indexPath.row)" but that code is not complying. The code uses no storyboards all code.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var numberOfRows = 3
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { numberOfRows }
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { 118 }
var tableView = UITableView()
var selectedIndexPath = IndexPath(row: 0, section: 0)
override func viewDidLoad() {
super.viewDidLoad()
setTableVIew()
}
func setTableVIew(){
let VCframe = view.frame
let height = VCframe.height * 0.8
let widthx = VCframe.width
tableView.frame = CGRect(x: 10, y: 0, width: widthx - 20, height: height)
tableView.delegate = self
tableView.dataSource = self
view.addSubview(tableView)
tableView.register(customtv.self, forCellReuseIdentifier: "cell")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! customtv
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
}
class customtv: UITableViewCell {
lazy var backView : UIView = {
let view = UIView(frame: CGRect(x: 10, y: 6, width: self.frame.width , height: 110))
view.backgroundColor = .green
print(self.frame.width)
return view
}()
override func layoutSubviews() {
backView.clipsToBounds = true
backView.frame = CGRect(x: 0, y: 6, width: bounds.maxX , height: 110)
}
lazy var lbl : UILabel = {
let press = UILabel(frame: CGRect(x: 0, y: 3, width: 120 , height: 50))
press.backgroundColor = .yellow
press.text = String("1")
return press
}()
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(animated, animated: true)
addSubview(backView)
backView.addSubview(lbl)
}
}
You are almost there :)
You have a custom cell, so you need to set the value of custom label you created, instead of cell.textLabel?.text.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! customtv
//cell.textLabel?.text = "\(indexPath.row)" // Don't Do this.
cell.lbl.text = "\(indexPath.row)" // Do this.
return cell
}
To clarify, your cells will start with values 0, 1, 2. IndexPath.row is 0 based.

Swift UITableViewAutomaticDimension is not working

I have got this table and cell
tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
tableView.allowsSelection = false;
tableView.estimatedRowHeight = 200
tableView.rowHeight = UITableViewAutomaticDimension
var postTexts = ["Nirvana"]
var posters = ["Champagnepapi"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postTexts.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let ProfilePicture = UIImageView(frame: CGRect(x:19, y: 14, width: 50, height: 50))
ProfilePicture.image = #imageLiteral(resourceName: "cole")
ProfilePicture.layer.cornerRadius = 25
ProfilePicture.layer.masksToBounds = true
let username = UILabel(frame: CGRect(x: 80, y: 14, width: 300, height: 30))
username.text = posters[indexPath.row]
let postText = UITextView(frame: CGRect(x:75,y:40,width:200,height:200))
postText.text = "I rather be dead than cool - Kurt Cobain"
let border = UIView(frame: CGRect(x:0,y:150,width:350,height:1))
border.backgroundColor = UIColor(r: 217, g: 221, b: 219)
cell.addSubview(ProfilePicture)
cell.addSubview(username)
cell.addSubview(postText)
cell.addSubview(border )
return cell
}
I wanted my cell to have automatic height but this it the result i get
How can i get an automatic height for my cells?
You needs to set the constraints on your cell objects like this so the cell can calculate the size needed.