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).
Related
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?
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.
Everything works, except when I click on a row.. nothing happens it should output You selected cell number:
class JokesController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var jokes_list: UITableView!
var CountCells = 0
var CellsData = [[String: Any]]()
override func viewDidLoad() {
super.viewDidLoad();
Alamofire.request("http://localhost:8080/jokes.php").responseJSON{ response in
if let JSON = response.result.value as? [[String: Any]] {
self.CellsData = JSON
self.CountCells = JSON.count
self.jokes_list.reloadData()
}else{
debugPrint("failed")
}
}
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return CellsData.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as UITableViewCell
cell.textLabel?.text = CellsData[indexPath.row]["title"] as! String?
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
debugPrint("You selected cell number: \(indexPath.row)!")
}
}
First, you need to inherit from UITableViewDelegate (class ... : UIViewController, UITableViewDelegate.. ).
Then, you need to assign
self.jokes_list.delegate = self
self.jokes_list.dataSource = self
tentatively in your viewDidLoad.
Edit: As #zsteed mentioned.
I'm trying to make a custom cell to be the Section of my cells:
For this I'm overriding some functions like:
numberOfRowsInSection
viewForHeaderInSection
heightForHeaderInSection
And I'm working with multiple cellForRowAtIndexPath I'm using a if indexPath.row to identify the Cell and populate them in a dynamic way.
import UIKit
class TesteTableViewController: PFQueryTableViewController {
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.LightContent
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
loadCollectionViewData()
}
func loadCollectionViewData() {
// Build a parse query object
let query = PFQuery(className:"Feed")
// Check to see if there is a search term
// Fetch data from the parse platform
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
// The find succeeded now rocess the found objects into the countries array
if error == nil {
print(objects!.count)
// reload our data into the collection view
} else {
// Log details of the failure
}
}
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return objects!.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var header = tableView.dequeueReusableCellWithIdentifier("Cell2")! as! TesteTableViewCell
return header
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30.0
}
// Initialise the PFQueryTable tableview
override init(style: UITableViewStyle, className: String!) {
super.init(style: style, className: className)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
// Configure the PFQueryTableView
self.parseClassName = "Feed"
self.pullToRefreshEnabled = true
self.paginationEnabled = false
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: TesteTableViewCell!
let object = objects![indexPath.section]
if indexPath.row == 0 {
cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! TesteTableViewCell
// Extract values from the PFObject to display in the table cell
if let nameEnglish = object["name"] as? String {
cell?.label1?.text = nameEnglish
}
}
else{
cell = tableView.dequeueReusableCellWithIdentifier("Cell2", forIndexPath: indexPath) as! TesteTableViewCell
// Extract values 2from the PFObject to display in the table cell
if let nameEnglish2 = object["brief"] as? String {
cell?.label2?.text = nameEnglish2
}
}
return cell
}
}
With my code I have this result:
I'm successfully populating both Cells with different Identifiers.
But look like this function is called before the cellForRowAtIndexPath and it return the content that I have in the storyBoard and not the content that I'm populating dynamically.
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var header = tableView.dequeueReusableCellWithIdentifier("Cell2")! as! TesteTableViewCell
return header
}
And I really think that is my problem. (The order that things happen).
Any ideas?
Thanks.
You need to move the code which you have in cellForRowAtIndexPath for row != 0 because that block of code is never executed which is causing static data rendering from storyboard instead of dynamic data.
In this case you have to give dynamic data to cell in viewForHeaderInSection method so that you cell will populate that information on each reload.
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var header = tableView.dequeueReusableCellWithIdentifier("Cell2")! as! TesteTableViewCell
let object = objects![section]
if let nameEnglish2 = object["brief"] as? String {
header.label2?.text = nameEnglish2
}
return header
}
I have a tableviewcontoller, it retrieves the data and stores in model objects. The model object is assigned to table cells. when i make a change in table cell text box, the changes are not get updated to model. Is anything wrong in this code? if this is not right approach, please let know how to get the changes in table row.
class myTable: UITableViewController , UITableViewDelegate, UITableViewDataSource{
var models = [Customer]()
override func viewDidLoad() {
super.viewDidLoad()
self.generateUpdateModels()
self.tableView.dataSource = self
self.tableView.delegate = self
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return models.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("rowIdentifier", forIndexPath: indexPath) as! TextInputLabelTableViewCell
cell.first.text = models[indexPath.row].first //label
cell.last.text = models[indexPath.row].last //label
cell.status.text = models[indexPath.row].status //textbox
return cell
}
func generateUpdateModels(){
//update models[]
}
#IBAction func done(sender: AnyObject) {
//look into models for changes....
// don't see the changes
self.performSegueWithIdentifier("final", sender: self)
}