Xcode UIButton to UITableView not connecting - ios

I am designing a project where I want it to go to a table view when a button is clicked.
Here is a pic of the storyboard:Storyboard
Here is the code for the view with the button:
import UIKit
import os.log
class MealViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
//MARK: Properties
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var priceLabel: UILabel!
#IBOutlet weak var photoImageView: UIImageView!
#IBOutlet weak var ratingControl: RatingControl!
#IBOutlet weak var caloriesLabel: UILabel!
#IBOutlet weak var descriptionLabel: UILabel!
#IBAction func addToCart(_ sender: UIButton) {
}
and here is the table view code:
import UIKit
class CartTableViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// 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 {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 0
}
When I run it how it is, it opens a blank table. When I change the numberOfRowsInSection, it gives a sigabrt error. How can I get it to just open the view regularly?

The function numberOfRowsInSection define the count of rows in the given section. If you define 0 the table must be empty. If you define something else the table view asks for a concrete cell for each row by calling:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
Depending on your code thats the first place to look for the crash reason. Your code snipped doesn't show it.

Related

UITableView with CustomCell not show data Swift4 on Xcode9

I read the other topics, but not solves my problem, I create a tableview and your cells with same value to make tests, but when I execute my project nothing data is showed. I put 5 size of rows to only to test. I don't know why my code not works.
My storyboard:
TableViewCellVenda.swift
class TableViewCellVenda: UITableViewCell {
#IBOutlet weak var cellView: UIView!
#IBOutlet weak var imageCloud: UIImageView!
#IBOutlet weak var labelValorTotal: UILabel!
#IBOutlet weak var labelQtdItens: UILabel!
#IBOutlet weak var labelCliente: UILabel!
#IBOutlet weak var labelDataVenda: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
ViewControllerVendas.swift
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
// UI View
#IBOutlet weak var tableViewVendas: UITableView!
#IBOutlet weak var waitView: UIActivityIndicatorView!
// DB
var db: OpaquePointer?
var count : Int = 0
// Data
var saleOrders : [SaleOrder] = []
override func viewDidLoad() {
super.viewDidLoad()
self.waitView.startAnimating()
self.waitView.hidesWhenStopped = true
tableViewVendas.delegate = self
tableViewVendas.dataSource = self
}
// TableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellVenda") as! TableViewCellVenda
print("Cell for row")
cell.labelCliente.text = "Nome do Cliente"
cell.labelDataVenda.text = "14/02/1991"
cell.labelQtdItens.text = "20"
cell.labelValorTotal.text = "R$ 542,22"
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 75
}
}
Emulator:
Try adding a new swift UIKit file with a class of type UITableView and do all the tableview setup in there. And of coarse set the tables’s class as this UITableView class.

"fatal error" when calling tableView.reloadData(), the tableView is properly connected

I am trying to dynamically update a tableView while the program is running. I believe I have updated the array that the data loads from correctly, but when I press the button that calls self.eventTable.reloadData() I receive the error:
fatal error: unexpectedly found nil while unwrapping an Optional value
Here is the relevant code:
View Controller:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
//Timer view
#IBOutlet weak var playButton: UIBarButtonItem!;
#IBOutlet weak var pauseButton: UIBarButtonItem!;
#IBOutlet weak var refreshButton: UIBarButtonItem!;
#IBOutlet weak var timerLabel: UILabel!
var counter = 0
var timer = Timer()
var isTimerRunning = false
//testing view container
var viewShowing = 1;
override func viewDidLoad() {
// Do any additional setup after loading the view, typically from a nib.
pauseButton.isEnabled = false
hideAll();
self.basicContainer.isUserInteractionEnabled = true;
self.basicContainer.isHidden = false;
self.timerLabel.text = String("00:00:00");
eventTable.dataSource = self
eventTable.delegate = self
super.viewDidLoad()
loadEvents(event: "timer start")
}
...
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Add table to keep track of events
#IBOutlet weak var eventTable: UITableView!
var eventData = [Session]()
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventData.count;
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! eventTableViewCell
let event = eventData[indexPath.row]
cell.eventLabel.text = event.session
return cell
}
private func loadEvents(event: String) {
guard let event1 = Session(session: event) else {
fatalError("Unable to instantiate event")
}
eventData += [event1]
DispatchQueue.main.async() {
self.eventTable.reloadData()
}
}
func testPrint() {
loadEvents(event: "testing cell adding")
//self.eventTable.reloadData()
viewWillAppear(false)
print("This is a test print");
}
}
The function works fine when it is called in ViewDidLoad(), but not when it is called by the button in another class ("This is a test print" prints to console so I know the button call is going through).
Expected behavior is the tableView (eventTable) reloading showing two cells, "timer start" and "testing cell adding" (ideally with "testing cell adding" being at the top).
Also want to emphasize that eventTable is connected to the storyboard, which seems to be a common problem on here.
Here is the Session.swift file and the eventTableViewCell.swift file if those are helpful:
Session.swift
import Foundation
import UIKit
class Session {
//MARK: Properties
var session: String
//MARK: Initialization
init?(session: String) {
guard !session.isEmpty else {
return nil
}
self.session = session
}
}
eventTableViewCell.swift
import Foundation
import UIKit
class eventTableViewCell: UITableViewCell {
//MARK: Properties
#IBOutlet weak var eventLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Thanks!
Edit: The ViewController from where I call testPrint().
import UIKit
class BasicViewController: UIViewController {
var VC = ViewController();
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.
}
//Basic buttons
#IBOutlet weak var warmButton: UIButton!
#IBOutlet weak var dryButton: UIButton!
#IBOutlet weak var stimulateButton: UIButton!
#IBOutlet weak var controlButton: UIButton!
#IBOutlet weak var bedButton: UIButton!
#IBOutlet weak var tempButton: UIButton!
#IBOutlet weak var pulseButton: UIButton!
#IBOutlet weak var ecgButton: UIButton!
#IBOutlet weak var apgarButton: UIButton!
#IBOutlet weak var helpButton: UIButton!
//APGAR options
#IBOutlet weak var skinColor: UIButton!
#IBOutlet weak var pulse: UIButton!
#IBOutlet weak var grimace: UIButton!
#IBOutlet weak var flexion: UIButton!
#IBOutlet weak var respiratoryEffort: UIButton!
#IBAction func warmButton(sender: AnyObject) {
VC.testPrint();
}
}
It would seem that you are all right in stating that I am instantiating a new ViewController which is causing the issue. How should I go about fixing this? Fairly new to Swift
I think, your problem is in this lines of codes:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellReuseIdentifier") as! eventTableViewCell
let event = eventData[indexPath.row]
cell.eventLabel.text = event.session
return cell
}
Can you check the cell identifier is same as your cell identifier
And number of rows in eventData array

UITableView Crashes on Segue to View Controller

Cause of Crash
Click the image above for a brief view of my Segue. My app is a workout tracker. I have a class that makes the workout object with properties such as workout name, description, etc. I have another object that creates the workoutlist, so just an array of Workout objects.
I have a UITableView and a button above it that lets the user create a new workout and adds it to the workoutList array.
The crash happens whenever I click this "create new workout" which segues to a new view controller. I get this error
Crash Error
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var setStepper: UILabel!
#IBOutlet weak var repStepper: UILabel!
#IBOutlet weak var workoutName: UITextField!
#IBOutlet weak var workoutDescription: UITextField!
#IBOutlet weak var tableView: UITableView!
var workoutList = WorkoutList().listOfWorkouts
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func stepperCounter(_ sender: UIStepper) {
if sender.tag == 1 {
setStepper.text = "\(Int(sender.value))"
}
else if sender.tag == 2 {
repStepper.text = "\(Int(sender.value))"
}
}
#IBAction func addToWorkout(_ sender: Any) {
//I know this is terrible fixing later. Just for Testing right now
let newWorkout : Workout = Workout(Name: workoutName.text!, Description: workoutDescription.text!, Sets: Int(setStepper.text!)!, Reps: Int(repStepper.text!)!)
workoutList.append(newWorkout)
print(workoutList.count)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return workoutList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Hello"
return cell
}
}
it looks like you are using the same ViewController for both Views in your storyboard.
Which means, when you push to the "AddNewWorkoutController" the viewDidLoad expects a tableView - which is not there, because the storyboard didn't build any for this view.
You should create 2 VCS. One for the OverView with the "add new button" and the tableview and another one for actually creating it.
here is a full solution:
create 2 new swift files:
OverViewViewController.swift & NewWorkoutViewController.swift
I just separated your code into 2 VC's:
import UIKit
class OverViewViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var workoutList = WorkoutList().listOfWorkouts
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return workoutList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = "Hello"
return cell
}
}
and
import UIKit
class NewWorkoutViewController: UIViewController {
#IBOutlet weak var setStepper: UILabel!
#IBOutlet weak var repStepper: UILabel!
#IBOutlet weak var workoutName: UITextField!
#IBOutlet weak var workoutDescription: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func stepperCounter(_ sender: UIStepper) {
if sender.tag == 1 {
setStepper.text = "\(Int(sender.value))"
}
else if sender.tag == 2 {
repStepper.text = "\(Int(sender.value))"
}
}
#IBAction func addToWorkout(_ sender: Any) {
//I know this is terrible fixing later. Just for Testing right now
let newWorkout : Workout = Workout(Name: workoutName.text!, Description: workoutDescription.text!, Sets: Int(setStepper.text!)!, Reps: Int(repStepper.text!)!)
workoutList.append(newWorkout)
print(workoutList.count)
}
}
Now go into the Storyboard, select the controllers and assign the right classes:
After assigning go and connect your tableView to the tableView in the OverView and the 2 actions in your NewWorkout.
This will work.
I'd guess that tableView outlet isn't wired up in your storyboard - and that property is an implicitly unwrapped optional. You're promising that it won't be nil.

UITableView doesn't fill custom cells inside of UITabBarController

I have UITabBarController and on one of the tabs I have UIViewController with UITableView inside.
I had created custom cell class.
If I fill tableView custom cells without UITabBarController (I put entry point to UIViewController) everything works fine, but if I use UITabBarController firstly, my cells are not populated with any data when I reach UITableView tab.
Where could be a bug here?
import UIKit
class blaViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableView: UITableView!
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.
}
func tableView(tableView:UITableView, numberOfRowsInSection section:Int) -> Int {
return 3
}
func tableView(tableView:UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! blaTableViewCell
cell.myLabel.text = "123"
return cell
}
}
import UIKit
class blaTableViewCell: UITableViewCell {
#IBOutlet weak var myLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Try tick install checkbox for all the constraints, not only wh wr. It worked for me. It is also described here: https://stackoverflow.com/a/32052154/2064500
#IBOutlet weak var myLabel: UILabel!
Try to do strong variable
#IBOutlet var myLabel: UILabel!

Custom Cell Labels in UITableView Does Not Populate

On my storyboard is a Tab Bar Controller with two view controllers. The first view controller has a UITableView, and the second view controller is used to collect data which will be displayed in table view format on the first view controller.
For this, I have created four swift files:
TARISKTREATMENT.swift - contains the class TARISKTREATMENT that's linked to the first view controller (the one with the UITableView)
TAADDRISKTREATMENT.swift - contains the class TAADDRISKTREATMENT that's linked to the second view controller.
TREATMENTS.swift - Struct that's used to collect data entered on second view controller.
CUSTOMTREATMENTCELL.swift - UITableViewCell class for the custom cell.
The second view controller collects the data from the user perfectly, and when I run print commands, I can see that the data is actually in the struct.
For some reason, the code from TARISKTREATMENT.swift does not populate the custom cell.
What am I doing wrong here?
CODE: TARISKTREATMENT.swift (View controller 1 with UITableView - the one that's not working...)
import UIKit
class TARISKTREATMENT: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var TreatmentsTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
TreatmentsTableView.dataSource = self
TreatmentsTableView.delegate = self
TreatmentsTableView.reloadData()
}//END - viewDidLoad
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TreatmentsManager.newTreatments.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let IndividualCell = TreatmentsTableView.dequeueReusableCellWithIdentifier("TreatmentCell", forIndexPath: indexPath) as! CUSTOMTREATMENTCELL
IndividualCell.outletLabel_TreatmentPackageName.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPackageName
IndividualCell.outletLabel_TreatmentDescription.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPackageDetail
IndividualCell.outletLabel_TreatmentResponsiblePerson.text = TreatmentsManager.newTreatments[indexPath.row].varTreatmentResponsiblePerson
IndividualCell.outletLabel_TreatmentDTGCompleted.text = String(TreatmentsManager.newTreatments[indexPath.row].varTreatmentDTGCompleted)
let varSelectPriorityPic = TreatmentsManager.newTreatments[indexPath.row].varTreatmentPriority
switch varSelectPriorityPic {
case "HIGH":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityHigh
case "MEDIUM":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityMedium
case "LOW":
IndividualCell.outletImage_TreatmentPriority.image = imageTreatmentPriorityLow
default:
break
}
return IndividualCell
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath){
if (editingStyle == UITableViewCellEditingStyle.Delete){
TreatmentsManager.newTreatments.removeAtIndex(indexPath.row)
TreatmentsTableView.reloadData()
}
}
}
CODE: TREATMENTS.swift
import UIKit
var TreatmentsManager: classTreatmentsManager = classTreatmentsManager()
struct structTreatment {
var varTreatmentPackageName : String
var varTreatmentPackageDetail : String
var varTreatmentResponsiblePerson : String
var varTreatmentPriority : String
var varTreatmentDTGCompleted : NSDate
}
class classTreatmentsManager: NSObject {
var newTreatments = [structTreatment]()
func funcAddTreatment(varTreatmentPackageName: String, varTreatmentPackageDetail: String, varTreatmentResponsiblePerson: String, varTreatmentPriority: String, varTreatmentDTGCompleted: NSDate){
newTreatments.append(structTreatment(varTreatmentPackageName: varTreatmentPackageName, varTreatmentPackageDetail: varTreatmentPackageDetail, varTreatmentResponsiblePerson: varTreatmentResponsiblePerson, varTreatmentPriority: varTreatmentPriority, varTreatmentDTGCompleted: varTreatmentDTGCompleted))
}
}
CODE: CUSTOMTREATMENTCELL.swift
import UIKit
class CUSTOMTREATMENTCELL: UITableViewCell {
#IBOutlet weak var outletImage_TreatmentPriority: UIImageView!
#IBOutlet weak var outletLabel_TreatmentPackageName: UILabel!
#IBOutlet weak var outletLabel_TreatmentDescription: UILabel!
#IBOutlet weak var outletLabel_TreatmentResponsiblePerson: UILabel!
#IBOutlet weak var outletLabel_TreatmentDTGCompleted: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I've uploaded a small video to show what's (not) happening here.
Your assistance is appreciated - thanks!
Everything is fine in your code. What you miss is reloading the data :
override func viewWillAppear() {
super.viewWillAppear()
TreatmentsTableView.reloadData()
}

Resources