View Controller doesn't find a func member - swift

I'm getting this error:
Value of type 'DiscountVC' has no member 'calculateTotal'. And I have no clue why. Basically, I'm trying to make this calculator:
It should work as soon as you insert any value on the discountTF. Also, I have some pre-discounted buttons that just edit the discount value. The subtotalLabel value comes from another ViewController. For testing purposes, I'm using an initial value of 999.9.
import UIKit
class DiscountVC: UIViewController {
#IBOutlet var numericKeyboardView: UIView!
#IBOutlet var subtotalLabel: UILabel!
#IBOutlet var discountTF: UITextField!
#IBOutlet var totalLabel: UILabel!
var subtotal : Double = 999.9
var discount : Double = 0.0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
addKeyboard(view: numericKeyboardView)
subtotal = 999.9
discount = 0.0
discountTF.addTarget(self, action: #selector(self.calculateTotal(_:)), for: UIControl.Event.editingChanged)
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
func calculateTotal() {
let totalDouble = Double(subtotal) - Double(discountTF.text!)!
totalLabel.text = String(totalDouble)
}
func addKeyboard(view: UIView) {
let numericKeyboard = KeyboardVC(nibName: "NumericKeyboardVC", bundle: nil)
view.addSubview(numericKeyboard.view)
addChild(numericKeyboard)
}
#IBAction func fivePercentedButtonPressed(_ sender: Any) {
discount = Double(discountTF.text!)! * 0.05
discountTF.text = "\(discount)"
print(discount)
}
#IBAction func tenPercentButtonPressed(_ sender: Any) {
discount = Double(discountTF.text!)! * 0.1
discountTF.text = "\(discount)"
print(discount)
}
#IBAction func fifteenPercentButtonPressed(_ sender: Any) {
discount = Double(discountTF.text!)! * 0.15
discountTF.text = "\(discount)"
print(discount)
}
#IBAction func twentyPercentButtonPressed(_ sender: Any) {
discount = Double(discountTF.text!)! * 0.2
discountTF.text = "\(discount)"
print(discount)
}
#IBAction func goButton(_ sender: Any) {
}
}

Change to
#objc func calculateTotal(_ tex:UITextField){ --- }

Related

How can I make variables inside an IBAction public to all view controllers?

So I'm trying to make a Chess Time app, where both players have access to a clock and they change the time between bullet(3minutes), Blitz(5minutes), and Rapid(10Minutes). Well in my second view controller SettingsController I made 3 IBActions UIButtons for this.
#IBAction func bulletPressed(_ sender: UIButton) {
var storedTime = bullet
self.delegate?.storedTimeTimer()
self.navigationController?.popViewController(animated: true)
}
#IBAction func blitzPressed(_ sender: UIButton) {
var storedTime = blitz
}
#IBAction func rapidPressed(_ sender: UIButton) {
var storedTime = rapid
}
This is my SettingsController, my whole point is trying to get the storedTime into the first controller. I tried to use a delegate, but I couldn't get it to work.
Here is the full First Controller:
import UIKit
class ChessTimer: UIViewController {
#IBOutlet weak var playerTimer1: UILabel!
#IBOutlet weak var playerTimer2: UILabel!
var timer = Timer()
var time = 10
var isTimerRunning = false
override func viewDidLoad() {
super.viewDidLoad()
if isTimerRunning == false {
runTimer()
}
}
#IBAction func restartButton(_ sender: UIButton) {
}
#IBAction func pausePressed(_ sender: UIButton) {
timer.invalidate()
}
#IBAction func settingsPressed(_ sender: UIButton) {
performSegue(withIdentifier: "goToSettings", sender: self)
}
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self,selector:
(#selector(ChessTimer.updateTimer)),userInfo: nil, repeats: true)
isTimerRunning = true
}
#objc func updateTimer() {
if storedTime! < 1 {
timer.invalidate()
playerTimer1.text = "00:00"
playerTimer2.text = "00:00"
}
else {
storedTime! -= 1
playerTimer1.text = prodTimeString(time: TimeInterval(storedTime)!)
}
}
func prodTimeString(time: TimeInterval) -> String {
let prodMinutes = Int(time) / 60 % 60
let prodSeconds = Int(time) % 60
return String(format: "%02d:%02d", prodMinutes, prodSeconds)
}
#IBAction func playerButton1(_ sender: UIButton) {
}
#IBAction func playerButton2(_ sender: UIButton) {
}
}
extension ChessTimer: SettingsControllerDelegate {
func storedTimeTimer() {
}
}
This is the second full controller
import UIKit
class SettingsController: UIViewController {
var bullet = "03:00"
var blitz = "05:00"
var rapid = "10:00"
var storedTime = 0
var delegate: SettingsControllerDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func bulletPressed(_ sender: UIButton) {
var storedTime = bullet
self.delegate?.storedTimeTimer()
self.navigationController?.popViewController(animated: true)
}
#IBAction func blitzPressed(_ sender: UIButton) {
var storedTime = blitz
}
#IBAction func rapidPressed(_ sender: UIButton) {
var storedTime = rapid
}
}
protocol SettingsControllerDelegate {
func storedTimeTimer()
}
This can be achieved using a Constants.swift file.
Click File -> New -> File -> Swift File and then name it Constants.swift.
In Constants.swift, declare var storedTime = 0.
Delete var storedTime = 0 from your view controllers, you'll only need it in Constants.swift. (So delete it from SettingsController, etc.)
The storedTime variable will now be public to all view controllers. 👍
Hope this helps someone!

Swift: Why can I pass info from one IBAction to another, but not to a function

I am trying to get the values for splitValue and tipPercent into the getSettings() at the bottom. Why can I get the values for both of those in the IBAction calculatePressed, but when I try to get the values into the function the value is nil. I am sooo confused. Thank you for the help!
#IBOutlet weak var billTextField: UITextField!
#IBOutlet weak var zeroPctButton: UIButton!
#IBOutlet weak var tenPctButton: UIButton!
#IBOutlet weak var twentyPctButton: UIButton!
#IBOutlet weak var splitNumberLabel: UILabel!
var tipChosen = ""
var totalPerPerson = ""
var tipPercent = ""
var splitValue = ""
#IBAction func tipChanged(_ sender: UIButton) {
tipPercent = sender.currentTitle!
if sender.isSelected == true {
return
}
zeroPctButton.isSelected = false
tenPctButton.isSelected = false
twentyPctButton.isSelected = false
sender.isSelected = true
if sender.currentTitle == "0%" {
tipChosen = "0.00"
} else if sender.currentTitle == "10%" {
tipChosen = "0.10"
} else if sender.currentTitle == "20%" {
tipChosen = "0.20"
}
billTextField.endEditing(true)
}
#IBAction func stepperValueChanged(_ sender: UIStepper) {
splitValue = String(Int(sender.value))
splitNumberLabel.text = String(Int(sender.value))
}
#IBAction func calculatePressed(_ sender: UIButton) {
let bill = Float(billTextField.text!)!
let tip = Float(tipChosen)!
let tax = bill * tip
let splitNumber = Float(splitNumberLabel.text!)
let total = (bill + tax) / Float(splitNumber!)
totalPerPerson = "$\(String(format: "%.2f", total))"
performSegue(withIdentifier: "goToTotal", sender: self)
}
func getSettings() -> String {
return "Split between \(splitValue) people, with a \(tipPercent) tip."
}
Ok, sorry it took me a bit, but I finally think I understand what I did.
class CalculatorViewController: UIViewController {
var tip = 0.0
var finalBill = ""
var split = 2
#IBOutlet weak var billTextField: UITextField!
#IBOutlet weak var zeroPctButton: UIButton!
#IBOutlet weak var tenPctButton: UIButton!
#IBOutlet weak var twentyPctButton: UIButton!
#IBOutlet weak var splitNumberLabel: UILabel!
#IBAction func tipChanged(_ sender: UIButton) {
if sender.isSelected == false {
sender.isSelected = false
} else if sender.isSelected == true {
sender.isSelected = true
}
zeroPctButton.isSelected = false
tenPctButton.isSelected = false
twentyPctButton.isSelected = false
sender.isSelected = true
billTextField.endEditing(true)
}
#IBAction func stepperValueChanged(_ sender: UIStepper) {
splitNumberLabel.text = Int(sender.value).description
}
#IBAction func calculatePressed(_ sender: UIButton) {
if zeroPctButton.isSelected == true {
tip = 0.0
} else if tenPctButton.isSelected == true {
tip = 0.1
} else if twentyPctButton.isSelected == true {
tip = 0.2
}
print(tip)
let bill = Double(billTextField.text!)
split = Int(Double(splitNumberLabel.text!)!)
if billTextField.text != "" {
let billWithTip = (bill! * tip) + bill!
let billWithTipSplit = billWithTip / Double(split)
finalBill = String(format: "%.2f", billWithTipSplit)
print(billWithTip)
}
self.performSegue(withIdentifier: "getResults", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "getResults" {
let destinationVC = segue.destination as! ResultsViewController
destinationVC.finalBill = finalBill
destinationVC.split = split
destinationVC.tip = tip
}
}
}
class ResultsViewController: UIViewController {
#IBOutlet weak var totalLabel: UILabel!
#IBOutlet weak var settingsLabel: UILabel!
var tip = 0.0
var split = 2
var finalBill = ""
override func viewDidLoad() {
super.viewDidLoad()
totalLabel.text = "$\(finalBill)"
settingsLabel.text = "Split between \(Int(split)) people, with a \(Int(tip * 100))% tip"
}
#IBAction func recalculatePressed(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
}
I did what you suggested with the string and some minor calculations on the second view controller, changed the values of a few declared properties and got rid of the getSettings(). I was under the impression that I couldn't pass data without a return value from a function. Thank you for the help!

How to use file.swift into a swift created app(project)?

I have a task to create an app that checks if a String is a palindrome or not. And also I have instructed to create a file and in that file should be a function. But what I can't figure out is how to make a button run that function that is in the file.
func isPalidrone(phrase: String) -> Bool {
let isPalidrone = true
let reversed = String(phrase.reversed())
if reversed == phrase {
return isPalidrone
} else {
return !isPalidrone
}
}
class ViewController: UIViewController {
#IBOutlet weak var Label: UILabel!
#IBOutlet weak var textFieldOutlet: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonPressed(_ sender: Any) {
}
}
Like this:
#IBAction func buttonPressed(_ sender: Any) {
let pal = isPalidrone(phrase: self.textFieldOutlet.text!)
// now pal is true or false and you can decide what else to do ...
// for example:
self.Label.text = pal ? "It is a palindrome" : "It is not a palindrome"
}

Swift OSX NSImageView Drag and Drop

I am trying to execute an action after dropping an image on a drag and drop NSImageView but it is not working. How can I control the drag and drop operations?
I have the logoFornecedorImageView that is an NSImageView outlet. My class inherits from NSDraggingDestinatio and the dragged types are registered, but when I run the software and drag an image on it nothing happens, nothing is printed in the console.
import Cocoa
class InserirFornecedorViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate, NSDraggingDestination {
#IBOutlet weak var tituloJanelaLabel: NSTextField!
#IBOutlet weak var logoFornecedorImageView: NSImageView!
#IBOutlet weak var nomeFornecedorTextField: NSTextField!
#IBOutlet weak var materialFornecidoTextField: NSTextField!
#IBOutlet weak var materiaisTableView: NSTableView!
#IBOutlet weak var indicadorAtividadeProgressIndicator: NSProgressIndicator!
#IBOutlet weak var salvarFornercedorButton: NSButton!
var fornecedor: Fornecedor?
var logoFornecedorSelecionada = false
override func viewDidLoad() {
super.viewDidLoad()
materiaisTableView.dataSource = self
materiaisTableView.delegate = self
logoFornecedorImageView.register(forDraggedTypes: logoFornecedorImageView.registeredDraggedTypes)
fornecedor = Fornecedor()
}
func draggingEnded(_ sender: NSDraggingInfo?) {
print("END")
logoFornecedorSelecionada = true
}
func draggingEntered(_ sender: NSDraggingInfo) -> NSDragOperation {
print("ENTERED")
return .generic
}
func draggingUpdated(_ sender: NSDraggingInfo) -> NSDragOperation {
print("UPDATED")
return .generic
}
func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
return true
}
func numberOfRows(in tableView: NSTableView) -> Int {
return fornecedor?.materiais.count ?? 0
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
var cell: NSTableCellView?
//if tableColumn == tableView.tableColumns[0]
if fornecedor?.materiais.count != 0 {
let identificadorCell = "materialCellView"
let material = fornecedor?.materiais[row]
cell = tableView.make(withIdentifier: identificadorCell, owner: nil) as? NSTableCellView
cell?.textField?.stringValue = material!
}
return cell
}
#IBAction func selecionarImagemButtonClicked(_ sender: NSButton) {
let panel = NSOpenPanel()
panel.canChooseFiles = true
panel.canChooseDirectories = false
panel.allowsMultipleSelection = false
panel.canCreateDirectories = false
//panel.allowedFileTypes = ["jpg","png","pct","bmp", "tiff"]
panel.allowedFileTypes = NSImage.imageTypes()
panel.beginSheetModal(for: view.window!) { (result) in
if result == NSFileHandlingPanelOKButton {
self.logoFornecedorImageView.image = NSImage(byReferencing: panel.url!)
self.logoFornecedorSelecionada = true
}
}
}
#IBAction func removerImagemButtonClicked(_ sender: NSButton) {
logoFornecedorImageView.image = NSImage(named: "LogoImagemTexto")
logoFornecedorSelecionada = false
}
#IBAction func adicionarMaterialButton(_ sender: NSButton) {
if materialFornecidoTextField.stringValue.isEmpty {
mostrarErro(mensagem: "Erro de preenchimento", informativo: "Informe o material")
materialFornecidoTextField.becomeFirstResponder()
} else {
fornecedor?.materiais.append(materialFornecidoTextField.stringValue)
materialFornecidoTextField.stringValue = ""
fornecedor?.materiais.sort {
$0.localizedCaseInsensitiveCompare($1) == ComparisonResult.orderedAscending
}
materiaisTableView.reloadData()
}
}
#IBAction func voltarButton(_ sender: NSButton) {
//let usarSoftViewController = presenting as! UsarSoftViewController
//usarSoftViewController.ativarBoxPrincipal()
//usarSoftViewController.usuario = usuario
//usarSoftViewController.fazerLogin()
dismiss(self)
}
func mostrarErro(mensagem: String, informativo: String) {
let alert = NSAlert()
alert.messageText = mensagem
alert.informativeText = informativo
alert.addButton(withTitle: "Fechar")
alert.alertStyle = .critical
alert.runModal()
}
}
Thanks everyone
I just performed an action and it worked fine.
#IBAction func logoFornecedorImageDropped(_ sender: NSImageView) {
self.logoFornecedorSelecionada = true
}
To add a little more clarity around this, you can connect a regular IBAction to your Editable NSImageView and get the image. You don't have to do any subclassing or dragging delegates.
Just do this:
#IBAction func imageChange(_ sender: NSImageView) {
if let image = sender.image{
let imageData = image.tiffRepresentation
}
}
I hope that helps. :)

How can I get hundredths place instead of tenths place in output

When I enter an amount in the text field I get in total the amount in tenths place, so how can I get hundredths place instead of tenths place?
Also how can I get the tip percentage label an integer instead of a decimal?
import UIKit
class ViewController: UIViewController, SettingsDelegate {
//Inputs
#IBOutlet weak var amountTextField: UITextField!
//Labels
#IBOutlet weak var TipPercentageLabel: UILabel!
#IBOutlet weak var numberOfPersonLabel: UILabel!
#IBOutlet weak var tipAmountLabel: UILabel!
#IBOutlet weak var totalBillLabel: UILabel!
#IBOutlet weak var billPerPersonLabel: UILabel!
//Slider & Stepper
#IBOutlet weak var tipSlider: UISlider!
#IBOutlet weak var personsStepper: UIStepper!
//Variables
var tipPercentage : Double = NSUserDefaults.standardUserDefaults().doubleForKey("DefaultTipRate") ?? 0.20
var numberOfPerson:Int = 1
let numberFormatter:NSNumberFormatter = NSNumberFormatter()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tipAmountLabel.text = "$0.00"
totalBillLabel.text = "Bill Total"
billPerPersonLabel.text = "$0.00"
numberOfPersonLabel.text = "1"
self.amountTextField.becomeFirstResponder()
print("DefaultTipRate")
let tipPercentage : Double = NSUserDefaults.standardUserDefaults().doubleForKey("DefaultTipRate")
TipPercentageLabel.text = self.numberFormatter.stringFromNumber(tipPercentage)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func setupContainer() {
tipSlider.minimumValue = 0
tipSlider.maximumValue = 100
tipSlider.value = 20
tipSlider.addTarget(self, action: "sliderTipChanged:", forControlEvents: .ValueChanged)
personsStepper.minimumValue = 1
personsStepper.maximumValue = 30
personsStepper.value = 1
personsStepper.addTarget(self, action: "sliderPersonChanged:", forControlEvents: .ValueChanged)
amountTextField.text = ""
refreshCalculation()
}
#IBAction func OnEditingFieldBill(sender: AnyObject) {
refreshCalculation()
}
func refreshCalculation() {
numberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
if let amount = numberFormatter.numberFromString(amountTextField.text!) as? Double {
let tipAmount = amount * tipPercentage
let totalBill = amount + tipAmount
let billPerPerson = totalBill / Double(numberOfPerson)
numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
tipAmountLabel.text = numberFormatter.stringFromNumber(tipAmount)
totalBillLabel.text = numberFormatter.stringFromNumber(totalBill)
billPerPersonLabel.text = numberFormatter.stringFromNumber(billPerPerson)
} else {
tipAmountLabel.text = "-"
totalBillLabel.text = "-"
billPerPersonLabel.text = "-"
}
numberFormatter.numberStyle = NSNumberFormatterStyle.PercentStyle
numberFormatter.minimumFractionDigits = 2
numberFormatter.maximumFractionDigits = 2
TipPercentageLabel.text = String(format: "%.0f%%", tipPercentage)
numberOfPersonLabel.text = "\(numberOfPerson)"
}
#IBAction func sliderTipChanged(sender: AnyObject) {
tipPercentage = Double(round(tipSlider.value)) / 100
refreshCalculation()
}
#IBAction func StepperPersonChanged(sender: AnyObject) {
numberOfPerson = Int(round(personsStepper.value))
refreshCalculation()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let SettingsViewController = segue.destinationViewController as? SettingsViewController {
SettingsViewController.delegate = self
refreshCalculation()
}
}
func tipPercentageChanged(newValue: Double) {
TipPercentageLabel.text = "\(newValue)%"
tipPercentage = newValue
refreshCalculation()
}
SETTINGS VIEW CODE
import UIKit
protocol SettingsDelegate{
func tipPercentageChanged(newValue : Double)
}
class SettingsViewController: UIViewController {
#IBOutlet weak var tipControl: UISegmentedControl!
var tipRates:Double?
var destName : String!
var delegate :SettingsDelegate?
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.
}
#IBAction func changeValue(sender: UISegmentedControl) {
var tipRate = [0.05, 0.10, 0.15, 0.20, 0.25, 0.30]
tipRates = (tipRate[tipControl.selectedSegmentIndex])
delegate?.tipPercentageChanged(tipRates!); print("(tipRates)")
NSUserDefaults.standardUserDefaults().setDouble(tipRates!, forKey: "DefaultTipRate")
NSUserDefaults.standardUserDefaults().synchronize()
}
}
Since you are using NSNumberFormatter, set maximumFractionDigits and minimumFractionDigits properties to 2:
let numberFormatter = NSNumberFormatter()
numberFormatter.maximumFractionDigits = 2
numberFormatter.minimumFractionDigits = 2
let str = numberFormatter.stringFromNumber(14.7) // "14.70"
Alternatively, you could use the String(format:) constructor:
let str = String(format: "%.2f", 14.7) // "14.70"
For your tip percentage, since you are storing it as a decimal percentage, you can do:
let tipPercentage: Double = 0.17
TipPercentageLabel.text = String(format: "%.0f%%", tipPercentage * 100) // "17%"