How to use a table view controller like you would a picker - ios

I am working on an app right now that how several long UIViewPickers. Instead of the picker I would like to have a table view of all the options.
When you click on a text field it will take you to my table view that lists all the data for that text field.
This is how my table view controller looks right now.
import UIKit
class SelectOptionsTableViewController: UITableViewController {
let options = ["New","Used"]
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 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 options.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "LabelCell", for: indexPath) as! SelectOptionTableViewCell
cell.selectOptionLabel?.text = options[indexPath.row]
return cell
}
}
To make the picker come up you would use something like this.
let pickerView = UIPickerView()
pickerView.delegate = self
carTypeTextField.inputView = pickerView
If I wanted to make it where I could use SelectOptionsTableViewController instead how would I go about that?

Related

TableViewCell isn't fully displayed

My TableViewCells looks normal in Xcode but are chopped off when displayed in a simulator. Please see the images below.
Anyone know why this is?
Any help is much appreciated!
Xcode image:
Simulator image:
class Feed: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.shared.isStatusBarHidden = false
}
override open func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
//It will hide the status bar again after dismiss
UIApplication.shared.isStatusBarHidden = false
}
override open var prefersStatusBarHidden: Bool {
return false
}
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 1
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! FeedCell
// Configure the cell...
return cell
}
Use tableView(_:heightForRowAt:). Add a height as per requirement.

Update a table in the detailview of a uisplitviewcontroller

So I have a UISplitViewController and in the DetailView I have a UITableView.
What I want to do is take the selected cell from the root view controller and append it to the string which is populating my tableview in the detail view controller. I can append with selection very easily but I need help with is the updating part.
What's supposed to happen is when you click the cell, it appends the value in the cell to the global variable main.BoatManifest, and then update the table. I just don't know how to do that.
Here's some code:
import UIKit
class DetailViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, FullListCellDelegate {
#IBOutlet weak var tableView: UITableView!
func updateName(sender: FullListCell, detVC: DetailViewController) {
tableView.reloadData()
}
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.
}
// MARK: - Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return main.BoatManifest.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
// Configure the cell...
cell.textLabel?.text = main.BoatManifest[indexPath.row]
return cell
}
}
struct Main {
var BoatManifest: [String] = []
}
var main = Main(BoatManifest: [" "])
This is the code for my detail view and the struct Main on the bottom is just a global variable. My MainView code is this:
import UIKit
protocol NameSelectionDelegate: class {
func nameSelected()
}
class MasterViewController: UITableViewController {
var Names: [String] = ["John", "Mark", "Paul", "Jeremy"]
override func viewDidLoad() {
super.viewDidLoad()
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
}
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 Names.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = Names[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
main.BoatManifest.append(Names[indexPath.row])
NotificationCenter.default.addObserver(self, selector: #selector(loadList), name: NSNotification.Name(rawValue: "load"), object: nil)
}
func loadList(){
//load data here
self.tableView.reloadData()
}
}
I attempted to use a UISplitViewController tutorial to figure it out but it didn't have the tableview in the detail view controller. I need to send a message when I select the cell to the detail tableview and have it update with the appended text.
Thanks for your help.

reloadData does not work after fetching data from get method

I have a table and I got my data from a GET method. After I get the data, I would like to use the reloadData function, but it doesn't work and my table does not show anything.
import SwiftyJSON
class NewsTableViewController: UITableViewController {
var ids = [String]()
var titles = [String]()
var descriptions = [String]()
var images = [String]()
var links = [String]()
var dates = [String]()
#IBOutlet var table_news: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
table_news.delegate = self
getNews()
// 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 numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return self.ids.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:NewsTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "news_cell") as! NewsTableViewCell
cell.lbl_date.text = self.dates[indexPath.row]
return cell
}
/*
// 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: UITableViewCellEditingStyle, 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.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
func getNews() {
RestApiManager.sharedInstance.getNews { (json: JSON) in
if let results = json.array {
for entry in results {
self.ids.append(entry["id"].string!)
self.titles.append(entry["title"].string!) self.descriptions.append(entry["description"].string!)
self.links.append(entry["link"].string!)
self.dates.append(entry["date"].string!)
}
DispatchQueue.main.async{
//print(self.ids.count) it shows 16
self.table_news.reloadData()
}
}
}
}
}
Aren't you returning 0 from numberOfRowsInSection: ? Then, how can the table show anything? :)

UITableView delegate and datasource in external class does not work

I have a simple project, with UITableView added as subview of the current view, and external tableviewcontroller class that make a delegate and datasource.
The problem is that all work correctly excepted delegate didSelectedRowAtIndexPath, when I click in a single row, all tableview become white, here is the code:
MAIN CLASS:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let cont:Tbcontroller = Tbcontroller()
let tableViewInner = UITableView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width-(self.view.frame.width/6), height: 180))
tableViewInner.scrollEnabled = false
tableViewInner.separatorStyle = .None
tableViewInner.allowsSelection = true
tableViewInner.userInteractionEnabled = true
cont.type = 1
cont.setCurrentTableView(tableViewInner)
self.view.insertSubview(tableViewInner, atIndex: self.view.subviews.count+1)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
EXTERNAL CLASS DELEGATE DATASOURCE:
import UIKit
class Tbcontroller: UITableViewController {
var type:Int = 1
override func viewDidLoad() {
super.viewDidLoad()
}
func getCell() -> UITableViewCell{
let presentCell: UITableViewCell = UITableViewCell()
return presentCell
}
func setCurrentTableView(table:UITableView){
self.tableView = table
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.reloadData()
}
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 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 4
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = getCell()
cell.textLabel?.text = "ciao"
cell.textLabel?.font = UIFont.systemFontOfSize(13)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("clicked")
}
}
When I click, I do not see the output "clicked"
Your main problem is that TbController() get deallocated. dataSource and delegate properties on UITableView are weak. Therefor, because you only assign TbController to a local variable and to the weak properties, it will get deallocated.
Also, the UITableViewController already creates a TableView for you. It is not good practice to "recreate" it. I would rather make use of the TableView in the UITableViewController and add the UITableViewController's view as a subview to your UIViewController's view.
To fix, you need an instance variable for TbController.
Sample code with ivar for TbController and making use of Tbcontroller's UITableView.
import UIKit
class ViewController: UIViewController {
var cont: Tbcontroller = Tbcontroller()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
cont.type = 1
self.view.addSubview(cont.view)
}
}
import UIKit
class Tbcontroller: UITableViewController {
var type:Int = 1
override func viewDidLoad() {
super.viewDidLoad()
tableView.scrollEnabled = false
tableView.separatorStyle = .None
tableView.allowsSelection = true
tableView.userInteractionEnabled = true
self.tableView.delegate = self
self.tableView.dataSource = self
}
func getCell() -> UITableViewCell{
let presentCell: UITableViewCell = UITableViewCell()
return presentCell
}
// 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 4
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = getCell()
cell.textLabel?.text = "ciao"
cell.textLabel?.font = UIFont.systemFontOfSize(13)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("clicked")
}
}
thanks to Carien, it works fine, i changed uitableviewcontroller with:
: NSObject, UITableViewDataSource, UITableViewDelegate

Populate table with Parse database

I'm working on an iOS app, which pulls data from a Parse database to populate a table view. I can get data from the database to print to the log, but when I try to use the data to populate the table cells, it just does not work. The table is empty every time and I can't figure out why. Any thoughts?
import UIKit
import Parse
var promoNum = -1
class TableViewController: UITableViewController, CLLocationManagerDelegate {
var titles = [String]()
override func viewDidLoad() {
super.viewDidLoad()
var getPromosQuery = PFQuery(className: "Promotions")
getPromosQuery.whereKey("zip", equalTo: "85281")
getPromosQuery.findObjectsInBackgroundWithBlock { (objects, error) in
if let objects = objects {
for object in objects {
self.titles.append(object["title"] as! String)
}
}
}
}
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 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 titles.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let promoCell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! Cell
promoCell.promotionTitle.text = titles[indexPath.row]
return promoCell
}
override func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
promoNum = indexPath.row
return indexPath
}
}
Fixed it! I just needed to add self.tableView.reloadData() after self.titles.append(object["title"] as! String).

Resources