I'm developing an application that has a "Plus" button which can add stopwatch to a table view, every cell has its own timer, and can be played by itself.
When I'm trying to delete one cell like that, random issues are happening like:
Order of the stopwatches being changed
some stopwatches time is being zeroed .
If trying to add new stopwatch after, an old stopwatch with it's timer are back!
TableView
class StopWatchViewController: UIViewController {
#IBOutlet weak var stopWatchesTableView: UITableView!
var stopwatchesList: [String] = []
var stopwatchesNum : Int = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
stopWatchesTableView.delegate = self
stopWatchesTableView.dataSource = self
NotificationCenter.default.addObserver(self,
selector: #selector(applicationDidEnterBackground(noti:)),
name: UIApplication.didEnterBackgroundNotification,
object: nil)
}
#objc func applicationDidEnterBackground(noti: Notification) {
// Save Date
let shared = UserDefaults.standard
shared.set(Date(), forKey: "SavedTime")
print(Date())
}
func refresh() {
stopWatchesTableView.reloadData()
}
#IBAction func AddStopWatch(_ sender: Any) {
stopwatchesNum += 1;
stopwatchesList.append(String(format: "Stopwatch %d", stopwatchesNum))
refresh()
}
}
extension StopWatchViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return stopwatchesList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let stopWatch = stopwatchesList[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "StopwatchCell") as! StopWatchCell
cell.initCell(title: stopWatch, index: indexPath.row)
return cell
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete {
stopwatchesList.remove(at: indexPath.row)
stopWatchesTableView.deleteRows(at: [indexPath], with: .automatic)
refresh()
}
}
}
What can cause such issues ?
Don't call refresh method after deleting the row.Hope this help.
Related
I have two buttons in my user's profile page, one for the saved shop items and one for his reviews.
I want when the user clicks the saved button it would load his saved shop's items in the table view and when he clicks the reviews button it would load his reviews.
I'm struggling on how to figure out how to do this
Any help, please?
here is my code:
#IBOutlet weak var reviewsBtn: UIButton!
#IBOutlet weak var saveBtntab: UIButton!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(reviewsBtn.isSelected == true){
print("review selected")
return reviews.count
}
if(saveBtntab.isSelected == true){
print("saved selected")
return shops.count
}
return shops.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellFave", for: indexPath) as! FaveTableViewCell
let shops = self.shops[indexPath.row]
let reviews = self.reviews[indexPath.row]
// i want to do the same idea for the number of rows here.
}
#IBAction func reviewsTapped(_ sender: Any) {
reviewsBtn.isSelected = true
reviewsBtn.isEnabled = true
faveBtntab.isEnabled = false
faveBtntab.isSelected = false
}
#IBAction func savedTapped(_ sender: Any) {
faveBtntab.isSelected = true
faveBtntab.isEnabled = true
reviewsBtn.isEnabled = false
reviewsBtn.isSelected = false
}
First of all if there are only two states you can simplify numberOfRows
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return reviewsBtn.isSelected ? reviews.count : shops.count
}
In cellForRow do the same thing, display the items depending on reviewsBtn.isSelected
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellFave", for: indexPath) as! FaveTableViewCell
if reviewsBtn.isSelected {
let reviews = self.reviews[indexPath.row]
// assign review values to the UI
} else {
let shops = self.shops[indexPath.row]
// assign shop values to the UI
}
}
And don't forget to call reloadData when the state has changed.
You can create two different dataSource instances for clarity and separation like following -
class ShopsDataSource: NSObject, UITableViewDataSource, UITableViewDelegate {
var shops: [Shop] = []
var onShopSelected: ((_ shop: Shop) -> Void)?
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return shops.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ShopTableViewCell", for: indexPath) as! ShopTableViewCell
let shop = self.shops[indexPath.row]
cell.populateDetails(shop: shop)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.onShopSelected?(shops[indexPath.row])
}
}
class ReviewsDataSource: NSObject, UITableViewDataSource, UITableViewDelegate {
var reviews: [Review] = []
var onReviewSelected: ((_ review: Review) -> Void)?
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return reviews.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ReviewTableViewCell", for: indexPath) as! ReviewTableViewCell
let review = self.reviews[indexPath.row]
cell.populateDetails(review: review)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.onReviewSelected?(reviews[indexPath.row])
}
}
class ViewController: UIViewController {
let shopsDataSource = ShopsDataSource()
let reviewsDataSource = ReviewsDataSource()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(ShopTableViewCell.self, forCellReuseIdentifier: "ShopTableViewCell")
tableView.register(ReviewTableViewCell.self, forCellReuseIdentifier: "ReviewTableViewCell")
shopsDataSource.onShopSelected = { [weak self] (shop) in
self?.showDetailsScreen(shop: shop)
}
reviewsDataSource.onReviewSelected = { [weak self] (review) in
self?.showDetailsScreen(review: review)
}
}
#IBAction func shopsTapped(_ sender: Any) {
tableView.dataSource = shopsDataSource
tableView.delegate = shopsDataSource
tableView.reloadData()
}
#IBAction func addNewShop(_ sender: Any) {
/// ask user about shop details and add them here
shopsDataSource.shops.append(Shop())
tableView.reloadData()
}
func showDetailsScreen(shop: Shop) {
/// Go to shop details screen
}
#IBAction func reviewsTapped(_ sender: Any) {
tableView.dataSource = reviewsDataSource
tableView.delegate = reviewsDataSource
tableView.reloadData()
}
#IBAction func addNewReview(_ sender: Any) {
/// ask user about review details and add them here
reviewsDataSource.reviews.append(Review())
tableView.reloadData()
}
func showDetailsScreen(review: Review) {
/// Go to review details screen
}
}
I tried to delete the rows by using the delete code but the row reappear everytime. I want to permanently delete any particular row.
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var countries = ["India","Canada", "USA","Russia","Dubai"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return countries.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = countries[indexPath.row]
return cell
}
//to enable delete action by swiping left
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete{
countries.remove(at: indexPath.row)
tableView.reloadData()
}
}
#IBOutlet weak var userTxt: UITextField!
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
let obj = UserDefaults.standard.object(forKey: "userKey") as? String
if let userName = obj {
userTxt.text = userName
}
}
#IBAction func savePressed(_ sender: UIButton) {
//we use this to save data
UserDefaults.standard.set(userTxt.text, forKey: "userKey")
}
#IBAction func deletePressed(_ sender: UIButton) {
UserDefaults.standard.removeObject(forKey: "userKey")
}
}
You have to save the modified array of countries to persist the changes you have made to it. Here's what you need to do:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//...
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
countries.remove(at: indexPath.row)
UserDefaults.standard.set(countries, forKey: "countries")
tableView.reloadData()
}
}
//...
override func viewDidLoad() {
super.viewDidLoad()
if let array = UserDefaults.standard.array(forKey: "countries") as? [String] {
countries = array
} else {
countries = ["India","Canada", "USA","Russia","Dubai"]
}
//...
}
}
Your implementation of delete does not persist the changes you make from delete as it uses a variable that’s initialized every time with data you hardcoded, hence array restores its elements to ones you specified every time you check back. So instead of hard coding values to an array to fill your tableView, consider using a persistent storage like a database or UserDefaults.
i have a tableview in a viewcontroller and because i need to reuse most of the code for another table i created an extra class:
class StatisticsViewDelegate: NSObject, UITableViewDelegate, UITableViewDataSource {
var defaultList:[String]
var infolist:[String] = []
var tableView:UITableView
var controller:UIViewController?
init(defaultList:[String], view:UITableView, controller:UIViewController?) {
self.defaultList = defaultList
self.controller = controller
tableView = view
super.init()
tableView.delegate = self
tableView.dataSource = self
loadTable()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infolist.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "infocell", for: indexPath) as! TableViewCell
// [fill cell]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// [...]
}
func loadTable() {
DispatchQueue.global(qos: .userInitiated).async {
//[...]
// in this case:
self.infolist = self.defaultList
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
and in my UITViewController in the viewDidLoad():
delegate = StatisticsViewDelegate(defaultList: defaultList, view: tableView, controller:self)
delegate is a member of the ViewController
now when i run it, the function func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) never gets called. The func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) gets called however(before and after the reload) and returns the correct number(in my case 4). The TableView isn't visible at all. Where is my error?
Maybe you can use the subclassing strategy to resolve your problem. There are many reference passed to your class and if you forgot to clean that up you will be have memory leaks in your hand. So I'll suggest the simple example as below. You can modify as you like and let me know if that was what you are after. If not please pardon me.
//This will be parent class that will handle all table methods, so you need to write only once the delegates and stuffs
class MyCommonTableController: UITableViewController {
var infoList = [String]()
// MARK: - TableView Delegate and Datsource Impl
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infoList.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 55.0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = infoList[indexPath.row]
return cell
}
}
The first class that is directly subclassing the from above MyCommonTableController
//In here we just have to know the data and set the infoList from parent
class TheTableViewController: MyCommonTableController {
let defaultList = ["Data1","Data2","Data3"] //....etc
override func viewDidLoad() {
super.viewDidLoad()
//this is were I will set those
infoList = defaultList
//reload the table
tableView.reloadData()
}
}
The second class that is directly subclassing the from above MyCommonTableController. Same process goes here
class TheSecondTableViewController: MyCommonTableController {
let defaultList = ["List1","List2","List3"] //....etc
override func viewDidLoad() {
super.viewDidLoad()
//this is were I will set those
infoList = defaultList
//reload the table
tableView.reloadData()
}
}
And now you are not repeating and table methods. You can also get the reference of table and use in your norma table view
#IBOutlet weak var theTable: UITableView!
let defaultList = ["List1","List2","List3"] //....etc
let commonTable = MyCommonTableController()
// MARK: - LifeCycle
override func viewDidLoad() {
super.viewDidLoad()
commonTable.infoList = defaultList
commonTable.tableView = theTable
}
I am implementing a tableview which it shows a lists of documents:
MyTableviewController
import UIKit
class MyTableViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var editButton: UIBarButtonItem!
#IBOutlet weak var tableview: UITableView!
var animalNameArray = ["cat","dog","lion"]
override func viewDidLoad() {
super.viewDidLoad()
tableview.delegate = self
tableview.dataSource = self
}
#IBAction func editButtonAtNavigationBar(_ sender: UIBarButtonItem) {
self.tableview.isEditing = !self.tableview.isEditing
sender.title = (self.tableview.isEditing) ? "Done" : "Edit"
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return animalNameArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let valueAtCell = tableView.dequeueReusableCell(withIdentifier: "myCustomCell", for: indexPath) as! CustomTableViewCell
valueAtCell.cellLabel?.text = animalNameArray[indexPath.row]
return valueAtCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
animalNameArray.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
//Rearranging the table view cells
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let itemMove = animalNameArray[sourceIndexPath.row]
animalNameArray.remove(at: sourceIndexPath.row)
animalNameArray.insert(itemMove, at: destinationIndexPath.row)
}
}
I want to reset the reordered lists clicking on cancel button. How?
When I close the application and start it again (any time refresh data function runs), rows comes back to their default places while I need to have saved the changes in reordering.
And how can i use image (trash) at the position of delete??
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var editButton: UIBarButtonItem!
#IBOutlet weak var tableview: UITableView!
var animalNameArray = [String]() {
didSet {
UserDefaults.standard.set(animalNameArray, forKey: "savedNameArray")
}
}
var originalArray = [String]()
override func viewDidLoad() {
super.viewDidLoad()
tableview.delegate = self
tableview.dataSource = self
animalNameArray = UserDefaults.standard.array(forKey: "savedNameArray") as? [String] ?? ["cat","dog","lion"]
originalArray = animalNameArray
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
#IBAction func editButtonAtNavigationBar(_ sender: UIBarButtonItem) {
self.tableview.isEditing = !self.tableview.isEditing
sender.title = (self.tableview.isEditing) ? "Done" : "Edit"
}
#IBAction func cancelButtonAtNavigationBar(_ sender: UIBarButtonItem) {
self.tableview.isEditing = false
navigationItem.rightBarButtonItem?.title = "Edit"
animalNameArray = originalArray
tableview.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return animalNameArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let valueAtCell = tableView.dequeueReusableCell(withIdentifier: "myCustomCell", for: indexPath) as! CustomTableViewCell
valueAtCell.cellLabel?.text = animalNameArray[indexPath.row]
return valueAtCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
animalNameArray.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
//Rearranging the table view cells
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let itemMove = animalNameArray[sourceIndexPath.row]
animalNameArray.remove(at: sourceIndexPath.row)
animalNameArray.insert(itemMove, at: destinationIndexPath.row)
}
}
Try this code, and connect your cancel button from storyboard to #IBAction func cancelButtonAtNavigationBar(_ sender: UIBarButtonItem)
Here is the solution
import UIKit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var editButton: UIBarButtonItem!
#IBOutlet weak var tableview: UITableView!
var animalNameArray = ["cat","dog","lion"]
override func viewDidLoad() {
super.viewDidLoad()
tableview.delegate = self
tableview.dataSource = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let defaults = UserDefaults.standard
let operationArray = defaults.stringArray(forKey: "SavedStringArray") ?? [String]()
if operationArray.count == 0 {
}else{
animalNameArray = operationArray
}
}
#IBAction func editButtonAtNavigationBar(_ sender: UIBarButtonItem) {
self.tableview.isEditing = !self.tableview.isEditing
sender.title = (self.tableview.isEditing) ? "Done" : "Edit"
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return animalNameArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let valueAtCell = tableView.dequeueReusableCell(withIdentifier: "myCustomCell", for: indexPath) as! CustomTableViewCell
valueAtCell.cellLabel?.text = animalNameArray[indexPath.row]
return valueAtCell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
animalNameArray.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
print(animalNameArray)
let defaults = UserDefaults.standard
defaults.set(animalNameArray, forKey: "SavedStringArray")
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return true
}
//Rearranging the table view cells
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let itemMove = animalNameArray[sourceIndexPath.row]
animalNameArray.remove(at: sourceIndexPath.row)
animalNameArray.insert(itemMove, at: destinationIndexPath.row)
print(animalNameArray)
}
}
Download sample https://github.com/testingraahul/TableViewEditing/tree/master
Ok so I am geting memory errors from this which is annoying ,since it isn't something like a simple syntax error. Well the thing I am doing to understanding how to manipulate data
What I am trying to do is to allow it to delete from another view ,but the thing still crashes. I will share the two table views I got going on.
This is the one that has problems ,since it is in the second view controller
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return FeedCommands.commentSection.count
}
//allows us to delete the code
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// this is called from a static variable class function
FeedCommands.RemoveComment(atIndex: indexPath.row)
CommentFeed.deleteRows(at: [indexPath], with: .fade)
}
}
Now this is the one that works perfectly fine
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return FeedCommands.feedArray.count
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
FeedCommands.feedArray.remove(at: indexPath.row)
TabView.deleteRows(at: [indexPath], with: .fade)
}
}
If I ran the problem one it exits with a memory error, I am thinking that it might have to deal with the arrays and might be the actual cause. I searched and there doesn't really seem to be anything that covers this case when doing multiple tableviews.
Here is the class I am calling the arrays from
static var commentSection: Array<String> = []
class func AddToComment(newElement: String){
FeedCommands.commentSection.append(newElement)
}
class func RemoveComment (atIndex: Int){
FeedCommands.commentSection.remove(at: atIndex)
}
static var QuestionToComment: Array<String> = []
class func AddQuestionToComment(newElement: String){
FeedCommands.QuestionToComment.append(newElement)
}
class func RemoveQuestionToComment (atIndex: Int){
FeedCommands.QuestionToComment.remove(at: atIndex)
}
static var feedArray: Array<String> = []
class func AddToFeed (newElement: String){
FeedCommands.feedArray.append(newElement)
}
class func Remove (atIndex: Int){
FeedCommands.feedArray.remove(at: atIndex)
}
If it needs more details please let me know.
Edit: Due to a request
this is the comment section file
import UIKit
class Comments: UIViewController, UITableViewDelegate, UITableViewDataSource{
#IBOutlet weak var Question: UITextView!
#IBOutlet weak var ReplyTextField: UITextField!
#IBOutlet weak var CommentFeed: UITableView!
#IBAction func SubmitReply(_ sender: UIButton) {
CommentFeed.reloadData()
if ReplyTextField.text == nil {
}
else{
FeedCommands.AddToComment(newElement: ReplyTextField.text!)
ReplyTextField.text = ""
}
// dismiss(animated: true, completion: nil)
// ReplyTextField.placeholder = "Comment"
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
//this is what we use to get the question to
//appear in the comment section
Question.text = ""
for Section in FeedCommands.QuestionToComment{
Question.text = "\(Section)"
CommentFeed.reloadData()
}
}
//adding the table view
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return FeedCommands.commentSection.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = CommentFeed.dequeueReusableCell(withIdentifier: "Com", for: indexPath)
cell.textLabel?.text = "#\(Question.text!)__ \(FeedCommands.commentSection[indexPath.row])"
return cell
}
//allows us to delete the code
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
FeedCommands.commentSection.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade) // crashes here
}
}
}
You are reloading the table view data before appending a new element to your table view instead of reloading it after appending the reply. Thats why you needed to press your button twice to make it appear. What you should actually do to fix your submit reply action is to insert a new row at the last index (count - 1) of your table view every time the SubmitReply button is pressed:
#IBAction func SubmitReply(_ sender: UIButton) {
if !ReplyTextField.text!.isEmpty{
FeedCommands.AddToComment(newElement: ReplyTextField.text!)
ReplyTextField.text = ""
CommentFeed.insertRows(at: [IndexPath(row: FeedCommands.commentSection.count-1, section: 0)], with: .automatic)
}
}