swift, tableView selectedTypes buttons - ios

i need an help, see this class
import UIKit
protocol TypesTableViewControllerDelegate: class {
func typesController(controller: TypesTableViewController, didSelectTypes types: [String])
}
class TypesTableViewController: UITableViewController {
let possibleTypesDictionary = ["bakery":"Bakery", "bar":"Bar", "cafe":"Cafe", "grocery_or_supermarket":"Supermarket", "restaurant":"Restaurant"]
var selectedTypes: [String]!
weak var delegate: TypesTableViewControllerDelegate!
var sortedKeys: [String] {
return possibleTypesDictionary.keys.sort()
}
// MARK: - Actions
#IBAction func donePressed(sender: AnyObject) {
delegate?.typesController(self, didSelectTypes: selectedTypes)
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return possibleTypesDictionary.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("TypeCell", forIndexPath: indexPath)
let key = sortedKeys[indexPath.row]
let type = possibleTypesDictionary[key]!
cell.textLabel?.text = type
cell.imageView?.image = UIImage(named: key)
cell.accessoryType = (selectedTypes!).contains(key) ? .Checkmark : .None
return cell
}
// MARK: - Table view delegate
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
let key = sortedKeys[indexPath.row]
if (selectedTypes!).contains(key) {
selectedTypes = selectedTypes.filter({$0 != key})
} else {
selectedTypes.append(key)
}
tableView.reloadData()
}
}
here the user can tap a cell of the tableView so that his prefer types are used on the next viewController for a search, now i need to build a class that do the same thing but there is no a tableview rather only 6 buttons in a view that the user can tap (so a viewController with only 6 different buttons to tap). The problem is that i don't know how to pass to the next viewController what buttons have been pressed and what are not, how can i build this class?
here is the function in the other class that need to know what buttons have been pressed
func fetchNearbyPlaces(coordinate: CLLocationCoordinate2D) {
mapView.clear()
dataProvider.fetchPlacesNearCoordinate(coordinate, radius:searchRadius, types: searchedTypes) { places in
for place: GooglePlace in places {
let marker = PlaceMarker(place: place)
marker.map = self.mapView
where is "types: serchedTypes"

What you wanna do is called delegation here is how you do it:
Make a protocol like this one:
protocol TransferProtocol : class
{
func transferData(types:[String])
}
Make the view controller with the buttons conform to that protocol, I like to do it by adding extensions to my classes like so:
extension ButtonsViewController:TransferProtocol{
func transferData(types:[String]){
//Do whatever you want here
}
}
Declare a variable in your Table View Controller class with the protocol you created as its type, this is called a delegate
weak var transferDelegate:TransferProtocol?
Before you segue to the Buttons View Controller you want to set that view controller as the delegate you just created like so:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as? ButtonsViewController
transferDelegate = vc
vc?.transferData(types: selected)
}
If done correctly you should be able to work with the array you built in the Table View Controller(TypesTableViewController)

Related

Is it valid to reuse a second view controller with dynamic cells to display elements of a different array in Swift?

I currently have 2 table view controllers. I've added two disclosure indicators on two static cells for marital status and home state (canton). The user clicks on one of both and is taken to another view controller where he makes the appropriate selection.
The code is currently working for marital status. My question is if here I could reuse the second view controller (i.e. the one with the dynamic cells) for the same purpose but utilising a different array (in this case an array with states' names). For me it is clear that I could simply add a new view controller and implement the states' list there. Here is a screenshot of the storyboard:
First View Controller code:
import UIKit
class FirstTableViewController: UITableViewController, DataEnteredDelegate {
#IBOutlet var maritalStatusCell: UITableViewCell!
#IBOutlet var maritalStatusLabel: UILabel!
func userDidEnterInformation(info: String) {
maritalStatusLabel.text = "Marital Status: (\(info))"
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "maritalStatusSegue" {
let sendingVC: SecondTableViewController = segue.destination as! SecondTableViewController
sendingVC.delegate = self
}
}
}
Second View Controller code:
import UIKit
protocol DataEnteredDelegate {
func userDidEnterInformation(info: String)
}
class SecondTableViewController: UITableViewController {
let maritalStatusArray: [String] = ["Single", "Married"]
let cantonArray: [String] = ["ZG", "ZH", "BE", "LU", "AG"]
var delegate: DataEnteredDelegate? = nil
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return maritalStatusArray.count
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if delegate != nil {
let information: String? = tableView.cellForRow(at: indexPath)?.textLabel?.text
delegate!.userDidEnterInformation(info: information!)
dismiss(animated: true, completion: nil)
self.navigationController?.popViewController(animated: true)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MaritalStatusCell", for: indexPath)
cell.textLabel?.text = maritalStatusArray[indexPath.row]
return cell
}
}
Does is make sense here to use the second table view controller for the states' list as well ? If yes, how can I implement that ? Thanks.
Yes you can use the Same View controller for displaying the Array of your states' names which I think you have declared in cantonArray, what you need to do is declare a bool variable in Second View Controller (In case if you want to manage only two arrays, if you want to manage more arrays then declare an enum). Then in the segue get from which index that segue is fired, you can get the selected indexPath like this
if let indexPath = tableView.indexPathForSelectedRow{
}
Now check the indexPath.row, if it is 0 then you have selected Marital State so you need to show maritalStatusArray array so make the bool variable true if you get indexpath.row = 1 then make that variable false
Now in Second View Controller add a condition as per the bool variable and show the data from that array like this
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MaritalStatusCell", for: indexPath)
if showMaritalArray {
cell.textLabel?.text = maritalStatusArray[indexPath.row]
} else {
cell.textLabel?.text = cantonArray[indexPath.row]
}
return cell
}
This is how you can declare enum
enum SelectedRow {
case MaritalStatus
case States
case ThirdRow
}
var selectedRow = SelectedRow.MaritalStatus

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
}
}

Swift xCode 6.4 - using a variable generated by a tableview controller in a second view controller

I am am googling around the whole day for a probably simple question but I do not get it right. Hopefully someone can help me.
I have a tableview controller with one prototype cell containing three custom labels.
When I run the app the table view controller will generate about 150 tableview cells with content parsed form a csv-file.
When I click on one of these cells the user will be forwarded two a second view controller showing some additional infotext for his cell selection.
During the same time the user is clicking the tabelview cell a variable will be updated to the corresponding tableview-row-number (e.g. 150 for the last tableview cell.
Now I want to use this variable as reference text within the text shown in the second view controller.
The variable in the tableview controller is "rowSelectedFromList" and will be set by the following code:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var rowSelectedFromList: String
rowSelectedFromList = rowOfItems[indexPath.row].customlabel3!
println(rowSelectedFromList)
}
The "println" is just for checking if it works correctly and it does.
The question is how can I use the variable "rowSelectedFromList" in the second view controller?
Appreciate your help, thanks!
You can add your custom logic in prepareForSegue like this:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let controller = segue.destinationViewController as? YourSecondController,
indexPath = tableView.indexPathForSelectedRow() {
controller.someVariable = rowOfItems[indexPath.row].customlabel3!
}
}
Replace YourSecondController with class name for second view controller.
Don't forget to create IBOutlet for your UITableView and name it tableView.
You'll want to put something in prepareForSegue as well as a variable in your second view controller. So in your table view controller:
var variableToPass: String!
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
variableToPass = rowOfItems[indexPath.row].customlabel3!.text
performSegueWithIdentifier("SecondControllerSegue", sender: nil)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SecondControllerSegue" {
let destinationController = segue.destinationViewController as! SecondViewController
destinationController.passedVariable = variableToPass
}
}
And in your second view controller you'll want to add the variable that the value will be passed to:
var passedVariable: String!
You can, of course, choose to replace the variable with whatever type you wish to send :)
Good question if you want sort this problem plz follow below code:
class ViewController {
var cvDataArray = cells = NSMutableArray.new()
func viewDidLoad() {
super.viewDidLoad()
cvDataArray.enumerateObjectsUsingBlock({(obj: AnyObject, idx: Int, stop: Bool) in var cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("")
cell.textLabel.text = obj["title"]
cells.addObject(cell)
})
tableView.reloadData()
}
func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cells.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cells.objectAtIndex(indexPath.row)
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var cell: UITableViewCell = cells.objectAtIndex(indexPath.row)
}
}
The code which is working for me is a mixture Phoen1xUK and glyuck answers.
I put both together and ended up with this working version:
For the FirstViewController:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "SecondControllerSegue" {
if let indexPath = self.tableView.indexPathForSelectedRow() {
let rowSelectedFromList = rowOfItems[indexPath.row].customlabel3
(segue.destinationViewController as! SecondViewController).rowTransferedFromList = rowSelectedFromList
}
}
}
In the SecondViewController I set up the variable as follows:
var rowTransferedFromList: String!

How to push a new view controller when a table cell is tapped?

I have created this table with 3 sections and 7 rows. The code is shown below
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var subjectTabelView: UITableView!
var slSubject = ["English Lang&Lit", "Chinese Lang&Lit", "Economics"]
var hlSubject = ["Mathematics", "Chemistry", "Biology"]
var tokSubject = ["Theory of Knowledge"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
subjectTabelView.dataSource = self
subjectTabelView.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 3
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return hlSubject.count
}else if section == 1{
return slSubject.count
}else {
return tokSubject.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let subjectCell = tableView.dequeueReusableCellWithIdentifier("idSubjectCell", forIndexPath: indexPath) as! UITableViewCell
if indexPath.section == 0 {
subjectCell.textLabel?.text = hlSubject[indexPath.row]
} else if indexPath.section == 1{
subjectCell.textLabel?.text = slSubject[indexPath.row]
} else {
subjectCell.textLabel?.text = tokSubject[indexPath.row]
}
return subjectCell
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {
return "HL"
} else if section == 1{
return "SL"
} else {
return "ToK"
}
}
}
What do I have to do to make every cell in this table pushes a new view controller when it is tapped? The picture of my storyboard is shown below. In my storyboard, my view controller, I have already created a navigation controller, and made the view controller that has the table the rootViewController. And for now, my tableView has only one prototype cell and one cell identifier.
Thank you!
Suppose your "locationVC" is:
class LocationVC: UIViewController {
#IBOutlet weak var fromWhereLabel: UILabel!
//This can be changed when creating this UIViewController
var textToShow : String?
override func viewWillAppear(animated: Bool) {
if let textToShow = textToShow {
fromWhereLabel.text = textToShow
}
}
}
then, just adding function below to your code in ViewController named UIViewController (that should have a better name ;-)) you can achieve your goal.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//if such cell exists and destination controller (the one to show) exists too..
if let subjectCell = tableView.cellForRowAtIndexPath(indexPath), let destinationViewController = navigationController?.storyboard?.instantiateViewControllerWithIdentifier("locationVC") as? LocationVC{
//This is a bonus, I will be showing at destionation controller the same text of the cell from where it comes...
if let text = subjectCell.textLabel?.text {
destinationViewController.textToShow = text
} else {
destinationViewController.textToShow = "Tapped Cell's textLabel is empty"
}
//Then just push the controller into the view hierarchy
navigationController?.pushViewController(destinationViewController, animated: true)
}
}
You will be able to have a LocationVC UIViewController launched every time you tap a cell, and it will have some value to prove it right. :)
Hope it Helps!
UPDATE: Code and Instructions below are for allowing to launch
different UIViewControllers after tap on cells
1.- Let's create a class that will be the parent for every one of our new UIViewControllers (the ones we are willing to go from our tableview cell's tap):
public class CommonDataViewController: UIViewController {
//Here we are going to be putting any data we want to share with this view
var data: AnyObject?
}
2.- Let's create some sort of Navigation rules, just to be organised ;-)
enum Navigation: Int {
case vc1 = 0, vc2 = 1, vc3 = 2, vc4 = 3
//How many rules we have (for not to exceed this number)
static let definedNavigations = 4
//This must return the identifier for this view on the Storyboard
func storyboardIdentifier() -> String {
//for this example's sake, we have a common prefix for every new view controller, if it's not the case, you can use a switch(self) here
return "locationVC_\(self.rawValue + 1)"
}
}
Now, let's build upon previous code:
3.- For clarity, let's change a little our previous LocationVC (that for this example, will have an Storyboard Identifier with the text "locationVC_1")
class LocationVC: CommonDataViewController {
#IBOutlet weak var fromWhereLabel: UILabel!
//This is optional, but improves clarity..here we take our AnyObject? variable data and transforms it into the type of data this view is excepting
var thisVCReceivedData: String? {
return data as? String
}
override func viewWillAppear(animated: Bool) {
if let textToShow = thisVCReceivedData {
fromWhereLabel.text = textToShow
}
}
}
4.- Now, we trigger all of this in our didSelectRowAtIndexPath function.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
//Just to avoid tapping on a cell that doesn't have an UIViewController asociated
if Navigation.definedNavigations > indexPath.row {
//The view's instance on our Navigation enum to which we most go after tapping this cell
let nextView = Navigation(rawValue: indexPath.row)!
//The identifier of the destination CommonDataViewController's son in our Storyboard
let identifier = nextView.storyboardIdentifier()
//If everything exists...
if let subjectCell = tableView.cellForRowAtIndexPath(indexPath), let destinationViewController = navigationController?.storyboard?.instantiateViewControllerWithIdentifier(identifier) as? CommonDataViewController {
//here you can use a switch around "nextView" for passing different data to every View Controller..for this example, we just pass same String to everyone
if let text = subjectCell.textLabel?.text {
destinationViewController.data = text
} else {
destinationViewController.data = "Tapped Cell's textLabel is empty"
}
navigationController?.pushViewController(destinationViewController, animated: true)
}
}
}
Notice that you can achieve same results using protocols and delegate approach, this is just simpler to explain
Well to push a view controller in a UINavigationController you just use this code:
ViewController *viewController = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:#"locationVC"];
[self.navigationController pushViewController:viewController animated:YES];
The method you are looking for is this one:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ViewController *viewController = [self.navigationController.storyboard instantiateViewControllerWithIdentifier:#"locationVC"];
[self.navigationController pushViewController:viewController animated:YES];
}
You could use prepareForSegue method. You just need to set up the destination view. or the didselectrowatindexpath
prepareForSegue code looks like :
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "nameofTheSegue"
{
if let destinationVC = segue.destinationViewController as? OtherViewController{
// do whatever you want with the data you want to pass.
}
}
}

Why is my variable is changing in printLn but not in the tableview Swift

I've spent ages trying to solve this but with no resolve.
I've finally got to a point where I am pulling my data from one one controller and moving it to the destination controller when I unwind segue, however, when the variable is only reloading in the println but not in the tableview.
I'll try to explain this a bit better with my code as it sounds complicated.
I have a label on one controller which when pressed, presents a UISearchController modally. when you select a cell, it dismisses the view with an unwind segue and passes the data from the cell back to the previous controller to change the label of the button.
I set the label.text in a variable at the top of the initial controller like so
var selectedStation = "Search Stations"
here is my shoddy named function which is used to println the variable to see if it works which it does:
func updateStuff() {
println("you selected \(selectedStation)")
tableView.reloadData()
}
and i declare the label text in my cellForRowAtIndexPath like so:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("searchFieldCell", forIndexPath: indexPath) as! searchFieldTableViewCell
cell.backgroundView = UIImageView(image: UIImage(named: "red-full"))
cell.destinationLabel.text = selectedStation
}
then in my UISearchController i have the following to pass that variable back
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
println(stationArray[indexPath.row])
selectedStation = stationArray[indexPath.row]
self.performSegueWithIdentifier("unwindToSet", sender: self)
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.destinationViewController .isKindOfClass(SetAlertController) {
var VC = segue.destinationViewController as! SetAlertController
VC.selectedStation = self.selectedStation
VC.updateStuff()
}
}
essentially my controller retrieves the updated variable but doesn't update it in the tableview, it only updates it in the println.
i set up a quick demo project with the following viewcontrollers:
class MainViewController: UIViewController {
#IBOutlet weak var label: UILabel!
#IBAction func unwind(segue: UIStoryboardSegue) {
println("unwinding")
if let sourceViewController = segue.sourceViewController as? ModalViewController {
label.text = sourceViewController.selectedText
}
}
}
tapping on the label results in the modalviewcontroller to show. i set this up in storyboard.
class ModalViewController: UITableViewController {
var selectedText: String?
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)!
selectedText = cell.textLabel?.text
performSegueWithIdentifier("unwindToSet", sender: self)
}
}
everything works as expected! feel free to ask if anything is unclear...
you can find the demo project here: https://www.dropbox.com/sh/u2blzmo3ztaaini/AADq8hOMMS71wvBH1eH4Bz_4a?dl=0

Resources