1

I am quite new to this. I am getting an issue with selection items and post back to tableview on specific index cell (reload). Scenario: I have two view controllers and both contains tableview.

FirstViewController: I am already displaying data from webservice into Tableview but on different action types I have used didSelectRow function which shows to ListViewController for item selection. In FirstViewController main model is Unit.

ListViewController: Simple list of data displaying in tableView for selection.

Issue: is how can I select item from ListViewController and pass data to FirstViewController tableview that change occurs on specific cell and then I have to post values with updated values. How can I reload tableview or model?

Model:

struct Unit : Codable {

    let sectionList : [SectionList]?

}

struct SectionList : Codable {

    let title : String?
    let items : [Item]?
}


struct Item : Codable {

    let actionType : Int?
    let textField : String?
    let textValue : String?
    let pickList: [SectionList]?
    let multiSelect: Bool?
    let selectedValue: [String]?
    let version: Int?
    let masterId: Int?
    let itemValue: String?
}

Updated FirstController:

class FirstViewController: UIViewControlller, ListDelegate {

   var selectedIndex: Int?
   var selectedSection: Int?

   //Click event for navigation from FirstViewController to SecondViewController
   @IBAction func BackButtonAction(_ sender: Any) {
       let vc = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
       vc.delegate = self
       self.navigationController?.pushViewController(vc, animated: true)
   }

   func listFunc(listValue: String) {
       AppData?.sectionList?[selectedSection!].items?[selectedIndex!].textField = listValue
       tableView.reloadData()
   }

   func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
       //Add these two line in your code
       selectedIndex = indexPath.row
       selectedSection = indexPath.section
   } 
}

Updated : ListViewController:

protocol ListDelegate {
    func listFunc(listValue: String)
}

class SecondViewController: UIViewControlller {
    var delegate: ListDelegate?

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let indexPath = tableView.indexPathForSelectedRow
        let currentCell = tableView.cellForRow(at: indexPath!)!
        //print(currentCell.textLabel?.text as Any)
        currentCell.accessoryType = .checkmark
        delegate?.listFunc(listValue: currentCell.textLabel?.text ?? "")
        self.navigationController?.popViewController(animated: true)
   }
}
  • Possible duplicate of [Examples of Delegates in Swift](https://stackoverflow.com/questions/40501780/examples-of-delegates-in-swift) – dahiya_boy Nov 29 '19 at 07:41
  • @dahiya_boy I have read delegates but not getting an idea how to select item send to previous viewController tableView cell.. –  Nov 29 '19 at 07:46
  • You need to pass selected data in the delegate func. For more details go with this https://www.appcoda.com/swift-delegate/. Better if you try some demos of delegate and protocol before approach directly in main project. Its not tough but you need to clear you fundamentals first. – dahiya_boy Nov 29 '19 at 08:01
  • @dahiya_boy I am trying to achieve but not up to mark. Can I share my test project with you please ? –  Nov 29 '19 at 12:56
  • Sure, Share github link. – dahiya_boy Nov 29 '19 at 12:58
  • @dahiya_boy Thank you so much. Here is the link. https://github.com/MasamMahmood/SqliteDataList –  Nov 29 '19 at 13:10
  • @dahiya_boy I am new in it not getting an idea is there any update? Is the link accessible to you? –  Dec 02 '19 at 08:35
  • Check my answer. – dahiya_boy Dec 02 '19 at 09:51

2 Answers2

0

You've got a handful of options to accomplish this. Assuming that the selected value is the only value that you've got to pass, using closures would be the easiest thing you could do.

1) Declare a closure that holds a type of your need inside ListViewController:

`var didSelectItem : ((YourType, IndexPath) -> ())?`

2) In ListViewController's didSelectRow method, use the closure:

`self.didSelectItem?(yourDataSourceItemAtIndexpath, indexPath)`

3) You'll get a callback for the triggered closure when you use this closure from your ListViewController instance inside FirstViewController like:

let myListInstance = ListViewController()

myListInstance.didSelectItem = { selectedItem, selectedIndex in
  //You'll get the selected item inside this block, do model updation here

}

After updating your model with new values, if you want to reload your tableView only at the particular(updated) index, you can use:

self.yourTableView.reloadSections(sections: IndexSet, with: UITableView.RowAnimation) to reload a whole section or..

self.yourTableView.reloadRows(at: [IndexPath], with: UITableView.RowAnimation) to reload a row in a section

(If you're performing multiple updates simultaneously, keep in mind that you'll have to do these reloads inside self.yourTableView.beginUpdates() and self.yourTableView.endUpdates())

NOTE:

You'll have to handle your dataSource properly during these reloads to make sure you have the right number of rows or sections before and after the reload, adding/subtracting the rows/sections that you insert/delete. Else, your app will crash!

If you don't want to risk that, just reload the whole table with yourTableView.reloadData()

Also keep in mind that there are other ways to pass data across controllers and this is just a suggestion based on what I assume your use case to be

Lokesh SN
  • 1,583
  • 7
  • 23
0

I hardly able to understand your code, it's totally messed up according to me.

I found that most of your code is done and I am adding rest your things that you need to do.


  1. In your FirstViewController.swift, didSelectRowAt func,

    let vc = self.storyboard?.instantiateViewController(withIdentifier: "ViewController") as! ViewController
    vc.Indexdata = // your data that you wanted to show in your next controller, 
    // if variable is different then assign data to that var
    vc.delegate = self
    self.navigationController?.pushViewController(vc, animated: true)
    
  2. In ViewController.swift, didSelectRowAt func,

    // Comment these below lines
    
    // let vc = self.storyboard?.instantiateViewController(withIdentifier: "FirstViewController") as! FirstViewController
    // self.navigationController?.pushViewController(vc, animated: true)
    
    // Add below line        
    self.navigationController?.popViewController(animated: true)
    

Now check it should work.

dahiya_boy
  • 9,298
  • 1
  • 30
  • 51
  • Yes Thank you its working. Only one thing how to reload in tableview specific index place or model. `let indexPathRow:Int = 0 let indexPosition = IndexPath(row: indexPathRow, section: 0) tableView.reloadRows(at: [indexPosition], with: .none) ` –  Dec 02 '19 at 10:27
  • Your code is good. All you need to find out which IndexPath you need to reload. Better if you specify when you wanted to reload. So that I can assist accordingly. – dahiya_boy Dec 02 '19 at 10:56
  • Thank you. Actually on the basis of action type `14`, `20` I am using list selection item. So in firstViewController I am using same list on multiple table cells. `print(indexPath.row)` & `print(indexPath.section)` Is it possible can update data model and tableview reload because once all selection made and table reload() I have to post values to server. –  Dec 02 '19 at 11:09
  • Sorry I am cleared, Did you mean, you need to update the tableView when you popped from `SecondViewController` ?? – dahiya_boy Dec 02 '19 at 12:48
  • I have done that only getting small issue if you help me in that? My list is used in different tableview cell based on action type. But if I change the value at last it works fine but upper cell click it changed down cell row not the same index row/section. Can you help me in that? Only that cell row value change which I have clicked for it not the last one. –  Dec 02 '19 at 12:48
  • check my updated code, I have done all only index row / section updating issue. It always update the last tableview cell row. Even I have updated the code on github. –  Dec 02 '19 at 12:52