Swift TableView insert row below button clicked - ios

I am new to Swift and I am using Swift 4.2 . I have a TableView with a label and button . When I press a button I would like to add a new row directly below the row in which the button was clicked . Right now when I click a button the new row gets added to the bottom of the TableView every time. I have been looking at posts on here but haven't been able to get it working this is my code base . I have a method called RowClick I get the indexpath of the row that was clicked but do not know how to use that to get the new row to appear directly below the clicked row .
class ExpandController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var TableSource: UITableView!
var videos: [String] = ["FaceBook","Twitter","Instagram"]
override func viewDidLoad() {
super.viewDidLoad()
TableSource.delegate = self
TableSource.dataSource = self
TableSource.tableFooterView = UIView(frame: CGRect.zero)
// Do any additional setup after loading the view.
}
#IBAction func RowClick(_ sender: UIButton) {
guard let cell = sender.superview?.superview as? ExpandTVC else {
return
}
let indexPath = TableSource.indexPath(for: cell)
InsertVideoTitle(indexPath: indexPath)
}
func InsertVideoTitle(indexPath: IndexPath?)
{
videos.append("Snapchat")
let indexPath = IndexPath(row: videos.count - 1, section: 0)
TableSource.beginUpdates()
TableSource.insertRows(at: [indexPath], with: .automatic)
TableSource.endUpdates()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videos.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let videoTitle = videos[indexPath.row]
let cell = TableSource.dequeueReusableCell(withIdentifier: "ExpandTVC") as! ExpandTVC
cell.Title.text = videoTitle
cell.ButtonRow.tag = indexPath.row
cell.ButtonRow.setTitle("Rows",for: .normal)
return cell
}
}
This is how my table looks I clicked the Facebook Rows button and it appended the string SnapChat . The Snapchat label should appear in a row below Facebook instead . Any suggestions would be great !

I think the easiest solution without re-writing this whole thing would be adding 1 to the current row of the IndexPath you captured from the action.
let indexPath = TableSource.indexPath(for: cell)
var newIndexPath = indexPath;
newIndexPath.row += 1;
InsertVideoTitle(indexPath: newIndexPath);
I did this from memory because I am not near an IDE, so take a look at the change and apply that change if needed in any other location.
class ExpandController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var TableSource: UITableView!
var videos: [String] = ["FaceBook","Twitter","Instagram"]
override func viewDidLoad() {
super.viewDidLoad()
TableSource.delegate = self
TableSource.dataSource = self
TableSource.tableFooterView = UIView(frame: CGRect.zero)
// Do any additional setup after loading the view.
}
#IBAction func RowClick(_ sender: UIButton) {
guard let cell = sender.superview?.superview as? ExpandTVC else {
return
}
let indexPath = TableSource.indexPath(for: cell)
var newIndexPath = indexPath;
newIndexPath.row += 1;
InsertVideoTitle(indexPath: newIndexPath);
}
func InsertVideoTitle(indexPath: IndexPath?)
{
videos.append("Snapchat")
let indexPath = IndexPath(row: videos.count - 1, section: 0)
TableSource.beginUpdates()
TableSource.insertRows(at: [indexPath], with: .automatic)
TableSource.endUpdates()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return videos.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let videoTitle = videos[indexPath.row]
let cell = TableSource.dequeueReusableCell(withIdentifier: "ExpandTVC") as! ExpandTVC
cell.Title.text = videoTitle
cell.ButtonRow.tag = indexPath.row
cell.ButtonRow.setTitle("Rows",for: .normal)
return cell
}
}

Your current code calls append to add the new item at the end of the array. What you want to do is insert a new row at indexPath.row+1. Array has an insert(element,at:) function.
You have to handle the case where the user has tapped the last row and not add 1 to avoid an array bounds error:
func InsertVideoTitle(indexPath: IndexPath)
{
let targetRow = indexPath.row < videos.endIndex ? indexPath.row+1 : indexPath.row
videos.insert("Snapchat" at:targetRow)
let newIndexPath = IndexPath(row: targetRow, section: 0)
TableSource.beginUpdates()
TableSource.insertRows(at: [newIndexPath], with: .automatic)
TableSource.endUpdates()
}

Related

UITableView load wrong cell height Swift

I'm doing with Xcode 10. I have a tableview in ViewController.
The cell has label which is set as leading, tralling, top and bottom, line is 0
In ViewDidload() I added
override func viewDidLoad() {
super.viewDidLoad()
tableview.rowheight = UITableView.automaticDimension
tableview.estimateheight = 98
tableview.reloaddata()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CommentCell", for: indexPath) as! CommentCell
let idcmt: String
idcmt = self.CommentIDArray[indexPath.row]
ref.child("Post_theme/\(userid!)/\(id)/comment/\(idcmt)").observe( .value, with: {(snapshot) in
let value = snapshot.value as? NSDictionary
cell.Comment.text = value!["content"] as? String
})
// I have a button in the custom cell but tableview load height wrong even I did not click the button on cell
self.ref.child("Post_theme/\(self.userid!)/\(self.id)/comment/\(idcmt)/likecomment").observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.hasChild(self.userid!){
cell.Heartcommentaction = {
cell.HeartCommentbutton.tintColor = .lightGray
self.TableCommentView.reloadData()
}
}
})
return cell
}
class CommentCell: UITableViewCell{
var Heartcommentaction : (() -> ()) = {}
#IBOutlet weak var Comment: UILabel!
#IBOutlet weak var HeartCommentbutton: UIButton!
#IBAction func HeartCommentaction(_ sender: Any) {
Heartcommentaction()
}
}
But when I click to Viewcontroller, tableview did not load the right height cell ( cell which is needed to autorize is not, cell which is not needed is resize)
Then I add this code
override func viewDidAppear(_ animated: Bool) {
tableview.reloadData()
}
the code run well just for initial few cells, but when I scroll down more (I have around over 100 cells), it's wrong height again, when I scroll up the initial cells get again wrong
I looked many solutions but not working for me
Really need help! thank you
UPDATE
this is the screenshot of wrong height cell, some timewrong, sometime right
Use :
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 98
}
Also remove tableview.estimateheight = 98
Give this a shot. My code here may not compile because I don't have your full source code. Remember, cellForRow should synchronously set all values on your cell. And you don't want to call reloadData because you will see glitches when scrolling. You want to call reloadRows. See below and see if that helps:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CommentCell", for: indexPath) as! CommentCell
let idcmt: String
idcmt = self.CommentIDArray[indexPath.row]
cell.Comment.text = "..."
cell.Heartcommentaction = {}
ref.child("Post_theme/\(userid!)/\(id)/comment/\(idcmt)")
.observe( .value, with: {(snapshot) in
let value = snapshot.value as? NSDictionary
if let value = value, let indexPath = tableView.indexPath(for: cell) {
cell.Comment.text = value!["content"] as? String
tableView.reloadRows(at: [indexPath], .fade)
} else {
print("nope")
}
})
self.ref.child("Post_theme/\(self.userid!)/\(self.id)/comment/\(idcmt)/likecomment")
.observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.hasChild(self.userid!){
if let indexPath = tableView.indexPath(for: cell) {
cell.Heartcommentaction = {
cell.HeartCommentbutton.tintColor = .lightGray
tableView.reloadRows(at: [indexPath], .fade)
}
} else {
print("bad indexPath")
}
} else {
print("no child")
}
})
return cell
}

How can i create a hamburger menu with Sub Menu inside

I am working on an app in which requirement is to create a hamburger menu with submenu in it like
I tried different method using table inside table view cell etc but unable to create this menu.
if someone has a solution then recommend me
You can create such an item structure as your data source
struct Item {
let text: String
var subItems: [String]?
var isExpanded = false
init(_ text: String, items: [String]? = nil) {
self.text = text
self.subItems = items
}
}
Usage
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
private let imgOpen = UIImage(named: "open")
private let imgClose = UIImage(named: "close")
private var dataSource = [Item]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "groupCell")
self.tableView.dataSource = self
self.tableView.delegate = self
self.dataSource.append(Item("HOME"))
self.dataSource.append(Item("ABOUT US"))
self.dataSource.append(Item("OUR PROJECTS", items: ["Project-1", "Project-2", "..."]))
self.dataSource.append(Item("BAHRIA TOWN PHASE 1 - 7"))
self.dataSource.append(Item("BAHRIA TOWN PHASE 8"))
self.tableView.reloadData()
}
func numberOfSections(in tableView: UITableView) -> Int {
return self.dataSource.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let item = self.dataSource[section]
if item.isExpanded, let count = item.subItems?.count {
return count + 1
}
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = self.dataSource[indexPath.section]
let cell = tableView.dequeueReusableCell(withIdentifier: "groupCell", for: indexPath)
var imageView: UIImageView?
if indexPath.row > 0, let text = item.subItems?[indexPath.row - 1] {
cell.textLabel?.text = text
} else {
cell.textLabel?.text = item.text
if item.subItems != nil {
imageView = UIImageView(image: item.isExpanded ? self.imgClose : self.imgOpen)
}
}
cell.accessoryView = imageView
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = self.dataSource[indexPath.section]
if indexPath.row == 0 && item.subItems != nil {
self.dataSource[indexPath.section].isExpanded = !item.isExpanded
let indexSet = IndexSet(integer: indexPath.section)
tableView.reloadSections(indexSet, with: .automatic)
} else {
// non-expandable menu item tapped
}
}
}
You should separate the process.
First, create the hamburger menu: for this, I recommend using this 3rd party library: https://github.com/John-Lluch/SWRevealViewController
With the help of this, it is very easy to create a side out menu from the left side of the screen.
The best thing that you will get a ViewController which will responsible for the menu, so you can easily customize it.
Second, as mentioned below, you should use a tableView with expandable cells. The best way to do this is to basically just show the headers of the cells. If the user taps on a header, then show the actual cell. (rowheight > 0). There is a tutorial about this: https://www.youtube.com/watch?v=bSKUYRsMCrM
-> you can create a sliding drawer menu(hamburger menu) using any of the following libraries:
1) REFrostedViewController
2) SWRevealViewController or any other
-> Sub Menu: In the drawer view controller, you have to add a table view and implement expandable/collapsible sections to display a submenu. You can follow any tutorial explaining about expand-collapse table view sections. Some of the tutorial links are below:
https://github.com/jeantimex/ios-swift-collapsible-table-section
https://medium.com/#legonaftik/uitableview-with-collapsible-sections-927d726b985c
1st Follow https://github.com/jonkykong/SideMenu.
And then to make EXPANDABLE Cells:-
You just need to create 2 Cells in UITableView(In Storyboard). First cell for those who are not expandable and Second cell for the expandable.
class SideMenuTableViewController: UITableViewController {
// MARK:- Constants And Vars
var isOurProjectCellExpanded = false
}
class SideMenuTableViewController: UITableViewDataSource, UITableViewDelegate {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "simpleCell", for: indexPath) as! SideMenuBasicTableViewCell
switch indexPath.row {
case 0:
cell.itemName.text = "HOME"
break
case 1:
cell.itemName.text = "About Us"
break
case 2:
if(isOurProjectCellExpanded){
//expandedCell
let cell = tableView.dequeueReusableCell(withIdentifier: "expandedCell", for: indexPath) as! SideMenuBasicTableViewCell
cell.itemName.text = "Our Projects"
return cell
}else{
cell.arrowDownImageView.isHidden = false
cell.itemName.text = "Our Projects"
}
break
case 3:
cell.itemName.text = "Bahria Town phase 1-7"
break
case 4:
cell.itemName.text = "Bahria Town phase 8"
break
default:
break
}
return cell
}
//And in `DidSelectRow` Method
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if(indexPath.row == 2){
if(isOurProjectCellExpanded){
isOurProjectCellExpanded = false
tableView.reloadRows(at: [indexPath], with: .none)
}else{
isOurProjectCellExpanded = true
tableView.reloadRows(at: [indexPath], with: .none)
}
}else if(indexPath.row == 0){
// Handle it yourself
}else if(indexPath.row == 1){
// Handle it yourself
}else if(indexPath.row == 3){
// Handle it yourself
}else if(indexPath.row == 4){
// Handle it yourself
}
}
}

Increase and Decrease values on Button click

I want to show value on UIlabel. when I press UIbutton to increase or decrease values on label. This is my code and when I am running my project but I didn't get any value on my uilabel.
#IBAction func btnIncreaseAction(_ sender: Any) {
var count = 0
count = (count + 1)
if let cell = (sender as? UIButton)?.superview?.superview?.superview as? ShoppingCell
{
//cell.lblForOnty.text = "\(cell.lblForOnty.text ?? 0 + 1)"
cell.lblForOnty.text = String(count)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellRID") as! ShoppingCell
var someValue: Int = 0 {
didSet {
cell.lblForOnty.text = "\(count)"
}
}
return cell
}
}
This is the code which should be in your ViewController. I am assuming that numberOfSections is 1 and in numberOfRowsInSection you are passing then number of rows you want. Else you need to modify this line : let indexPath = IndexPath(row: sender.tag, section: 0).
var count = 0 // Count variable should be a global variable, you need it to decrease the value too.
#objc func increaseCounter(sender: UIButton) {
//increase logic here
count = (count + 1)
let indexPath = IndexPath(row: sender.tag, section: 0)
let cell = tableView.cellForRow(at: indexPath)
cell.lblForOnty.text = "\(count)"
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellRID") as! ShoppingCell
// Add tag and action to your button
cell.yourButton.tag = indexPath.row
cell.yourButton.addTarget(self, action: #selector(increaseCounter(sender:)), for: .touchUpInside)
return cell
}
superview?.superview?.superview is pretty weird. Don't do that. A callback is more reliable.
In the subclass ShoppingCell create a callback and the IBActions for in- and decrease . Connect the actions to the buttons
class ShoppingCell: UITableViewCell {
#IBOutlet weak var lblForOnty: UILabel!
var callback : ((Int)->())?
var counter = 0 {
didSet {
lblForOnty.text = "\(count)"
}
}
#IBAction func btnIncreaseAction(_ sender: UIButton) {
counter += 1
callback?(counter)
}
#IBAction func btnDecreaseAction(_ sender: UIButton) {
if counter > 0 { counter -= 1 }
callback?(counter)
}
}
In cellForRow pass the counter value to the cell and use the callback to update the model which is represented by dataSource and which is a custom struct or class containing a property counter.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellRID", for: indexPath) as! ShoppingCell
let item = dataSource[indexPath.row]
cell.counter = item.counter
cell.callback = ( newValue in
item.counter = newValue
}
return cell
}
No hassle with superviews and index paths.
Move you count variable outside of the function
Increment/decrement the count inside the function and reload the table or you can reload particular index as well.
PFB the code snipped
let indexPath = NSIndexPath(forRow: rowNumber, inSection: 0)
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Top)
Please follows these step:
Step 1 :
create object class
class QuantityBO : NSObject{
var quantity : Int?
}
step 2:
Create global array in your class
var arrQuantityList = [QuantityBO]()
step 3 :
Assign the value according to your number of cell
It may be change according to your api resonse
step 4:
In cellForRowAt method please write:
cell.lblQuantity.text = String(arrQuantityList[indexPath.row].quantity)
cell.yourBtnName.tag = indexPath.row
step 5:
On your button action
arrQuantityList[sender.tag].quantity = arrQuantityList[sender.tag].quantity + 1
let indexPath = NSIndexPath(forRow: sender.tag, inSection: 0)
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.none)
It may helps to you.hank you.

Value of type '_' has no member

In the cb.check(self.rowChecked[indexPath.row]) line under cellForRowAt I'm getting a "Value of type 'LolFirstTableViewController' has no member 'rowChecked'" even though I set up rowChecked to be an array of Booleans with tasks.count number of items. Do I need to initialize rowChecked somewhere else besides cellForRowAt or what am I doing wrong here? The point of this code is to make a checkbox show up in each cell of a table where you can click it to change the accessory to a check mark, and click it again to uncheck it. The check box itself is a separate custom class called CheckButton. I'm still learning Swift so any help would be greatly appreciated! Thank you!
import UIKit
class LoLFirstTableViewController: UITableViewController {
var tasks:[Task] = taskData
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 60.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tasks.count
}
#IBAction func cancelToLoLFirstTableViewController(_ segue:UIStoryboardSegue) {
}
#IBAction func saveAddTask(_ segue:UIStoryboardSegue) {
if let AddTaskTableViewController = segue.source as? AddTaskTableViewController {
if let task = AddTaskTableViewController.task {
tasks.append(task)
let indexPath = IndexPath(row: tasks.count-1, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
}
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell
let task = tasks[indexPath.row]
cell.task = task
var rowChecked: [Bool] = Array(repeating: false, count: tasks.count)
if cell.accessoryView == nil {
let cb = CheckButton()
cb.addTarget(self, action: #selector(buttonTapped(_:forEvent:)), for: .touchUpInside)
cell.accessoryView = cb
}
let cb = cell.accessoryView as! CheckButton
cb.check(self.rowChecked[indexPath.row])
return cell
}
func buttonTapped(_ target:UIButton, forEvent event: UIEvent) {
guard let touch = event.allTouches?.first else { return }
let point = touch.location(in: self.tableView)
let indexPath = self.tableView.indexPathForRow(at: point)
var tappedItem = tasks[indexPath!.row] as Task
tappedItem.completed = !tappedItem.completed
tasks[indexPath!.row] = tappedItem
tableView.reloadRows(at: [indexPath!], with: UITableViewRowAnimation.none)
}
You are declaring rowChecked as a local variable and calling it with self.rowChecked as if it were a class property.
To solve this issue, remove the self. before rowChecked.
Old:
cb.check(self.rowChecked[indexPath.row])
New:
cb.check(rowChecked[indexPath.row])
There might be further issues, but that's the reason for the error as your code currently stands.
You have the line: var rowChecked: [Bool] = Array(repeating: false, count: tasks.count) inside the tableView:cellForRowAt method, so it's a local variable, it's not a property of the LolFirstTableViewController class.
That means you need to change this line: cb.check(self.rowChecked[indexPath.row]) to cb.check(rowChecked[indexPath.row]) (Removed self.).

number of rows contained in existing section after update (15) must equal

So i'm building an app as a hobby and have researched, it appears a few people have a similar problem, except mine happens when inserting the data to begin with. So I think it's slightly different.
When I go to insert data into my array and table it returns an error (title), it retrieves the right amount of current count, but struggled to add a new one.
class AccountsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var totalLabel: UILabel!
#IBOutlet weak var tableview: UITableView!
#IBOutlet weak var tableview2: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//Set the table background as the image
tableview.backgroundView = UIImageView(image: UIImage(named: "splasnowords-1.png"))
//Use the edit button item provided by the table view controller
navigationItem.leftBarButtonItem = editButtonItem
//self.navigationItem.leftBarButtonItem = self.editButtonItem;
//Calculate the latest totalstandings
BudgetDataModel.calculateTotalStandings()
totalLabel.text = ("Total Current Standings = £\(BudgetDataModel.returnTrueValue(number: BudgetDataModel.total))")
self.tableview.delegate = self
self.tableview2.delegate = self
self.tableview.dataSource = self
self.tableview2.dataSource = self
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
if (tableView == tableview){
return 1
//BudgetDataModel.budgets.count
}
else{
return 2
//SavingsDataModel.savings.count
}
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?{
//reload data?
if (tableView == tableview){
return "Budgets"
}
else{
return "Savings"
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var rowCount = 0
if (tableView == self.tableview) {
rowCount = BudgetDataModel.budgets.count
}
if (tableView == self.tableview2) {
rowCount = SavingsDataModel.savings.count
}
return rowCount
// #warning Incomplete implementation, return the number of rows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Table view cells are reused and should be dequeued using a cell identifier.
if (tableView == self.tableview){
let cellIdentifier = "AccountsTableViewCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! AccountsTableViewCell
let budget = BudgetDataModel.budgets[(indexPath as NSIndexPath).row]
cell.nameLabel.text = budget.name
cell.amountLabel.text = ("£\(BudgetDataModel.returnTrueValue(number: budget.amount))")
cell.backgroundColor = UIColor(white: 1, alpha: 0.5)
return cell
}
else if (tableView == self.tableview2){
let cellIdentifier = "SavingsTableViewCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! SavingsTableViewCell
let saving = SavingsDataModel.savings[(indexPath as NSIndexPath).row]
cell.savingsnameLabel.text = saving.savingname
cell.savingsamountLabel.text = ("£\(BudgetDataModel.returnTrueValue(number: saving.savingamount))")
cell.backgroundColor = UIColor(white: 1, alpha: 0.5)
return cell
}
else { preconditionFailure ("unexpected cell type") }
}
// Override to support conditional editing of the table view.
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
// Override to support editing the table view.
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
if (tableView == tableview){
// Delete the row from the data source
BudgetDataModel.budgets.remove(at: indexPath.row)
BudgetDataModel.saveBudgets()
BudgetDataModel.calculateTotalStandings()
totalLabel.text = ("Total Current Standings = £\(BudgetDataModel.returnTrueValue(number:BudgetDataModel.total))")
// self.tableview.reloadData()
tableView.deleteRows(at: [indexPath], with: .fade)
}
else if (tableView == tableview2){
// Delete the row from the data source
SavingsDataModel.savings.remove(at: indexPath.row)
SavingsDataModel.saveSavings()
//implement BudgetDataModel.calculateTotalStandings()
//implement totalLabel.text = ("Total Current Standings = £\(BudgetDataModel.returnTrueValue(number:BudgetDataModel.total))")
//self.tableview2.reloadData()
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
}
}
// Override to support rearranging the table view.
func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "ShowDetail"{
let budgetDetailViewController = segue.destination as! BudgetViewController
//Get the cell that generated this segue.
if let selectedBudgetCell = sender as? AccountsTableViewCell {
let indexPath = tableview.indexPath(for: selectedBudgetCell)!
let selectedBudget = BudgetDataModel.budgets[indexPath.row]
budgetDetailViewController.budget = selectedBudget
}
}
else if segue.identifier == "AddItem"{
//self.tableview.reloadData()
print("Adding new budget.")
}
else if segue.identifier == "ShowSavings"{
let savingDetailViewController = segue.destination as! SavingsViewController
//Get the cell that generated this segue.
if let selectedSavingsCell = sender as? SavingsTableViewCell {
let indexPath = tableview2.indexPath(for: selectedSavingsCell)!
let selectedSavings = SavingsDataModel.savings[indexPath.row]
savingDetailViewController.saving = selectedSavings
}
}
else if segue.identifier == "AddSaving"{
//self.tableview2.reloadData()
print ("Adding new saving.")
}
}
//MARK: Actions
#IBAction func unwindToBudgetList(_ sender: UIStoryboardSegue){
if let sourceViewController = sender.source as? BudgetViewController, let budget = sourceViewController.budget {
if let selectedIndexPath = tableview.indexPathForSelectedRow{
//Update an existing budget.
BudgetDataModel.budgets[selectedIndexPath.row] = budget
tableview.reloadRows(at: [selectedIndexPath], with: .none)
}
else{
//Add a new budget
let newIndexPath = IndexPath(row:BudgetDataModel.budgets.count, section: 0)
BudgetDataModel.budgets.append(budget)
tableview.insertRows(at: [newIndexPath as IndexPath], with: .bottom)
}
//Save the budgets.
BudgetDataModel.saveBudgets()
BudgetDataModel.calculateTotalStandings()
totalLabel.text = ("Total Current Standings = £\(BudgetDataModel.returnTrueValue(number: BudgetDataModel.total))")
}
}
#IBAction func unwindtoSavingsList(_ sender: UIStoryboardSegue){
if let sourceViewController = sender.source as? SavingsViewController, let savings = sourceViewController.saving {
if let selectedIndexPath = tableview2.indexPathForSelectedRow{
//Update an existing budget.
SavingsDataModel.savings[selectedIndexPath.row] = savings
tableview2.reloadRows(at: [selectedIndexPath], with: .none)
}
else{
//Add a new saving
let newIndexPath = IndexPath(row:SavingsDataModel.savings.count, section: 1)
SavingsDataModel.savings.append(savings)
//tableview2.reloadData()
tableview2.insertRows(at: [newIndexPath as IndexPath], with: .bottom)
}
//Save the budgets.
SavingsDataModel.saveSavings()
//implement SavingsDataModel.calculateTotalStandings()
// totalLabel.text = ("Total Current Standings = £\(BudgetDataModel.returnTrueValue(number: BudgetDataModel.total))")
}
}
}
Thanks #jcaron
Two corrections required:
Change my numberofsectionscode to return 1, so that my second table didn't have a randomly replicated second section
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
Replace the section with 0, when adding a new saving
//Add a new saving
let newIndexPath = IndexPath(row:SavingsDataModel.savings.count, section: 1)

Resources