UITableView cells updates just after restart of app - ios

There's a button in another ViewController, if I press on it, I should see the time when I pressed on the button.
The button works, but the table won't refresh after I click on a refresh button, place the refresh on the ViewDidAppear function doesn't work as well.
I need to quit the app, close it from multitasking and open it again, then the time that I pressed on the button shows. What should I do to make the refresh button work?
(Both View Controllers are in the same storyboard, the second one extends the first one)
First View Controller:
class Tracking: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var activity: UITableView!
var activities = [String]()
var userData = false
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return activities.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
cell.textLabel?.text = activities[indexPath.row]
return(cell)
}
#IBAction func Reload(_ sender: AnyObject) {
activity.reloadData()
}
.
.
.
}
Second view controller:
class Activity: Tracking {
.
.
.
#IBAction func playButton(_ sender: AnyObject) {
isPlayed += 1
userData = true
UserDefaults.standard.set(userData, forKey: "userData")
let playElm = playStr + " בשעה: " + getTime()
activities.append(playElm)
UserDefaults.standard.set(activities, forKey: "activities")
}
.
.
.
}

You need to fetch from user defaults your new date in activities array and after that you can reloadData
#IBAction func Reload(_ sender: AnyObject) {
self.activities = UserDefaults.standard.get( forKey: "activities")
activity.reloadData()
}

When you call activity.reloadData(), you're telling the table view to update its rows and what they display based solely on the contents of your activities property that you defined with the line:
var activities = [String]()
When you're loading the app from a fresh start, that activities array of strings hasn't been filled with anything. I see you save data to UserDefaults, but I don't see anywhere from which you read it.
Put this next code in your viewDidLoad(). viewDidAppear() isn't what you want to use for this purpose.
activities = UserDefaults.standard.get(forKey: "activities")
activity.reloadData()

I managed to get this working automaticlly without the refresh button. The code that Svetoslav Bramchev wrote works when I place it in viewDidAppear. Thanks for your help!
override func viewDidLoad() {
super.viewDidLoad()
userData = UserDefaults.standard.bool(forKey: "userData")
if(userData == true){
activities = UserDefaults.standard.object(forKey: "activities") as! [String]
} else {
activities.append("no data")
UserDefaults.standard.set(activities, forKey: "activities")
if(activities[0] == "no data"){
activities.remove(at: 0)
UserDefaults.standard.set(activities, forKey: "activities")
}
}
}
override func viewDidAppear(_ animated: Bool) {
activities = UserDefaults.standard.object(forKey: "activities") as! [String]
activity.reloadData()
}

Related

Swift retain UISegmentedControl values in UITableViewCells

I'm creating a quiz app with custom cells that include a label of questions and then an answer coming from a UISegmentedControl.
The values of the segmentedcontrols get changed when scrolling and this leads to an inaccurate score. I understand that this is due to UITableView reusing cells.
My tableview's datasource in my main vc is simply the labels for all my questions coming from a plist file.
The code for my custom tableviewcell class is
class QuestionsTableViewCell: UITableViewCell {
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var selection: UISegmentedControl!
var question: String = "" {
didSet {
if (question != oldValue) {
questionLabel.text = question
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
//Just for testing
#IBAction func segmentChanged(_ sender: UISegmentedControl) {
print("value is ", sender.selectedSegmentIndex);
}
}
where the View is stored in an .XIB file.
And the code for my main vc is
class ViewController: UIViewController, UITableViewDataSource {
let questionsTableIdentifier = "QuestionsTableIdentifier"
#IBOutlet var tableView:UITableView!
var questionsArray = [String]();
var questionsCellArray = [QuestionsTableViewCell]();
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let path = Bundle.main.path(forResource:
"Questions", ofType: "plist")
questionsArray = NSArray(contentsOfFile: path!) as! [String]
tableView.register(QuestionsTableViewCell.self,
forCellReuseIdentifier: questionsTableIdentifier)
let xib = UINib(nibName: "QuestionsTableViewCell", bundle: nil)
tableView.register(xib,
forCellReuseIdentifier: questionsTableIdentifier)
tableView.rowHeight = 108;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return questionsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(
withIdentifier: questionsTableIdentifier, for: indexPath)
as! QuestionsTableViewCell
let rowData = questionsArray[indexPath.row]
cell.question = rowData
return cell
}
#IBAction func calculate(_ sender: UIButton) {
var score = 0
for cell in tableView.visibleCells as! [QuestionsTableViewCell] {
score += cell.selection.selectedSegmentIndex
}
let msg = "Score is, \(score)"
print(msg)
}
#IBAction func reset(_ sender: UIButton) {
for cell in tableView.visibleCells as! [QuestionsTableViewCell] {
cell.selection.selectedSegmentIndex = 0;
}
}
}
What I'd like to do is just keep track of all 'selection' changes of the Questions cells in an array, and then use that array in cellForRowAt. I'm just confused as to how i can dynamically keep track of changes from a view in another class. I'm new to Swift and would like to solve this is a proper MVC fashion. Thanks
Instead of a simple string array as data source create a class holding the text and the selected index
class Question {
let text : String
var answerIndex : Int
init(text : String, answerIndex : Int = 0) {
self.text = text
self.answerIndex = answerIndex
}
}
Declare questionArray as
var questions = [Question]()
Populate the array in viewDidLoad with
let url = Bundle.main.url(forResource: "Questions", withExtension: "plist")!
let data = try! Data(contentsOf: url)
let questionsArray = try! PropertyListSerialization.propertyList(from: data, format: nil) as! [String]
questions = questionsArray.map {Question(text: $0)}
In the custom cell add a callback and call it in the segmentChanged method passing the selected index, the property question is not needed, the label is updated in cellForRow of the controller
class QuestionsTableViewCell: UITableViewCell {
#IBOutlet weak var questionLabel: UILabel!
#IBOutlet weak var selection: UISegmentedControl!
var callback : ((Int) -> ())?
#IBAction func segmentChanged(_ sender: UISegmentedControl) {
print("value is ", sender.selectedSegmentIndex)
callback?(sender.selectedSegmentIndex)
}
}
In cellForRow add the callback and update the model in the closure
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: questionsTableIdentifier, for: indexPath) as! QuestionsTableViewCell
let question = questions[indexPath.row]
cell.questionLabel.text = question.text
cell.selection.selectedSegmentIndex = question.answerIndex
cell.callback = { index in
question.answerIndex = index
}
return cell
}
To reset the segmented controls in the cells set the property in the model to 0 and reload the table view
#IBAction func reset(_ sender: UIButton) {
questions.forEach { $0.answerIndex = 0 }
self.tableView.reloadData()
}
Now you could calculate the score directly from the model instead of the view.
Don't try to use cells to hold information. As the user scrolls through your table view, cells that scroll out of view will get recycled and their field settings will be lost. Also, newly dequeued cells will have the settings from the last time they were used.
You need to refactor your code to read/write information into a data model. Using an array of Structs as a data model is a reasonable way to go. (Or, as vadian suggests in his answer, and array of Class objects, so you get reference semantics.)
You have an IBAction segmentChanged() in your custom cell class. The next trick is to notify the view controller when the user changes the selection, and to update cells when you set them up in cellForRowAt.
I suggest defining a protocol QuestionsTableViewCellProtocol, and have the view controller conform to that protocol:
protocol QuestionsTableViewCellProtocol {
func userSelected(segmentIndex: Int, inCell cell: UITableViewCell)
}
}
Add a delegate property to your QuestionsTableViewCell class:
class QuestionsTableViewCell: UITableViewCell {
weak var delegate: QuestionsTableViewCellProtocol?
//The rest of your class goes here...
}
Update your cell's segmentChanged() method to invoke the delegate's userSelected(segmentIndex:inCell:) method.
In your view controller's cellForRowAt, set the cell's delegate to self.
func userSelected(segmentIndex: Int, inCellCell cell: UITableViewCell) {
let indexPath = tableView.indexPath(for: cell)
let row = indexPath.row
//The code below assumes that you have an array of structs, `dataModel`, that
//has a property selectedIndex that remembers which cell is selected.
//Adjust the code below to match your actual array that keeps track of your data.
dataModel[row].selectedIndex = segmentIndex
}
Then update cellforRowAt() to use the data model to set the segment index on the newly dequeued cell to the correct index.
Also update your calculate() function to look at the values in your dataModel to calculate the score, NOT the tableView.
That's a rough idea. I left some details out as "an exercise for the reader." See if you can figure out how to make that work.

Data in the UITableView get duplicated when back button is pressed

I working on a project that is written in swift 3.0. My requirement is to save data (on CoreData) that I enter on some text fields and populate one of those attributes in to a table view, thus once a row is selected I wants to update that record (re-assign values on my text fields and save).
Basically I have an entity named "Task" and it got three attributes, and I wants to populate one of those attributes(called "name") that I have saved on core data, in to a table view. Hence when I wants to edit the data that I entered, I tap on a row and it'll direct me to the ViewController where I initially entered those data. However when I click the back button without saving the data it'll duplicate the array and populate in my table view. how can I stop this. The code of the table view class as follow.
import UIKit
import CoreData
class TableViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var stores = [Store] ()
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.reloadData()
// Do any additional setup after loading the view.
}
override func viewDidAppear(_ animated: Bool) {
let request = NSFetchRequest <NSFetchRequestResult> (entityName: "Store")
request.returnsObjectsAsFaults = false
do {
let results = try context.fetch(request) as! [Store]
// check data existance
if results.count>0 {
print(results.count)
for resultGot in results {
if let expName = resultGot.name {
print("expence name is :", expName)
stores += [resultGot]
print("my array is : \(stores)")
}
}
self.tableView.reloadData()
}
}catch{
print("No Data to load")
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return stores.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell ()
let store = stores [indexPath.row]
cell.textLabel?.text = store.name
//cell.textLabel?.text = myExpensesArray[indexPath.row]
return cell
}
#IBAction func nextButtonPressed(_ sender: AnyObject) {
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "editStore", sender: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "editStore"{
let v = segue.destination as! ViewController
let indexPath = self.tableView.indexPathForSelectedRow
let row = indexPath?.row
v.store = stores[row!]
}
}
This is happening because already loaded elements are present inside your array. When you came back to previously loaded ViewController its method viewWillAppear, viewDidAppear called everytime according to the viewController's life cycle.
You need to clear your previously loaded array using removeAll() method when you came back.
Use below code:
override func viewDidAppear(_ animated: Bool) {
stores.removeAll() // clears all element
let request = NSFetchRequest <NSFetchRequestResult> (entityName: "Store")
request.returnsObjectsAsFaults = false
do {
let results = try context.fetch(request) as! [Store]
// check data existance
if results.count>0 {
print(results.count)
for resultGot in results {
if let expName = resultGot.name {
print("expence name is :", expName)
stores += [resultGot]
print("my array is : \(stores)")
}
}
self.tableView.reloadData()
}
}catch{
print("No Data to load")
}
}
You populate your tableView in the viewDidAppear method which is execute everytime the view is shown (either for first time or coming back from a anbother detail view controller).
You either
populate it once by moving the populate code to viewDidLoad
or clean (remove all objects from) the stores before repopulating it, if you need fresh data to be shown. so before for resultGot in results
insert something like
stores = []

Why TableView is empty

There are two ViewControllers in the app. The first one has a WebView and a Navigation Bar on top, the second one is a TableView to show URLs visited. Please see screenshots and codes. After I clicked Save button to save current URL user is visiting, the TableView is empty. I have tested the TableView first, it is set up fine. Please help to find out the problem. By the way, var savedURLs = [String]( I didn't put the other half of bracket as it won't show correctly if I put it.)
import UIKit
class BrowserViewController: UIViewController {
#IBOutlet weak var browser: UIWebView!
#IBAction func saveButtonPressed(sender: AnyObject) {
if let currentURL = browser.request?.URL?.absoluteString {
savedURLs.append(currentURL)
NSUserDefaults.standardUserDefaults().setObject(savedURLs, forKey: "savedURLs")
}
}
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL(string: "https://www.google.com")!
let request = NSURLRequest(URL: url)
browser.loadRequest(request)
}
}
import UIKit
var savedURLs = [String](
class SavingViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var savingTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
savingTableView.delegate = self
savingTableView.dataSource = self
if NSUserDefaults.standardUserDefaults().objectForKey("savedURLs") != nil {
savedURLs = NSUserDefaults.standardUserDefaults().objectForKey("savedURLs") as! [String]
}
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return savedURLs.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("SavingCell")
cell!.textLabel?.text = savedURLs[indexPath.row]
return cell!
}
override func viewDidAppear(animated: Bool) {
savingTableView.reloadData()
}
}
Please check the currentURL is not nil. Because of empty currentURL your tableview is empty.
I suggest you to Saved the urls in NSuserdefault after webview loading finished completely. Hope this will help you.
I think you should add this function:
func reloadTable() {
if NSUserDefaults.standardUserDefaults().objectForKey("savedURLs") != nil {
savedURLs = NSUserDefaults.standardUserDefaults().objectForKey("savedURLs") as! [String]
}
savingTableView.reloadData()
}
And call that one instad of savingTableView.reloadData()
Also debug the code by printing the value of variables at some points. For example the new data when you read from NSUserDefaults and the value of savedURLs in viewDidAppear.
If that doesn't work make sure you're using the right cell identifier:
let cell = tableView.dequeueReusableCellWithIdentifier("SavingCell")
Try passing the data to the next view controller when you click on send button rather than using NSUserDefaults.
Maintain an array by appending the URLs that you visit, then pass it to the next view controller when you click on send.

reloadData() isn't work in swift

So, I have trouble - can't reloadData of TableView, in command line I see good data - when I click button idMeet is changed, but in Simulator I don't see refresh table view after click on the button, and idMeet is changed and my query is changed too. I understand that I must use tableView.reloadData(), but don't understand where write it for correct working?
var x = true;
#IBOutlet weak var myButton: UIButton!
#IBOutlet var tbRouteData: UITableView!
#IBAction func act(sender: UIButton) {
x = !x
getInfo()
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
self.getTmp()
}
func getInfo() -> NSMutableArray {
sharedInstance.database!.open()
var idMeet: Int
if x {
idMeet = 1
} else {
idMeet = 2
}
print(idroute)
let selectInfo: FMResultSet! = sharedInstance.database!.executeQuery("SELECT * FROM t1 AS one JOIN t2 AS two ON (one.id = two.id AND two.line_id = ?) ORDER BY two.position ASC", withArgumentsInArray: [idMeet])
...
return tmp
}
func getTmp(){
infoTmp = NSMutableArray()
infoTmp = getInfo()
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infoTmp.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! PrivateCell
let my:Info = infoTmp.objectAtIndex(indexPath.row) as! Info
cell.listOfStop.text = my.Name.uppercaseString
return cell
}
There are a few issues here:
The getTmp function should reload the data:
func getTmp(){
infoTmp = getInfo()
tbRouteData.reloadData()
}
Now that you have a function that populates the property and reloads the table, act should call that, rather than getInfo:
#IBAction func act(sender: UIButton) {
x = !x
getTmp()
}
When you call getInfo, that doesn't set infoTmp. And by calling getTmp that centralizes the population of infoTmp and reloading of the table in one place.
If you're not seeing any data in your table view, make sure that you've set the delegate of the table view accordingly. You can do that either in IB, or programmatically:
override func viewDidLoad() {
super.viewDidLoad()
tbRouteData.delegate = self
}
This assumes, of course, that you defined your view controller to conform to UITableViewDataSource and have implemented the appropriate methods. Without seeing those methods, we can't tell if there might be some further issue there.
func getTmp(){
infoTmp = NSMutableArray()
infoTmp = getInfo()
tbRouteData.reloadData()
}
Write this code and this will reload your tableview with new data after the array fills up
The reload data should be completed within the button but after the getInfo() has been completed. The following should work:
#IBAction func act(sender: UIButton) {
x = !x
getInfo()
tbRouteData.reloadData()
}
Usually when tableView data array become changed then tableView should reload. In this case at the end of the button action method reload tableview.
#IBAction func act(sender: UIButton) {
x = !x
getInfo()
tbRouteData.reloadData()
}

swift couldn't store data back to array, even during seguing

I have two viewcontrollers, one is rootviewcontroller, the other one is selectorviewcontroller. In rootvc, there is a textfield and button, when the button is clicked, it takes us to the selectorvc where we can choose and if necessary add a new item (area) and then choose the item, after we choose it, it takes us back to the rootvc, and display the selected item in the textfield. I understand that if we don't use data persistence measures, the data added in won't persist after we recommence the app. Although I can add in new item to the selectorvc, but the newly added data just gone even after we unwind the segue back to rootvc and re-enter the selectorvc. I am not sure where I did wrong, as the data storing array is mutable. It is great if you could pointing me to the right direction. Thanks a lot.
A simple array is defined to store the data,
import UIKit
class AreaClass {
var areaName: String
init? (areaName: String) {
self.areaName = areaName
if areaName.isEmpty {
return nil
}
}
}
This is the unwind segue in the rootvc,
#IBAction func unwindWithSelectedArea(segue:UIStoryboardSegue) {
if let SelectorViewController = segue.sourceViewController as? SelectorViewController,
selectedArea = SelectorViewController.selectedArea
{
AreaSelectedTextField.text = selectedArea
}
}
This is the declaration and addnewitem in the selectorvc,
var selectedArea: String?
var selectedAreaIndex: Int?
var areas = [AreaClass]()
var newarea = AreaClass?()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
areaNewnSelectedTF.delegate = self
saveButton.enabled = false
loadSample()
// Do any additional setup after loading the view.
}
func loadSample (){
let area1 = AreaClass(areaName: "TopHill")!
let area2 = AreaClass(areaName: "Foothill")!
let area3 = AreaClass(areaName: "Summit")!
let area4 = AreaClass(areaName: "Riverside")!
areas += [area1, area2, area3, area4]
}
#IBAction func addNewArea(sender: UIBarButtonItem) {
var dupli = false
if saveButton == sender {
let areaname = areaNewnSelectedTF.text ?? ""
newarea = AreaClass(areaName: areaname)
for var index = 0; index < areas.count; ++index {
if areaname == areas[index].areaName {
dupli = true
// Mark: alert for duplicate inputs
let alert = UIAlertController(title: "Duplicate", message: "Can't have same items", preferredStyle:.Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alert, animated: true, completion: nil)
}
}
if dupli == false {
let newIndexPath = NSIndexPath(forRow: areas.count, inSection: 0)
areas.append(newarea!)
tableView.insertRowsAtIndexPaths([newIndexPath], withRowAnimation: .Bottom)
}
}
}
This is the PrepareforSegue in selectorvc
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "saveSelectionSegue" {
if let cell = sender as? UITableViewCell {
let indexPath = tableView.indexPathForCell(cell)
if let index = indexPath?.row {
selectedArea = areas[index].areaName
}
}
}
}
You need to use a delegate to pass data from a childViewController to your rootViewController.
Below there are ViewController(root) and SelectTableViewController(selector), they implement a simple example of what you look for. I used a struct to make it simple.
At first, you need to create a protocol using the role of your delegate => ViewControllerDelegate with a simple function with an argument "AreaStruct".
This protocol needs to be implemented by the "root". When you pressed the button, you performSegueWithIdentifier that will call prepareForSegue. In it, you pass yourself(ViewControllerDelegate) to the destinationViewController.
In your destinationViewController, the user select one row. By selecting, it triggers didSelectRowAtIndex. In it, you get the selectedArea (the concern AreaStruct) and with your delegate, you call choseArea(...). After that you pop the ViewController to go back to the root.
When you call choseArea, it will put the areaName into the label to display what you selected as shown by the implementation of choseArea(areaStruct : AreaStruct) in your RootViewController.(In this function, you can do whatever you want with your areaStruct)
------ EDIT ------
In your code, your "selectorviewcontroller" create the data => loadSample. So no matter what happened when you go to "selectorviewcontroller", you will always loadSample even if you added new "areas" before. I updated my example code based on your example.
ViewController -> press button -> SelectTableViewController -> add area -> select area -> back to ViewController
To summarise,
in ViewController, I setupListData when viewDidLoad is called
I pressed the button to go to SelectTableViewController
3 I passed myself(delegate) and dataList to SelectTableViewController in prepareForSegue
SelectTableViewController is loaded and display my list based on dataList !
I pressed addNewArea, it append a new area to "areas" that is only local to SelectTableViewController !
My list is refreshed and displays my new area
I select an area
I call the delegate by passing 2 arguments : What I selected and my updated areas(List); I pop SelectViewController => Popping SelectViewController, it disappear and all data are lost
When I called the delegate, I updated my label based on what I selected and also I updated dataList in ViewController with areas (from SelectTableViewController).
When I click on my button, see point 2.1. => You should understand
If you want to persist data, you could use different techniques such as singleton, core data, NSUserDefaults, etc.
ViewController.swift
import UIKit
import Foundation
struct AreaStruct {
var areaName : String
}
protocol ViewControllerDelegate : class{
func choseArea(areaStruct : AreaStruct, areas : [AreaStruct])
}
class ViewController: UIViewController, ViewControllerDelegate { //1. Implement the delegate here.
#IBOutlet weak var infoLabel: UILabel!
#IBOutlet weak var btnToVC: UIButton!
var dataList : [AreaStruct] = [AreaStruct]()
override func viewDidLoad() {
super.viewDidLoad()
self.setupListData()
}
func setupListData(){
for i in 0...5{
dataList.append(AreaStruct.init(areaName: "Coucou \(i)"))
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SelectTableViewController" {
let destinationViewController = segue.destinationViewController as! SelectTableViewController
destinationViewController.delegate = self //2. Here you passed itself to the destinationViewController so it can know how to call you !
destinationViewController.areas = dataList //
}
}
func choseArea(areaStruct : AreaStruct, areas : [AreaStruct]) {
self.infoLabel.text = areaStruct.areaName
dataList = areas
}
#IBAction func pushToSelectTableViewController(sender: AnyObject) {
//0. When pressed, you want to go to SelectTableViewController
self.performSegueWithIdentifier("SelectTableViewController", sender: nil)
}
}
SelectTableViewController.swift
import UIKit
class SelectTableViewController: UITableViewController {
var areas : [AreaStruct] = [AreaStruct]()
weak var delegate : ViewControllerDelegate? // <-- Delegate to send a mess. to ViewController
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func addNewArea(sender: UIBarButtonItem) {
let hello_world = "Hello World" //For the example !
areas.append(AreaStruct.init(areaName: hello_world))
self.tableView.reloadData()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return areas.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("reuseIdentifier", forIndexPath: indexPath)
cell.textLabel?.text = areas[indexPath.row].areaName
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedArea = areas[indexPath.row]
self.delegate?.choseArea(selectedArea, areas: areas) //3. When you select, you pass the data to ViewController via the delegate
self.navigationController?.popViewControllerAnimated(true)//4. You dismiss itself
}
}

Resources