I am developing a ToDo app in Swift, I am using Firebase to save data for my Swift App, but I can't delete it from collection, which called "tasks", only cells from Table View are deleting. I use Swift 5 and Xcode 12.5.1
Any help is welcome.
class ToDoViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
}
#IBOutlet weak var statusCheckBox: UIImageView!
#IBOutlet weak var titleTextField: UITextField!
#IBOutlet weak var bodyTextField: UITextView!
#IBOutlet var blurView: UIVisualEffectView!
#IBOutlet var popupView: UIView!
#IBOutlet weak var tableView: UITableView!
let db = Firestore.firestore()
var tasks: [Task] = []
// Getting number of existing tasks
extension ToDoViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
// Creating tasks from reusable cell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: K.FStore.reusableCell, for: indexPath)
cell.textLabel?.text = tasks[indexPath.row].title
cell.detailTextLabel?.text = tasks[indexPath.row].body
if tasks[indexPath.row].status {
cell.accessoryType = UITableViewCell.AccessoryType.checkmark
} else {
cell.accessoryType = UITableViewCell.AccessoryType.none
}
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
guard editingStyle == .delete else { return }
tasks.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
// here I need to delete data from Firebase
}
}
Related
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
I'm making an alarm function similar to the iPhone alarm app.
When setting the alarm day, I am writing code to check the day of the week.
class DaySelectCell: UITableViewCell {
#IBOutlet weak var dayLbl: UILabel!
#IBOutlet weak var checkView: Checkbox!
}
import UIKit
class DaySelectViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
let days = ["일요일마다","월요일마다","화요일마다","수요일마다","목요일마다","금요일마다","토요일마다"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
}
}
extension DaySelectViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return days.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DaySelectCell") as! DaySelectCell
cell.dayLbl.text = days[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: "DaySelectCell") as! DaySelectCell
}
}
The part I want to ask is didSelectRowAt
I want to make a checkView.isSelectd of that cell to be true when I click on a certain day cell.
You have to manage datasource to hold the selected value, So you can pretend which index is selected.
var selectedDays: [Int] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.accessoryType = selectedDays.contains(indexPath.row) ? .checkmark : .none
}
Now in didSelectRowAt method write this code
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let index = selectedDays.firstIndex(where: { $0 == indexPath.row }) {
selectedDays.remove(at: index)
} else {
selectedDays.append(indexPath.row)
}
tableView.reloadData()
}
For some reason, the delegate method is not being called. I am printing the delegate property in the console but it returns nil. I was looking for other answers here, but none of them were helpful for me.
protocol FilterSwitchDelegate {
func switchValueChanged(tagValue:Int)
}
class FilterTableViewCell: UITableViewCell {
#IBOutlet weak var filterLabel: UILabel!
#IBOutlet weak var filterSwitch: UISwitch!
var delegate:FilterSwitchDelegate?
#IBAction func filterSwitchValueChanged(_ sender: UISwitch) {
print(sender.tag)
delegate?.switchValueChanged(tagValue: sender.tag)
}
}
//In FilterViewController I am calling this delegate method
class FilterViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var dataSource = FilterTableViewCell()
var filterModel = [FilterVCDataModel]()
var ids = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
dataSource.delegate = self
}
}
extension FilterViewController: FilterSwitchDelegate {
func switchValueChanged(tagValue: Int) {
ids.remove(at: tagValue)
print(ids)
}
}
TableView dataSource and delegate methods
extension FilterViewController:UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filterModel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "filterCell", for: indexPath) as! FilterTableViewCell
cell.filterSwitch.tag = indexPath.row
cell.filterLabel.text = filterModel[indexPath.row].filterData["title"] as? String
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 66
}
}
in the cellForRow you have to dequeue your cell.
let cell = tableView.dequeueReusableCell(withIdentifier: "yourId") as? FilterTableViewCell
cell.delegate = self
return cell
and the job is done
What is the best practice to add dynamic list of items in UITableViewCell with showMore/showLess?
UITableView inside UITableViewCell
I used table view inside my UITableViewCell , but I have issue with reload row at indexPath causes jumpy scrolling.
TableViewController Code :
class ViewController: UIViewController , UITableViewDelegate , UITableViewDataSource , delegatCell {
#IBOutlet weak var tableView: UITableView!
var elementsArray: [data] = []
override func viewDidLoad() {
super.viewDidLoad()
for i in 1...20 {
elementsArray.append(data.init(title: "title\(i)", date: "8:00 PM", isShowMoreClicked: false, elements: ["ToDo\(i)","Aqraa\(i)","ToDo\(i)","ToDo\(i)" , "Mobile Team\(i)" , "Testing Data\(i)"]))
// Do any additional setup after loading the view, typically from a nib.
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return elementsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let obj = elementsArray[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! expandedTableViewCell
cell.initializeCell()
print(obj.elements)
cell.data = obj.elements
cell.delegate = self
cell.dateLabel.text = obj.date
cell.titleLabel.text = obj.title
cell.showMore.titleLabel?.font = reqularDynamicFont()
cell.showMore.titleLabel?.adjustsFontSizeToFitWidth = true
cell.showMore.tag = indexPath.row
cell.isShowMoreClicked = obj.isShowMoreClicked
cell.tableView.reloadData()
self.view.layoutIfNeeded()
return cell
}
func reqularDynamicFont()-> UIFont{
let font = UIFont.systemFont(ofSize: 15, weight: .regular)
let fontMetrics = UIFontMetrics(forTextStyle: .caption1)
return fontMetrics.scaledFont(for: font)
}
func reloadTableView(indexpath: IndexPath , isShowMoreClicked: Bool) {
elementsArray[indexpath.row].isShowMoreClicked = isShowMoreClicked
tableView.reloadRows(at: [indexpath], with: .automatic)
}
}
ExpandedTableViewCell with inner table view Code :
import UIKit
protocol delegatCell {
func reloadTableView(indexpath: IndexPath , isShowMoreClicked: Bool)
}
class expandedTableViewCell: UITableViewCell , UITableViewDelegate , UITableViewDataSource{
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var showMore: UIButton!
var data : [String] = []
var initalNum = 2
var isShowMoreClicked: Bool = false
var delegate:delegatCell?
func initializeCell(){
data.removeAll()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isShowMoreClicked{
return data.count
}else{
return initalNum
}
}
#IBAction func reloadData(_ sender: UIButton) {
delegate?.reloadTableView(indexpath: IndexPath(row: sender.tag, section: 0), isShowMoreClicked: !isShowMoreClicked)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print(data)
let cell = tableView.dequeueReusableCell(withIdentifier: "simpleTableViewCell", for: indexPath) as! simpleTableViewCell
cell.descLabel.text = data[indexPath.row]
return cell
}
}
I used auto layout to support dynamic height.
hey so I'm trying to create a custom cell and I've properly linked everything in my story board but for some reason it doesn't display anything when I run. I Tried testing it out, it appears that the custom cell objects don't even get created.
class customCell : UITableViewCell{
#IBOutlet weak var EventImage: UIImageView!
#IBOutlet weak var type: UILabel!
#IBOutlet weak var rating: UIImageView!
#IBOutlet weak var date: UILabel!
#IBOutlet weak var name: UILabel!
}
class EventHistoryViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var TableView: UITableView!
let k = ["hi","hey","yo","hello"]
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return k.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.TableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! customCell
cell.name!.text = self.k[index.row]
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
self.TableView.register(customCell.self, forCellReuseIdentifier: "cell")
TableView.delegate = self
TableView.dataSource = self
}
what am I doing wrong? the program in this case crashes when it reaches cell.name!.text = self.k[index.row]
Check this one
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: VC_FavouriteCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath as IndexPath) as! VC_FavouriteCell
cell.name.text = k[index.row]
return cell
}
In place of cell.name!.text write cell.name.text
Don't register the cell