Swift - table is empty after moving between controllers - ios

I'm updating existing Objective-C app.
There is a structure:
AppDelegate
- creates mainBackgroundView and adding subview with UITabBarController
I have in one "Tab" HistoryViewController:
#objc class HistoryViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let historyTableViewController = HistoryTableViewController()
self.view.addSubview(historyTableViewController.view)
}
}
And HistoryTableViewController:
import UIKit
#objc class HistoryTableViewController: UITableViewController {
// Mark: properties
var historyCalls = [HistoryItem]()
// Mark: private methods
private func loadSimpleHistory() {
let hist1 = HistoryItem(personName: "Test", bottomLine: "text", date: "10:47")
let hist2 = HistoryItem(personName: "Test 2", bottomLine: "text", date: "10:47")
let hist3 = HistoryItem(personName: "Test 3", bottomLine: "text", date: "10:47")
historyCalls += [hist1, hist2, hist3]
}
override func viewDidLoad() {
super.viewDidLoad()
self.loadSimpleHistory()
self.tableView.register(UINib(nibName: "HistoryCallTableViewCell", bundle: nil), forCellReuseIdentifier: "HistoryCallTableViewCell")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// 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 historyCalls.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "HistoryCallTableViewCell", for: indexPath) as? HistoryCallTableViewCell else {
fatalError("Coulnd't parse table cell!")
}
let historyItem = historyCalls[indexPath.row]
cell.personName.text = historyItem.personName
cell.bottomLine.text = historyItem.bottomLine
cell.date.text = historyItem.date
return cell
}
}
When I open the navigation tab with HistoryViewController for the first time, table appers with data. When I click into the table or switch navTab and then go back, table is not there anymore.
When I switch to another app and then go back, table is there again.
How to fix this?
Thank you

Call data method in viewwillappear and reload the table..
override func viewWillAppear() {
super.viewWillAppear()
self.loadSimpleHistory()
self.tableview.reloadData()
}

Related

Problem tu update tableview, Delegate Hell

first of all I'am renewing my votes with mobile dev almost 4 yeas without any code, a decided to start over new... so is like I'm a newvbie right now!!!
I'm creating a sort of restaurant app, where you can choose pizza, dinks and some other staff that i haven't decided yet.
My problems is..my main view controller I have a UIView and inside it a table view...
I've put a button (the pizza button) that has a segue to another view with a table view controller and data is plenty of pizza info. You have to choose a pizza and then DONE button witch sends data back to my main view controller and this view controller should populate the table view from the choice I've made in the view before.
This is my storyboard
My OrderTableViewController do this:
class OrderTableViewController: UITableViewController {
var orderedItems = OrderList();
override func viewDidLoad() {
super.viewDidLoad()
let noOrder = OrderItem()
noOrder.itemName = "No item Yet"
orderedItems.add(orderItem: noOrder)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true);
}
// 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 orderedItems.list.count;
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// Configure the cell...
let row = indexPath.row
cell.textLabel?.text = orderedItems.list[row].itemName
cell.detailTextLabel?.text = orderedItems.list[row].itemSize
return cell
}
// MARK - Dev methods
func updateTable(orderList:OrderList){
// Here in this line I get que item from my other tableview
print("\(orderedItems.lastSelection) inside OrderTableView");
orderedItems = orderList;
tableView.reloadData();
}
Before call reloadData() I can see that that the result is correctly put on the orderedItem I can even print it
But the method reloadData does nothing.. the view keep showing "no items".
Maybe I misunderstood the whole protocol delegate pattern.
Can you see where is it wrong?
My MainController;
class MainController: UIViewController, PizzaViewControllerDelegate {
var orderedItems = OrderList();
var orderTableVC = OrderTableViewController()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
orderTableVC.updateTable(orderList: orderedItems);
}
func didSelectPizza(pizza: OrderItem) {
orderedItems.add(orderItem: pizza);
orderTableVC.updateTable(orderList: orderedItems);
}
// 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.
if segue.identifier == "orderSegue" { //embedded view -- keep controller around
orderTableVC = segue.destination as! OrderTableViewController
}
if segue.identifier == "pizzaSegue"{
let pizzaViewController = segue.destination as! PizzaViewController
pizzaViewController.delegate = self
}
}
}
My protocol for pizza:
protocol PizzaViewControllerDelegate {
func didSelectPizza(pizza:OrderItem);
}
protocol PizzaTableViewControllerDelegate {
func didSelectPizzaCell(pizza:String)
}
My PizzaViewController
class PizzaViewController: UIViewController, PizzaTableViewControllerDelegate {
var pizza = OrderItem();
var delegate: PizzaViewControllerDelegate!;
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
// 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.
if segue.identifier == "pizzaTableSegue" {
let vc = segue.destination as! PizzaTableViewController;
vc.delegate = self;
}
}
//IBActions
#IBAction func didCancel(_ sender: Any) {
_ = navigationController?.popViewController(animated: true);
}
#IBAction func didDone(_ sender: UIButton) {
delegate.didSelectPizza(pizza: pizza);
_ = navigationController?.popViewController(animated: true);
}
// MARK -
func didSelectPizzaCell(pizza: String) {
self.pizza.itemName = pizza;
}
}
My PizzaTableViewControlle
class PizzaTableViewController: UITableViewController {
var delegate:PizzaTableViewControllerDelegate! = nil
var pizzaMenu = PizzaMenu();
var pizza = String();
override func viewDidLoad() {
super.viewDidLoad()
}
// 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 pizzaMenu.menu.count;
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath);
let row = indexPath.row;
cell.textLabel?.text = pizzaMenu.menu[row].pizzaName;
cell.detailTextLabel?.text = pizzaMenu.menu[row].pizzaDescription;
// Configure the cell...
//Making the cell fancy
//font changes
cell.textLabel?.font = UIFont.preferredFont(forTextStyle: .headline)
cell.detailTextLabel?.font = UIFont.preferredFont(forTextStyle: .caption1)
cell.textLabel?.backgroundColor = UIColor.clear
cell.detailTextLabel?.backgroundColor = UIColor.clear
if row % 2 == 0 {
cell.backgroundColor = UIColor(white: 1.0, alpha: 0.7)
} else {
cell.backgroundColor = UIColor(white: 1.0, alpha: 0.5)
}
return cell;
}
// MARK: - TableView Delegate Methods
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
pizza = pizzaMenu.menu[indexPath.row].pizzaName;
delegate.didSelectPizzaCell(pizza: pizza);
}
///This changes cell format on the fly
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return view.frame.size.height/5.0;
}
}
I'm sure that is something I haven't understood yet.. :)
Thanks!!!

How to add alphabetic sections in TableView from database using swift 3

I'v created a TableView that shows data from my database, now I want to add alphabetic sections into my table my database already sorted alphabetically.
My problems:
1 - I can't make the Dictionary to accesses only the first column of the database (the name column).
2 - I don't know how to get the first letter of the names and store every item in the letter the name start with.
If you know a better way than using a Dictionary I'm open to any suggestions.
My code:
class crimesTableViewController: UITableViewController {
var marrCrimesData : NSMutableArray!
#IBOutlet weak var crimesTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
self.getCrimesData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getCrimesData()
{
marrCrimesData = NSMutableArray()
marrCrimesData = ModelManager.getInstance().getAllCrimesData()
crimesTableView.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 marrCrimesData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: crimesTableViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! crimesTableViewCell
let crime: CrimesInfo = marrCrimesData.object(at: indexPath.row) as! CrimesInfo
cell.nameLabel.text = crime.Name
cell.detailLabel.text = crime.Detail
cell.timeLabel.text = crime.Time
return cell
}

Append array from another Controller

I want to append new element to array. I'm using container view. I call addItem function to tableviewcontroller. But I clicked button nothing happen.
My TableViewController
import UIKit
class TableViewController: UITableViewController {
var myArray = ["1"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func addItem () {
myArray.append("asd")
tableView.reloadData()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(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 myArray.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath)
// Configure the cell...
cell.textLabel?.text = myArray[indexPath.row]
return cell
}
}
My TableViewController
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func addButton(sender: AnyObject) {
TableViewController().addItem()
}
}
The line TableViewController().addItem() means create a brand new instance of TableViewController and then call addItem() on it. You need to find a reference to the specific instance of TableViewController you want to manipulate. How does that ViewController relate to the one calling addItem?
It should be something like this:
class ViewController: UIViewController {
let tableViewController = TableViewController()
..
#IBAction func addButton(sender: AnyObject) {
tableViewController.addItem()
}
}

second TableView Cell dissapear in my TabBarController

I got an TabBar bassed app (using Swift) and i got 2 table views in different ViewControllers, and just the table that is in the first View, but isnt in other views.
I check the display of the cells and is ok.
If i put another view (without a table as first view) the other views within table views dont appear also.
some images of my problem
http://s12.postimg.org/7c58vxfe5/Captura_de_pantalla_2015_10_03_a_las_17_25_01.png
http://s13.postimg.org/meysu5j0n/Captura_de_pantalla_2015_10_03_a_las_17_24_48.png
Thanks in advance !
Edit:
Some code
import UIKit
class HomeViewController: UIViewController , UITableViewDataSource , UITableViewDelegate , UITabBarControllerDelegate {
let CellIdentifier = "CellTarea";
#IBOutlet var tareasTable: UITableView!
let tareas = ["Revisar etiquetado leche Nido","Reponer yoghurt sin lactosa","Reponer Chocolates Sahne Nuss","Revisar etiquetado de Chamito","Reponer Nescafe Clasico 200 gr."]
override func viewDidLoad() {
super.viewDidLoad()
self.tareasTable.delegate=self
self.tareasTable.dataSource=self
//Tabbar Config
self.tabBarController?.delegate = self;
for item in (self.tabBarController?.tabBar.items as NSArray!){
(item as! UITabBarItem).image = (item as! UITabBarItem).image?.imageWithRenderingMode(.AlwaysOriginal)
(item as! UITabBarItem).selectedImage = (item as! UITabBarItem).selectedImage?.imageWithRenderingMode(.AlwaysOriginal)
}
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: - TableView
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:CustomTareasCell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier, forIndexPath: indexPath) as! CustomTareasCell
cell.tareaLabel.text = tareas[indexPath.row];
cell.indiceLabel.text = String(indexPath.row+1);
return cell
}
Other view controller with tableview
import UIKit
class ReportesViewController: UIViewController, UITableViewDelegate , UITableViewDataSource, UITabBarControllerDelegate {
let personas = ["Alexis Parra","Ernesto Jímenez","Paulina Torres","Juan Soto","Julio Gallardo"]
let fechas = ["24 de Septimbre","22 de Septimbre", "21 de Septimbre", "20 de Septimbre","18 de Septimbre"]
let textCellIdentifier = "CellReporte";
#IBOutlet var reportesTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.reportesTable.delegate=self;
self.reportesTable.dataSource=self;
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewDidAppear(animated: Bool) {
let topOffest = CGPointMake(0, -(self.reportesTable.contentInset.top))
self.reportesTable.contentOffset = topOffest
}
//MARK: - TableView
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let reportesCell:CustomReportesCell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as! CustomReportesCell
print(fechas[indexPath.row])
reportesCell.fecha.text = fechas[indexPath.row];
reportesCell.autor.text = personas[indexPath.row];
return reportesCell
}

delegate modal view swift

I have tried the other methods for delegation and protocols for passing data between modal views and the parent view button they aren't working for me. This is obviously because I am implementing them wrong.
What I have is a parent view controller which has a tableviewcell which in the right detail will tell you your selection from the modal view. The modal view is another table view which allows you to select a cell, which updates the right detail and dismisses the modal view. All is working except the actual data transfer.
Thanks in advance!! :)
Here is my code for the parent view controller:
class TableViewController: UITableViewController, UITextFieldDelegate {
//Properties
var delegate: transferData?
//Outlets
#IBOutlet var productLabel: UILabel!
#IBOutlet var rightDetail: UILabel!
override func viewWillAppear(animated: Bool) {
println(delegate?.productCarrier)
println(delegate?.priceCarrier)
if delegate?.productCarrier != "" {
rightDetail.text = delegate?.productCarrier
productLabel.text = delegate?.productCarrier
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 5
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return 1
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
The code for the model view controller and protocol is:
protocol transferData {
var priceCarrier: Double { get set }
var productCarrier: String { get set }
}
class ProductsDetailsViewController: UITableViewController, transferData {
//Properties
var priceCarrier = 00.00
var productCarrier = ""
//Outlets
//Actions
#IBAction func unwindToViewController(segue: UIStoryboardSegue) {
self.dismissViewControllerAnimated(true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
populateDefaultCategories()
// 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 didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return Int(Category.allObjects().count)
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return (Category.allObjects()[UInt(section)] as Category).name
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return Int(objectsForSection(section).count)
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:ProductListCell = tableView.dequeueReusableCellWithIdentifier("productCell", forIndexPath: indexPath) as ProductListCell
let queriedProductResult = objectForProductFromSection(indexPath.section, indexPath.row)
cell.name.text = queriedProductResult.name
cell.prices.text = "$\(queriedProductResult.price)"
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = self.tableView.indexPathForSelectedRow()!
let product = objectForProductFromSection(indexPath.section, indexPath.row)
let PVC: TableViewController = TableViewController()
println("didSelect")
productCarrier = product.name
priceCarrier = product.price
println(productCarrier)
println(priceCarrier)
self.dismissViewControllerAnimated(true, completion: nil)
}
I think for passing data, you should use segue like:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let indexPath = self.tableView.indexPathForSelectedRow()!
let product = objectForProductFromSection(indexPath.section, indexPath.row)
println("didSelect")
productCarrier = product.name
priceCarrier = product.price
println(productCarrier)
println(priceCarrier)
self.performSegueWithIdentifier("displayYourTableViewControllerSegue", sender: self)
}
and then override the prepareForSegue function:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var controller = segue.destinationViewController as TableViewController
controller.rightDetail.text = "\(self.priceCarrier)"
controller.productLabel.text = self.productCarrier
}

Resources