View doesn't get updated until the second time loaded - ios

I have a main view which is a table view with a list of countries. When clicking on any country name (cell), another view is loaded via segue which is passing the name of the country to the next view controller's navigation bar title.
The problem is on the first click the title isn't updated, but when I click back button (dismissing the current view) and click on another country name, the second view loads again and shows the previous title that was suppose to be shown on the first attempt.
The code for the first main view controller:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var sectionsArray = [String]()
var sectionsCountries = [Array<AnyObject>]()
#IBOutlet weak var countries: UITableView!
internal func numberOfSections(in tableView: UITableView) -> Int {
// Return the number of sections.
return self.sectionsArray.count
}
internal func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return self.sectionsCountries[section].count
}
internal func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sectionsArray[section]
}
internal func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CountryCell", for: indexPath)
cell.textLabel?.text = self.sectionsCountries[indexPath.section][indexPath.row] as? String
return cell
}
var valueToPass:String!
internal func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You selected cell #\(indexPath.row)!")
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow;
let currentCell = tableView.cellForRow(at: indexPath!) as UITableViewCell!;
valueToPass = currentCell?.textLabel?.text
performSegue(withIdentifier: "cellSegue", sender: self)
//print(valueToPass)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "cellSegue" {
let destination = segue.destination as! CountryViewController
destination.passedValue = valueToPass
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let url = URL(string: "http://cyber7.co.il/swift/countries/countries-list.json")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print(error)
} else {
if let urlContent = data {
do {
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers)
for result in jsonResult as! [Dictionary<String, AnyObject>]{
self.sectionsArray.append(result["sectionName"] as! String)
self.sectionsCountries.append(result["sectionCountries"] as! Array<String> as [AnyObject])
}
} catch {
print("JSON Processing Failed")
}
DispatchQueue.main.async(execute: { () -> Void in
self.countries.reloadData()
})
}
}
}
task.resume()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
the code for the second view controller:
import UIKit
class CountryViewController: UIViewController {
var passedValue:String!
#IBOutlet weak var navBar: UINavigationBar!
#IBAction func backButton(_ sender: AnyObject) {
self.dismiss(animated: true, completion: nil)
}
override func viewWillAppear(_ animated: Bool) {
self.navBar.topItem?.title = passedValue
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}

When you have a segue set up from a table view cell to a view controller in the storyboard then it is performed automatically when a cell is selected. Your call to perform a segue in your cell selection method is performing the segue a second time after the first one has already been performed.
Remove your tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) method and do all the data passing logic in prepareForSegue:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "cellSegue" {
let destination = segue.destination as! CountryViewController
let indexPath = countries.indexPathForSelectedRow
let currentCell = countries.cellForRow(at: indexPath!)
destination.passedValue = currentCell?.textLabel?.text
}
}

Related

Send data from detail view controller to table view controller

I create an app which uses https://newsapi.org/.
There is a table view that contains news and they have their detail page (Detail View Controller).
Detail view controller has a tab bar button item which is favorites button(<3).
This button send data to favorites table view. But can't send data. Also, in favorites table view you can click the cell and go detail view controller again. So there is two way. And i want to go BACK segue.
main.storyboard:
this is NewsTableViewController:
import UIKit
import Alamofire
class NewsTableViewController: UITableViewController , UISearchBarDelegate {
#IBOutlet weak var searchBar: UISearchBar!
var arr : [Article]? = []
var filteredData: [Article] = []
override func viewDidLoad() {
super.viewDidLoad()
searchBar.delegate = self
//
// let parameters = ["q":"%20", "page": "1", "apiKey":"06c2318ea4c64504b48b3d126168203c"]
let parameters = ["q":"saliha", "page": "1", "apiKey":"06c2318ea4c64504b48b3d126168203c"]
let url = "https://newsapi.org/v2/everything"
AF.request(url, method: .get, parameters: parameters) .responseJSON { (res) in
if(res.response?.statusCode == 200) {
print("res data: ",res.data as Any)
let news = try? JSONDecoder().decode(News.self, from: res.data!)
self.arr = news?.articles
self.tableView.reloadData()
print("kaç sonuç var?",news?.totalResults as Any)
}
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(filteredData.count > 0) {
return filteredData.count
} else {
return arr!.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! NewsTableViewCell
let item: Article
if filteredData.count > 0 {
item = filteredData[indexPath.row]
} else {
item = arr![indexPath.row]
}
DispatchQueue.main.async {
let url = URL(string: item.urlToImage!)
let data = try! Data(contentsOf: url!)
cell.newsImage.image = UIImage(data: data)
}
cell.newsTitle.text = item.title
cell.newsAbout.text = item.description
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let sender: Article
if filteredData.count > 0 {
sender = filteredData[indexPath.row]
}
else {
sender = arr![indexPath.row]
}
performSegue(withIdentifier: "detail", sender: sender)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if ( segue.identifier == "detail" ) {
let vc = segue.destination as! DetailViewController
vc.item = (sender as! Article)
}
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredData = []
if searchText == ""{
filteredData = arr!
}
else{
for item in arr!{
if item.title!.lowercased().contains(searchText.lowercased()){
filteredData.append(item)
}
}
}
self.tableView.reloadData()
}
}
this is DetailViewController:
import UIKit
import Alamofire
class DetailViewController: UIViewController {
var item: Article!
var arr: [Article] = []
var favArr: [Article] = []
#IBOutlet weak var dTitle: UILabel!
#IBOutlet weak var dImage: UIImageView!
#IBOutlet weak var dDate: UILabel!
#IBOutlet weak var dAbout: UITextView!
#IBAction func btnWebview(_ sender: Any) {
performSegue(withIdentifier: "goWeb", sender: item)
}
#IBAction func btnFav(_ sender: UIBarButtonItem) {
print("favoriler ekleme butonuna basıldı")
}
#IBAction func btnShare(_ sender: UIBarButtonItem) {
let items = [URL(string: item.url!)]
let ac = UIActivityViewController(activityItems: items as [Any], applicationActivities: nil)
present(ac, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: item.urlToImage!)
let data = try! Data(contentsOf: url!)
dImage.image = UIImage(data: data)
dTitle.text = item.title
dAbout.text = item.description
dDate.text = item.publishedAt
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if ( segue.identifier == "goWeb" ) {
let vc = segue.destination as! WebViewViewController
vc.item = (sender as! Article)
}
}
}
this is FavoriteTableViewController:
import UIKit
import Alamofire
class FavoriteTableViewController: UITableViewController {
var item: Article!
var arr : [Article]? = []
var favArr: [Article] = []
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.reloadData()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return favArr.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "favcell", for: indexPath) as! FavoriteTableViewCell
let url = URL(string: item.urlToImage!)
let data = try! Data(contentsOf: url!)
cell.fImage.image = UIImage(data: data)
cell.fTitle.text = item.title
cell.fDetail.text = item.description
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "detail", sender: item)
}
/*
// Override to support conditional editing of the table view.
override 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.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
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.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// 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?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}

When adding a text using UITextField from another controller it doesn't show up in the UITableView

I have to create a Web app. I use Split View. In my main view I have and Add button, where I enter the name of the page and its URL, after I press save and it should show up in the UITableView as a new row. All the buttons work, but new row doesn't appear. I'm not sure why.
Here is my main UITableView
import UIKit
import WebKit class WebBrowsers: UITableViewController, NewDelegate {
private var list:[List] = [
List(name: "google", url: URL(string: "https://google.com")),
List(name: "facebook", url: URL(string: "https://www.facebook.com"))
]
#IBOutlet weak var myTableView: UITableView!
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
let addContactVC = storyboard?.instantiateViewController(identifier: "AddBrowser") as! AddBrowser
addContactVC.delegate = self
navigationController?.pushViewController(addContactVC, animated: true)
addContactVC.modalPresentationStyle = .fullScreen
}
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Browsers"
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return list.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
cell.textLabel?.text = list[indexPath.row].name
// Configure the cell...
return cell
}
func addSomeCell(name: String?, url:URL!){
let listNew = List.init(name: name,url: url)
self.list.append(listNew)
myTableView.reloadData()
}
/*
// Override to support conditional editing of the table view.
override 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.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
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 func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if segue.identifier == "showDetail"{
if let navcon = segue.destination as? UINavigationController{
if let destination = navcon.visibleViewController as? infoBrowser{
if let row = tableView.indexPathForSelectedRow?.row{
destination.detailUrl = list[row].url
destination.navigationItem.title = list[row].name
}
}
}
}
}
}
public protocol NewDelegate: class{
func addSomeCell(name: String?, url:URL!)}
here is my AddButton ViewController
import UIKit
class AddBrowser: UIViewController {
var delegate: NewDelegate?
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var urlTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func saveButtonPressed(_ sender: UIButton) {
self.delegate?.addSomeCell(name: nameTextField.text!, url: URL(string: urlTextField.text!))
navigationController?.popViewController(animated: true)
}
/*
// 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?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
} }

How to connect to tableview containers?

I am a beginner to Xcode and Swift and I am currently creating an application where the user adds a person on the application and after that it right the amount of money they owe that person or that person owes him/her.
Note: I have used core data to store all the value
I have ViewController called PeopleTableViewController where the user adds the name of the person they owe. Then I have PersonDetailTableViewController which shows the list of details the user owes that particular person the selected in PeopleTableViewController. The problem I am facing is that if I add three people in PeopleTableViewController and when I select any one of the people then I am directed to same tableview in PersonDetailTableViewController but I want different tableviews for different person the user selects in PeopleTableViewController.
PersonDetailTableViewController:
import UIKit
class PersonDetailTableViewController: UITableViewController {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var totalLabel: UILabel?
var person: People?
var owe: Owe?
#IBOutlet var personTable: UITableView!
var dataInfo: [Owe] = []
var selectedObject: [Owe] = []
var balanceAmount = "Balance: "
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (dataInfo.count)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = personTable
.dequeueReusableCell(withIdentifier: "detailsCell", for: indexPath)
cell.textLabel?.text = dataInfo[indexPath.row].name
cell.detailTextLabel?.text = "₹ \(dataInfo[indexPath.row].amount)"
// if dataInfo[indexPath.row].amount < 0 {
// cell.detailTextLabel?.textColor = UIColor.red
// } else {
// cell.detailTextLabel?.textColor = UIColor.green
// }
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
selectedObject = [dataInfo[indexPath.row]]
performSegue(withIdentifier: "addOweDetails", sender: nil)
tableView.deselectRow(at: indexPath, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
getData()
personTable.dataSource = self
addTotalToNav()
print(dataInfo as Any)
}
// MARK: - Table view data source
func addTotalToNav() -> Void {
if let navigationBar = self.navigationController?.navigationBar {
let totalFrame = CGRect(x: 10, y: 0, width: navigationBar.frame.width/2, height: navigationBar.frame.height)
totalLabel = UILabel(frame: totalFrame)
totalLabel?.text = balanceAmount
totalLabel?.tag = 1
totalLabel?.font = UIFont.boldSystemFont(ofSize: 14)
totalLabel?.textColor = UIColor.red
// navigationBar.large = totalLabel?.text
self.title = totalLabel?.text
}
}
func getData() -> Void {
do{
dataInfo = try context.fetch(Owe.fetchRequest())
var total:Double = 0.00
for i in 0 ..< dataInfo.count {
total += dataInfo[i].amount as! Double
}
balanceAmount = "Balance: ₹" + (NSString(format: "%.2f", total as CVarArg) as String)
}
catch{
print("Fetching Failed")
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! NewOweTableViewController
vc.dataInfo = selectedObject
selectedObject.removeAll()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
getData()
personTable.reloadData()
if (self.navigationController?.navigationBar.viewWithTag(1)?.isHidden == true){
self.navigationController?.navigationBar.viewWithTag(1)?.removeFromSuperview()
addTotalToNav()
}
}
}
PeopleTableViewController:
import UIKit
import CoreData
class PeopleTableViewController: UITableViewController {
#IBOutlet weak var peopleTableView: UITableView!
var people: [People] = []
override func viewDidLoad() {
super.viewDidLoad()
peopleTableView.separatorStyle = .none
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
//ViewWillAppear allows us to fetch all the data in the backend and help us display to the user
override func viewWillAppear(_ animated: Bool) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext = appDelegate.persistentContainer.viewContext
let fetchRequest: NSFetchRequest<People> = People.fetchRequest()
do {
people = try managedContext.fetch(fetchRequest)
peopleTableView.reloadData()
} catch {
print("Could not fetch")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func addButtonPressed(_ sender: UIBarButtonItem) {
}
//Following function is called right before the user segues from one viewcontroller to another viewcontroller
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
guard let destination = segue.destination as? PersonDetailTableViewController,
let selectedRow = self.peopleTableView.indexPathForSelectedRow?.row else {
return
}
destination.person = people[selectedRow]
// destination.owe = people[selectedRow]
}
func deletePerson(at indexPath: IndexPath) {
let person = people[indexPath.row]
guard let managedContext = person.managedObjectContext else {
return
}
managedContext.delete(person)
do {
try managedContext.save()
people.remove(at: indexPath.row)
peopleTableView.deleteRows(at: [indexPath], with: .automatic)
} catch {
print("Could not delete")
peopleTableView.reloadRows(at: [indexPath], with: .automatic)
}
}
}
extension PeopleTableViewController{
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return people.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = peopleTableView.dequeueReusableCell(withIdentifier: "peopleCell", for: indexPath)
let person = people[indexPath.row]
cell.textLabel?.text = person.title
return cell
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
deletePerson(at: indexPath)
}
}
}
The following images shows what I exactly require:
PeopleTableViewController
PeopleTableViewController
On clicking Mike I get following:
PersonDetailTableViewController
On clicking John I get following:
PersonDetailTableViewController
I want that the records for Mike and John should be different that is on PersonDetailTableViewController.
You can try (Both in PeopleTableViewController) , create a segue named shoePersonDetails from PeopleTableViewController to PersonDetailTableViewController
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let person = people[indexPath.row]
performSegue(withIdentifier: "shoePersonDetails", sender: person)
tableView.deselectRow(at: indexPath, animated: true)
}
//
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! PersonDetailTableViewController
vc.dataInfo = sender as! People
}

Pass the myCell.textLabel?.text value via a segue in a dynamic prototype

I'm trying to segue from one UITableView to another UITableView. I want to segue and pass the myCell.textLabel?.text value of the selected cell to the second UITableView.
The code for my first UITableView (MenuTypeTableViewController and the code for my second UITableView (TypeItemsTableViewController) is also below.
I'm fully aware this involves the prepareForSegue function which currently I've not created, purely because I'm unsure where I override it and how to pass in the textLabel value to it.
Hope my question makes sense, I will update with suggestions and edits.
class MenuTypeTableViewController: UITableViewController, MenuTypeServerProtocol {
//Properties
var cellItems: NSArray = NSArray()
var menuType: MenuTypeModel = MenuTypeModel()
override func viewDidLoad() {
super.viewDidLoad()
let menuTypeServer = MenuTypeServer()
menuTypeServer.delegate = self
menuTypeServer.downloadItems()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellItems.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier: String = "cellType"
let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
let item: MenuTypeModel = cellItems[indexPath.row] as! MenuTypeModel
myCell.textLabel?.text = item.type
return myCell
}
func itemsDownloaded(items: NSArray) {
cellItems = items
tableView.reloadData()
}
}
class TypeItemsTableViewController: UITableViewController, TypeItemsServerProtocol {
//Properties
var cellItems: NSArray = NSArray()
var typeItemList: TypeItemsModel = TypeItemsModel()
override func viewDidLoad() {
super.viewDidLoad()
let typeItemsServer = TypeItemsServer()
typeItemsServer.delegate = self
typeItemsServer.downloadItems()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellItems.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier: String = "cellTypeItem"
let myCell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier)!
let item: TypeItemsModel = cellItems[indexPath.row] as! TypeItemsModel
myCell.textLabel?.text = item.name
return myCell
}
func itemsDownloaded(items: NSArray) {
cellItems = items
tableView.reloadData()
}
}
Hi try the following set of code, I have added few additional changes in your code make use of it, I hope it will solve your issue.
I have added only the extra codes which you needed
class TypeItemsTableViewController: UITableViewController, TypeItemsServerProtocol {
// Add this variable in this class and use it whereever you needed it in this class
var selectedItem: String?
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Get the selected cell
let selectedCell = tableView.cellForRow(at: indexPath)
// Now maintain the text which you want in this class variable
selectedItem = selectedCell?.textLabel?.text
// Now perform the segue operation
performSegue(withIdentifier: "TypeItemsTableViewController", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "TypeItemsTableViewController" {
let destinationVC = segue.destination as? TypeItemsTableViewController
destinationVC?.selectedItem = self.selectedItem // Pass the selected item here which we have saved on didSelectRotAt indexPath delegate
}
}
In Second class:
class TypeItemsTableViewController: UITableViewController, TypeItemsServerProtocol {
// Add this variable in this class and use it whereever you needed it in this class
var selectedItem: String?
What you can do is to make a variable in your second UITableView
var String: labelSelected?
then in you prepare for segue method just set the labelSelected to the value of the cell.
refToTableViewCell.labelSelected = youCell.textlabel?.text
If you set up a segue in storyboards from one storyboard to another, you can use the code below in your prepareForSegue method. You'll need to add a testFromMenuTableViewController property to your TypeItemsTableViewController.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? TypeItemsTableViewController,
let path = self.tableView.indexPathForSelectedRow,
let cell = self.tableView.cellForRow(at: path),
let text = cell.textLabel?.text {
destination.textFromMenuTypeTableViewController = text
}
}
For more info check this SO answer.

Swift: Passing data from a tableView in a ViewController to another ViewController

I'm trying to pass the indexPath.row data from the selected cell to the next view controller using both the didSelectCellAtIndexPath and the prepareForSegue methods but the value isnt passing through.
Code for both ViewControllers is show below:
import UIKit
class MainMenu: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
// array of the menu options
let mainMenuOptions = ["Exercises 1", "Exercises 2", "Exercises 3"]
// UITableView
#IBOutlet weak var exerciseOptions: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
exerciseOptions.delegate = self
exerciseOptions.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Table configuration
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ExercisesTableViewCells"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ExercisesTableViewCell
cell.textLabel!.text = mainMenuOptions[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
// Segue to VC based on row selected
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0{
self.performSegueWithIdentifier("SegueToExercises", sender: self)
}
else if indexPath.row == 1{
self.performSegueWithIdentifier("SegueToExercises", sender: self)
}
else{
self.performSegueWithIdentifier("SegueToReminders", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "SegueToExercise"){
let viewController = segue.destinationViewController as? ExerciseMenu
viewController!.mainMenuValue = exerciseOptions.indexPathForSelectedRow!.row
}
}
For the Second View Controller:
import UIKit
class ExerciseMenu: UIViewController, UITextFieldDelegate, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var exerciseOptionsTitle: UILabel!
#IBOutlet weak var exerciseOptionsTable: UITableView!
#IBAction func beginWorkout(sender: AnyObject) {
}
// receives data from MainMenu
var mainMenuValue: Int!
override func viewDidLoad() {
super.viewDidLoad()
exerciseOptionsTable.delegate = self
exerciseOptionsTable.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ExerciseMenuCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ExercisesTableViewCell
cell.textLabel!.text = String(mainMenuValue)
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
See this thread for possible explanations for this behavior.
The first step of troubleshooting would be to put a breakpoint in your prepareForSegue method to see if exerciseOptions.indexPathForSelectedRow is already nil at that point, in which case something is happening before the segue even occurs that's messing with the value (which the link above can help you diagnose).
Try making a property in your table view controller called something like selectedRow, and in didSelectRowAtIndexPath, set self.selectedRow = indexPath.row. This way you have your own variable that'll be more reliable than exerciseOptions.indexPathForSelectedRow. Then change the code in prepareForSegue appropriately. So to give you the full methods as I'm envisioning them:
(As a property of the first view controller) var selectedRow: Int?
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if indexPath.row == 0{
self.performSegueWithIdentifier("SegueToExercises", sender: self)
self.selectedRow = 0
}
else if indexPath.row == 1{
self.performSegueWithIdentifier("SegueToExercises", sender: self)
self.selectedRow = 1
}
else{
self.performSegueWithIdentifier("SegueToReminders", sender: self)
self.selectedRow = indexPath.row
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "SegueToExercise"){
let viewController = segue.destinationViewController as? ExerciseMenu
viewController!.mainMenuValue = self.selectedRow!
}
}
Disclaimer: I'm still learning Swift, so my judgment regarding optionals/optional unwrapping might be unideal for a technical reason I'm not aware of, but the overall theory here is sound, I think.

Resources