Swift delegate not working - ios

I have a stepper in my ViewController that controls the value of a variable in my UIView. When I reset the variables to 0 in my UIView, I also want the stepper and label to reset, but they won't. I tried using a delegate, but am getting an error. Thanks in advance!
ViewController:
protocol CircleViewDelegate: class {
func updateStepper(view: CircleView)
}
class ViewController: UIViewController, CircleViewDelegate {
var colors = CircleView()
#IBOutlet weak var circleView1: CircleView!
#IBOutlet weak var blueStepper: UIStepper!
#IBOutlet weak var greenStepper: UIStepper!
#IBOutlet weak var redStepper: UIStepper!
#IBOutlet weak var redValue: UILabel!
#IBOutlet weak var greenValue: UILabel!
#IBOutlet weak var blueValue: UILabel!
var circleViewDelegate: CircleView!
override func viewDidLoad() {
super.viewDidLoad()
circleViewDelegate!.delegate = self
}
func updateStepper(view: CircleView) {
redStepper.value=0.0;
greenStepper.value=0.0;
blueStepper.value=0.0;
}
#IBAction func stepperChange(sender: UIStepper) {
circleView1.redd1 = Int(redStepper.value);
redValue.text = Int(sender.value).description;
}
#IBAction func stepperChange1(sender: UIStepper) {
circleView1.greenn1 = Int(greenStepper.value);
greenValue.text = Int(sender.value).description;
}
#IBAction func stepperChange2(sender: UIStepper) {
circleView1.bluee1 = Int(blueStepper.value);
blueValue.text = Int(sender.value).description;
}
}
UIView:
class CircleView: UIView {
var redd1 = 0
var greenn1 = 0
var bluee1 = 0
weak var delegate: CircleViewDelegate?
func updateStepper() {
delegate?.updateStepper(self)
}
func game() {
if(redd1==Int(red1) && greenn1==Int(green1) && bluee1==Int(blue1)) {
redd1 = 0;
green1 = 0;
blue1 = 0;
updateStepper()
}
}
}

Try this:
override func viewDidLoad() {
super.viewDidLoad()
circleView1.delegate = self
}
func updateStepper(view: CircleView) {
redStepper.value = 0.0
greenStepper.value = 0.0
blueStepper.value = 0.0
stepperChange(redStepper)
stepperChange(greenStepper)
stepperChange(blueStepper)
}

Instead of assigning the delegate like this circleViewDelegate!.delegate = self in viewDidLoad try circleView1.delegate = self

Related

"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

Transferring data from a UITableViewCell cocoa touch class to a UIViewController class

Okay, so what I am essentially trying to do is transfer data from a UITableViewCell class to a UIViewController class. Below is my UITableViewCell:
class OrderCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
}
var post: OrderModel!
var link: Link!
var addedList: [String:Float] = [:]
#IBOutlet weak var dishName: UILabel!
#IBOutlet weak var dishDescriptionAndPrice: UILabel!
#IBOutlet weak var numberOfOrders: UILabel!
#IBOutlet weak var addOrderBtn: UIButton!
#IBOutlet weak var subtractOderBtn: UIButton!
#IBAction func addButtonPressed(sender: AnyObject) {
if numberOfOrders.text == "9" {
numberOfOrders.text = "9"
} else {
numberOfOrders.text = String((Int(numberOfOrders.text!)! + 1))
}
addedList.updateValue(post.dishPrice, forKey: post.dishName)
print(addedList)
}
#IBAction func subtractButtonPressed(sender: AnyObject) {
if numberOfOrders.text == "0" {
numberOfOrders.text = "0"
} else {
numberOfOrders.text = String((Int(numberOfOrders.text!)! - 1))
}
}
func getOrders() -> Dictionary<String, Float> {
return addedList
}
func configureCell(post: OrderModel) {
self.post = post
self.dishName.text = post.dishName
self.dishDescriptionAndPrice.text = post.dishDescription
self.numberOfOrders.text = "0"
}
}
What I am trying to do, is have my other class (which is of UIViewController), retrieve 'addedList' from the above class. I obviously cannot use prepareForSegue, and I have had no luck find a way to do this that is compatible with these two classes. I am open to creating a new class to be the "bridge" between the two and transfer the data through, but I again cannot find a way to do this. Any and all help is greatly appreciated, thank you in advance.
To get more specific, the UIViewController holds my tableview, and the class that is above is just the object file for each individual cell. I need to transfer the data when the addButtonPressed IBaction is called.
You can do this by creating a delegate in your cell class. And in your view controller class, under cell for row at indexPath, add:
cell.delegate = self
And update your cell class like this:
protocol ClassNameDelegate:class {
func addButtonAction(addedList:[String:Float])
}
#IBOutlet weak var dishName: UILabel!
#IBOutlet weak var dishDescriptionAndPrice: UILabel!
#IBOutlet weak var numberOfOrders: UILabel!
#IBOutlet weak var addOrderBtn: UIButton!
#IBOutlet weak var subtractOderBtn: UIButton!
//Create a delegate
weak var delegate: ClassNameDelegate?
#IBAction func addButtonPressed(sender: AnyObject) {
if numberOfOrders.text == "9" {
numberOfOrders.text = "9"
} else {
numberOfOrders.text = String((Int(numberOfOrders.text!)! + 1))
}
addedList.updateValue(post.dishPrice, forKey: post.dishName)
print(addedList)
// Call this when added list is done and get the call to your view controller.
if delegate != nil {
delegate?.addButtonAction(addedList: addedList)
}
}
#IBAction func subtractButtonPressed(sender: AnyObject) {
if numberOfOrders.text == "0" {
numberOfOrders.text = "0"
} else {
numberOfOrders.text = String((Int(numberOfOrders.text!)! - 1))
}
}
func getOrders() -> Dictionary<String, Float> {
return addedList
}
func configureCell(post: OrderModel) {
self.post = post
self.dishName.text = post.dishName
self.dishDescriptionAndPrice.text = post.dishDescription
self.numberOfOrders.text = "0"
}
}
Finally import this delegate method in your view controller class, in the same way you import tableView delegate and datasource.
A cell is not the good place to store information like this. You should store the information in your view controller. And when your cell button is pressed, retrieve the information thanks to the index path of the cell.
In your cell:
func configureCell(post: OrderModel, delegate:UIViewController) {
self.dishName.text = post.dishName
self.dishDescriptionAndPrice.text = post.dishDescription
self.numberOfOrders.text = "0"
self.addButton.addTarget(delegate, action: #selector(delegate.addButtonPressed(_:)), for: UIControlEvents.touchUpInside)
}
In your view controller:
//store your data in your view controller
var data=[OrderModel]()
func addButtonPressed(_ button:UIButton){
let selectedCell=button.superview?.superview? as! OrderCell
let indexPath=tableView.indexPath(for: selectedCell)
let cellData=data[indexPath!.row]
if cellData.numberOfOrders==9{
selectedCell.numberOfOrders.text="9"
}else{
selectedCell.numberOfOrders.text=String(cellData.numberOfOrders+1)
}
}

How come the values are nil?

I am passing data from one class to another, and I am receiving nil values when I breakpoint and look at the console.
This is the class with the values, and I want to pass these values to the class viewc
func viewControllerAtIndex(index: Int) -> viewc {
if ((self.namepage.count == 0) || (index >= self.namepage.count) {
return viewcard()
}
var vc: viewc = self.storyboard?.instantiateViewControllerWithIdentifier("ItemController") as! viewc
vc.imageFile = self.pageImages[index] //not nil
vc.cTitle = self.namepage[index] //not nil
vc.nTitle = self.numberpage[index] //not nil
vc.pageIndex = index
vc.getArray()
return vc
}
This class is the class I want to pass the data to.
class viewc: UIViewController{
var pageIndex: Int!
var cTitle: String!
var imageFile: String!
var nTitle: String!
#IBOutlet weak var imagen: UIImageView!
#IBOutlet weak var name: UILabel!
#IBOutlet weak var number: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
func getArray() {
self.imagen.image = UIImage(named: self.imageFile)//imageFile is nil
self.name.text = self.cTitle//cTitle is nil
self.number.text = self.nTitle//nTitle is nil
}
}
func viewControllerAtIndex(index: Int) -> ViewC {
var vc = self.storyboard?.instantiateViewControllerWithIdentifier("ItemController") as! ViewC
vc.imageFile = self.pageImages[index]
vc.cTitle = self.namepage[index]
vc.nTitle = self.numberpage[index]
vc.pageIndex = index
vc.testProperties()
return vc
}
class ViewC: UIViewController{
var pageIndex: Int!
var cTitle: String!
var imageFile: String!
var nTitle: String!
#IBOutlet weak var imagen: UIImageView!
#IBOutlet weak var name: UILabel!
#IBOutlet weak var number: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
imagen.image = UIImage(named: imageFile)
name.text = cTitle
number.text = nTitle
}
// This will crash if one of them is nil
func testProperties() {
print("pageIndex: \(pageIndex)")
print("cTitle: \(cTitle)")
print("imageFile: \(imageFile)")
print("nTitle: \(nTitle)")
}
}
Now your ViewC will be set up properly. Notice you can only access your IBOutlet after the view has loaded. If you need to access the outlets before the view has loaded, you'll need to do something else.
The function should look like this.
func viewControllerAtIndex(index: Int) -> UIViewController?
{
let vc = storyboard?.instantiateViewControllerWithIdentifier (pagesArray[index]) return vc
}

Swift Stepper Action that changes UITextField and UILabel within same cell

I am using a function to build my custom cell. the function used to create the cell is "makeMyList". The stepper I have successfully increments and decrements the itemQuantity textField. The trouble I am having comes with updating the "itemPrice" label. I want itemPrice.text to be quantity * price and update dynamically as the quantity either goes up or down dynamically.
Could someone possibly help me with how to get this to happen?
Thank you in advance!
class MyListTableViewCell: UITableViewCell
{
#IBOutlet weak var itemPrice: UILabel!
#IBOutlet weak var itemName: UILabel!
#IBOutlet weak var itemQuantity: UITextField!
#IBOutlet weak var stepper: UIStepper!
#IBAction func itemQuantityStepper(sender: UIStepper)
{
self.itemQuantity.text = Int(sender.value).description
}
override func awakeFromNib() {
super.awakeFromNib()
}
func makeMyList(myItem: MyList)
{
self.itemName.text = myItem.MyItemName
self.itemPrice.text = String(stepper.value * Double(myItem.MyItemPrice))
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
For anyone who has the same issue. Here is the answer to my own question.
Hope it helps!
class MyListTableViewCell: UITableViewCell
{
#IBOutlet weak var itemPrice: UILabel!
#IBOutlet weak var itemName: UILabel!
#IBOutlet weak var itemQuantity: UITextField!
#IBOutlet weak var stepper: UIStepper!
var price: Float = 0.0
var quantity: Int = 1
override func awakeFromNib() {
super.awakeFromNib()
}
func makeMyList(myItem: MyList)
{
self.itemName.text = myItem.MyItemName
self.itemPrice.text = myItem.MyItemPrice
price = Float(myItem.MyItemPrice)
}
#IBAction func itemQuantityStepper(sender: UIStepper)
{
quantity = Int(sender.value)
self.itemQuantity.text = String(quantity)
self.itemPrice.text = price * Float(quantity)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}

UiTextField in ViewController2 Change value of Struct Var

I have two view Controllers connected with a tabBar. In the first tab, I see all buttons to add Repairs and Delete Repairs. In The First Step of my private project, I have Static values for the Repair times. Now in my second step, I wanted to change the time that a person needs to repair by the second tap, but when I go back after editing the time in the second VieController, the value of the struct didn't change.
ViewController.swift
class ViewController: UIViewController {
#IBOutlet weak var AddBrepair: UIButton!
#IBOutlet weak var AddOrepair: UIButton!
#IBOutlet weak var AddDrepair: UIButton!
#IBOutlet weak var GeniusNumber: UISegmentedControl!
#IBOutlet weak var AddBCrepair: UIButton!
#IBOutlet weak var CheckOutOrepair: UIButton!
#IBOutlet weak var CheckOutBrepair: UIButton!
#IBOutlet weak var CheckOutBCrepair: UIButton!
#IBOutlet weak var CheckOutDrepair: UIButton!
#IBOutlet weak var DisplayLeftNumber: UILabel!
#IBOutlet weak var RFPTime: UILabel!
#IBOutlet weak var CurrentTimerepair: UILabel!
let repairTime=RepairTime()
override func viewDidLoad() {
super.viewDidLoad()
//RFPTime.text = repairTime.ReadyForPickup()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
//print(repairTime.getNumberOfRepairGenius())
}
#IBAction func Controller(sender: AnyObject) {
repairTime.NumberOfRepairGenius(GeniusNumber.selectedSegmentIndex+1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
}
#IBAction func AddBr(sender: AnyObject) {
repairTime.NumberOfBatteryRepair(repairTime.getNumberOfBatteryRepair()+1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
}
#IBAction func AddOr(sender: AnyObject) {
repairTime.NumberOfOtherRepair(repairTime.getNumberOfOtherRepair()+1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
}
#IBAction func AddBCr(sender: AnyObject) {
repairTime.NumberOfBackCoverRepair(repairTime.getNumberOfBackCoverRepair()+1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
}
#IBAction func AddDr(sender: AnyObject) {
repairTime.NumberOfDisplayRepair(repairTime.getNumberOfDisplayRepair()+1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
//print("view controler")
//print(
}
#IBAction func DeleteBr(sender: AnyObject) {
if(repairTime.getNumberOfBatteryRepair() != 0){
repairTime.NumberOfBatteryRepair(repairTime.getNumberOfBatteryRepair()-1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
}
}
#IBAction func DeleteOr(sender: AnyObject) {
if(repairTime.getNumberOfOtherRepair() != 0){
repairTime.NumberOfOtherRepair(repairTime.getNumberOfOtherRepair()-1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
}
}
#IBAction func DeleteBCr(sender: AnyObject) {
if(repairTime.getNumberOfBackCoverRepair() != 0){
repairTime.NumberOfBackCoverRepair(repairTime.getNumberOfBackCoverRepair()-1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
}
}
#IBAction func DeleteDr(sender: AnyObject) {
if(repairTime.getNumberOfDisplayRepair() != 0){
repairTime.NumberOfDisplayRepair(repairTime.getNumberOfDisplayRepair()-1)
CurrentTimerepair.text = String(format:"%.1f", repairTime.TimeOfRepair())
RFPTime.text = String(repairTime.ReadyForPickup())
}
}
#IBAction func ShowQueuePop(sender: AnyObject) {
let out="Display Repair: \(repairTime.getNumberOfDisplayRepair()) \n Other Repair: \(repairTime.getNumberOfOtherRepair()) \n Battery Repair: \(repairTime.getNumberOfBatteryRepair()) \n Back Cover Repair: \(repairTime.getNumberOfBackCoverRepair())"
let alertController = UIAlertController(title: "Current repair Queue", message: out
, preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default,handler: nil))
self.presentViewController(alertController, animated: true, completion: nil)
}
class RepairTime {
var optiontime = OptionTime()
var RepairGenius: Int = 1
var DisplayRepair: Int = 0
var OtherRepair: Int = 0
var BackCoverRepair: Int = 0
var BatteryRepair: Int = 0
func TimeOfRepair()->Double{
var repairtimezwei: Double
repairtimezwei=0.0
var repairzeit: Int
repairzeit=0
repairzeit=(BatteryRepair*optiontime.BatteryTime)+(BackCoverRepair*optiontime.BCTime)+(DisplayRepair*optiontime.DisplayTime)+(OtherRepair*optiontime.OtherTime)
//print(DisplayRepair)
repairtimezwei = (Double(repairzeit)/Double(RepairGenius))+15.0
return repairtimezwei
}
so and this is my second viewController:
class ViewController2: UIViewController,UITextFieldDelegate {
var optiontime = OptionTime()
#IBOutlet weak var DisplayTime: UITextField!
#IBOutlet weak var BatteryTime: UITextField!
#IBOutlet weak var BackCoverTime: UITextField!
#IBOutlet weak var OtherTime: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
//RFPTime.text = repairTime.ReadyForPickup()
// set TextField with Values of struct optionTime from class RepairTime
DisplayTime.text=String(optiontime.DisplayTime)
BatteryTime.text=String(optiontime.BatteryTime)
BackCoverTime.text=String(optiontime.BCTime)
OtherTime.text=String(optiontime.OtherTime)
//set KeybardType for Textinputs
self.DisplayTime.keyboardType = UIKeyboardType.NumbersAndPunctuation
self.BatteryTime.keyboardType = UIKeyboardType.NumbersAndPunctuation
self.BackCoverTime.keyboardType = UIKeyboardType.NumbersAndPunctuation
self.OtherTime.keyboardType = UIKeyboardType.NumbersAndPunctuation
self.DisplayTime.delegate = self
self.BatteryTime.delegate = self
self.BackCoverTime.delegate = self
self.OtherTime.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return false
}
#IBAction func TimeChangeDisplay(sender: AnyObject) {
optiontime.DisplayTime = Int(DisplayTime.text!)!
print("vie controler 2")
print(optiontime.DisplayTime)
}
#IBAction func TimeChangeBattery(sender: AnyObject) {
optiontime.BatteryTime = Int(BatteryTime.text!)!
}
#IBAction func TimeChangeBC(sender: AnyObject) {
optiontime.BCTime = Int(BackCoverTime.text!)!
}
#IBAction func TimeChangeOther(sender: AnyObject) {
optiontime.OtherTime = Int(OtherTime.text!)!
}
}
My Problem is that the value of the struct after finishing the edit in the textfield didn't change.

Resources