RxSwift 'bindTo(aNSButton.rx_enabled)' failed - swift

here is my code:
let aDisposeBag = DisposeBag()
class LoginController: NSViewController {
#IBOutlet weak var accountField: NSTextField!
#IBOutlet weak var passwdField: NSSecureTextField!
#IBOutlet weak var loginBtn: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
let accAvailable = accountField.rx_text.map({(aa)-> Bool in
print("aa")
return aa.characters.count > 0
})
let passAvailable = passwdField.rx_text.map({(aa)-> Bool in
print("bb")
return aa.characters.count > 0
})
let allAvailable = Observable.combineLatest(accAvailable, passAvailable){$0 && $1}
allAvailable.bindTo(loginBtn.rx_enabled).addDisposableTo(aDisposeBag)
}
}
When I input contents into accountField,nothing prints in the console.
But if I replace allAvailable.bindTo(loginBtn.rx_enabled).addDisposableTo(aDisposeBag) into
allAvailable.subscribeNext { (available) in
print(available)
}.addDisposableTo(aDisposeBag)
Then I can see aa or bb is printed in the console.
Anyone can tell what's wrong with my code,thanks a lot!

Related

I am trying to add a UILabel exactly like I already have but keep getting this error

I am trying to add a label to my calculator where it shows the tip amount but I keep getting
Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
I just want it to display the tip amount as well. I copied it exact for the other UILabel.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var PriceTxt: UITextField!
#IBOutlet weak var Tip: UITextField!
#IBOutlet weak var totalFinal: UILabel!
#IBOutlet weak var TipAmount: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
totalFinal.text = ""
TipAmount.text = ""
}
#IBAction func Calcualte(_ sender: Any) {
if PriceTxt.text! == "" || Tip.text! == ""
{
totalFinal.text = "Input the Numbers"
TipAmount.text = ""
}
else {
let price = Double(PriceTxt.text!)!
let tipPer = Double(Tip.text!)!
let TipMult = price * (tipPer/100)
let TipFinal = Double((round(100*TipMult)/100) + price)
totalFinal.text = "$\(TipFinal)"
TipAmount.text = "$\(TipMult)"
}
}
}
It will show you the problem in your code.. please always try to avoid force cast
class ViewController: UIViewController {
#IBOutlet weak var PriceTxt: UITextField!
#IBOutlet weak var Tip: UITextField!
#IBOutlet weak var totalFinal: UILabel!
#IBOutlet weak var TipAmount: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
totalFinal.text = ""
TipAmount.text = ""
}
#IBAction func Calcualte(_ sender: Any) {
if let getPrice = PriceTxt.text , let getTip = Tip.text
{
if getPrice.isEmpty || getTip.isEmpty {
totalFinal.text = "Input the Numbers"
TipAmount.text = ""
}
else {
let price = Double(getPrice)!
let tipPer = Double(getTip)!
let TipMult = price * (tipPer/100)
let TipFinal = Double((round(100*TipMult)/100) + price)
totalFinal.text = "$\(TipFinal)"
TipAmount.text = "$\(TipMult)"
}
} else {
print("either PriceTxt or Tip is nil")
}
}
}
Try using ? instead of !
! force unwraps and gives you a fatal error if there is no value (nil). ? only unwraps if a value is present.
Also, why unwrap the text here at all?
Use
PriceTxt.text == "" || Tip.text == "" without the ! or ?.

How do I store a calculated result in UserDefaults to display in a "results" View controller [duplicate]

This question already has answers here:
How can I use UserDefaults in Swift?
(14 answers)
Closed 4 years ago.
First time poster so sorry for the incorrect format/length of the question.
I am building an app in Xcode that allows users to input various inputs among numerous view controllers and then have output in a single view controller with results displayed through labels.
The raw inputted textfield data is stored into UserDefaults and can display them later in the resulting VC with no problem. Im having trouble with calculated outputs (in this example "papiresult") however.
Can anyone provide guidance how to print out the calculated result several view controllers later using UserDefaults?
This is the rough layout
Here is the code I have in the first ViewController:
import UIKit
let userDefaults = UserDefaults()
var papiresult = Double()
class ViewController1: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField1: UITextField!
#IBOutlet weak var textField2: UITextField!
#IBOutlet weak var textField3: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField1.delegate = self
textField2.delegate = self
textField3.delegate = self
}
//Declaring data input into UserDefaults//
#IBAction func sendDataToVC2(_ sender: Any) {
let systPA = Double(textField1.text!)
let diastPA = Double(textField2.text!)
let cvPressure = Double(textField3.text!)
papiresult = ((systPA!-diastPA!)/cvPressure!)
userDefaults.set(textField1.text, forKey: "PASP")
userDefaults.set(textField2.text, forKey: "PADP")
userDefaults.set(textField3.text, forKey: "CVP")
userDefaults.set(papiresult, forKey: "PAPI")
}
}
Here is the code in the last (result) view controller:
import UIKit
class ViewController3: UIViewController {
#IBOutlet weak var label1: UILabel!
#IBOutlet weak var label2: UILabel!
#IBOutlet weak var label3: UILabel!
#IBOutlet weak var label4: UILabel!
#IBOutlet weak var label5: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
}
//Recalling data from UserDefaults//
override func viewWillAppear(_ animated: Bool) {
if let data1 = userDefaults.object(forKey: "PASP") {
if let message1 = data1 as? String {
self.label1.text = message1}
}
if let data2 = userDefaults.object(forKey: "PADP") {
if let message2 = data2 as? String {
self.label2.text = message2}
}
if let data3 = userDefaults.object(forKey: "CVP") {
if let message3 = data3 as? String {
self.label3.text = message3}
}
if let data4 = userDefaults.object(forKey: "Age") {
if let message4 = data4 as? String {
self.label4.text = message4}
}
if let data5 = userDefaults.object(forKey: "PAPI") {
if let message5 = data5 as? Double {
self.label5.text = "\(message5)"}
}
}
Basically, you should use UserDefaults.standard rather than creating a new instance of UserDefaults class. So I think this code
let userDefaults = UserDefaults()
should be replaced with this:
let userDefaults = UserDefaults.standard

enable NSButton if NSTextfield is not empty

I am creating a OSX app and would like to enable a button when all textfield are filled. But do not have much experience with osx app as there seem to be some difference from ios.
This is what I have tried.
override func viewDidLoad() {
super.viewDidLoad()
btnCalculate.enabled = false
}
override func controlTextDidChange(obj: NSNotification) {
if panelsWideTextField.stringValue.isEmpty {
btnCalculate.enabled = false
} else {
btnCalculate.enabled = true
}
}
Hope someone has a good tip for me :-)
EDIT:
Complete code.
import Cocoa
//import AppKit
class ViewController: NSViewController, NSTextFieldDelegate {
#IBOutlet weak var panelHightTextField: NSTextField!
#IBOutlet weak var panelWidthTextField: NSTextField!
#IBOutlet weak var panelPitchTextField: NSTextField!
#IBOutlet weak var panelsHighTextField: NSTextField!
#IBOutlet weak var panelsWideTextField: NSTextField!
#IBOutlet weak var resWidthLabel: NSTextField!
#IBOutlet weak var resHightLabel: NSTextField!
#IBOutlet weak var lblScreenWidth: NSTextField!
#IBOutlet weak var lblScreenHight: NSTextField!
#IBOutlet weak var lblScreenArea: NSTextField!
#IBOutlet weak var btnCalculate: NSButton!
#IBOutlet weak var lblAmountPanels: NSTextField!
var panelHight = ""
var panelWidth = ""
var panelPitch = ""
var panelsHigh = ""
var panelsWidth = ""
var resWidth : Float = 0
var resHigh : Float = 0
var screenHight : Float = 0
var screenWidth : Float = 0
var screenArea : Float = 0
var ammountPanels : Float = 0
override func viewDidLoad() {
super.viewDidLoad()
btnCalculate.enabled = false
}
override func controlTextDidChange(obj: NSNotification) {
if panelsWideTextField.stringValue.isEmpty {
btnCalculate.enabled = true
} else {
btnCalculate.enabled = false
}
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
#IBAction func calculateResButton(sender: AnyObject) {
takeUserData()
calculatehight()
calculatewidth()
calculateArea()
calculateAmountPanels()
}
func takeUserData(){
panelHight = panelHightTextField.stringValue
panelWidth = panelWidthTextField.stringValue
panelPitch = panelPitchTextField.stringValue
panelsHigh = panelsHighTextField.stringValue
panelsWidth = panelsWideTextField.stringValue
}
// Calculating resolution and physical hight
func calculatehight(){
let fpanelHight = Float(panelHight)
let fpanelPitch = Float(panelPitch)
let fpanelsHigh = Float(panelsHigh)
resHigh = fpanelHight! * fpanelsHigh! / fpanelPitch!
screenHight = fpanelHight! * fpanelsHigh! / 1_000
printText()
}
// Calculating resolution and physical width
func calculatewidth(){
let fpanelWidth = Float(panelWidth)
let fpanelPitch = Float(panelPitch)
let fpanelsWidth = Float(panelsWidth)
resWidth = fpanelWidth!*fpanelsWidth!/fpanelPitch!
screenWidth = fpanelWidth!*fpanelsWidth! / 1_000
printText()
}
// Calculating sqm of LED screen
func calculateArea(){
let fpanelHight = Float(panelHight)
let fpanelsHigh = Float(panelsHigh)
let fpanelWidth = Float(panelWidth)
let fpanelsWidth = Float(panelsWidth)
screenArea = (fpanelHight! * fpanelsHigh!) * (fpanelWidth! * fpanelsWidth!) / 1_000_000
printText()
}
// Calculating the amount of panels used.
func calculateAmountPanels(){
let fpanelsHigh = Float(panelsHigh)
let fpanelsWidth = Float(panelsWidth)
ammountPanels = (fpanelsWidth! * fpanelsHigh!)
printText()
}
// Outputting text to labels with correct format.
func printText(){
let formatResHigh = String(format: "%0.0f", resHigh)
let formatResWidth = String(format: "%0.0f", resWidth)
let formatScreenHight = String(format: "%0.2f", screenHight)
let formatScreenWidth = String(format: "%0.2f", screenWidth)
let formatScreenArea = String(format: "%0.0f", screenArea)
let formatAmmountPanels = String(format: "%0.0f", ammountPanels)
resHightLabel.stringValue = "\(formatResHigh)px"
resWidthLabel.stringValue = "\(formatResWidth)px"
lblScreenHight.stringValue = "\(formatScreenHight)m"
lblScreenWidth.stringValue = "\(formatScreenWidth)m"
lblScreenArea.stringValue = "\(formatScreenArea) sqm"
lblAmountPanels.stringValue = "\(formatAmmountPanels)"
}
}
I had the same problem but I found simple solution: checkbox can enable and disable NSButton.
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var btnCalculate: NSButton!
#IBOutlet weak var checkBox: NSButton!
override func viewDidLoad() {
super.viewDidLoad()
btnCalculate.enabled = false
checkBox.state = 0
}
#IBAction func checkAgree(sender: NSButton) {
if btnCalculate.stringValue.characters.count > 0 && checkBox.state == 1 {
btnCalculate.enabled = true
} else {
btnCalculate.enabled = false
}
}
}

Disable button in cocoa application OS X

I would like to have the submit button enabled once some fields on a form have been validated. Currently the preview function works great, preview button provides the validation I need. Working on Xcode 7 and swift 2. I would really appreciated if someone can point me in the right direction. Below is the code I currently have:
import Cocoa
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var projectFlag = false
var descriptionFlag = false
var releaseFlag = false
// Fields
#IBOutlet weak var projectNumberTextField:NSTextField!
#IBOutlet weak var projectDescriptionTextField:NSTextField!
#IBOutlet weak var releaseFolderNameTextField:NSTextField!
#IBOutlet weak var passwordTextField:NSTextField!
// Labels for preview
#IBOutlet weak var label1: NSTextField!
#IBOutlet weak var label2: NSTextField!
#IBOutlet weak var label3: NSTextField!
#IBOutlet weak var label4: NSTextField!
#IBOutlet weak var label5: NSTextField!
// Quit Button :: Quits the application
#IBAction func quitButton(sender: AnyObject) {
NSApplication.sharedApplication().terminate(self)
}
// Preview button behavior
#IBAction func previewButton(sender: AnyObject) {
// Project Number ::
let project = projectNumberTextField.stringValue
label1.stringValue = "\(project)"
if (label1.stringValue == "00-0000") {
label1.stringValue = "Project Number is not valid"
label1.textColor = NSColor.redColor()
projectFlag = false
} else {
label1.textColor = NSColor.blackColor()
projectFlag = true
}
// Project Description :: Name, 2016
let description = projectDescriptionTextField.stringValue
label2.stringValue = "\(description)"
if (label2.stringValue == "Name, 2016") {
label2.stringValue = "Enter a valid project description"
label2.textColor = NSColor.redColor()
descriptionFlag = false
} else {
label2.textColor = NSColor.blackColor()
descriptionFlag = true
}
// Folder Release Name :: RELEASE_NAME
let release = releaseFolderNameTextField.stringValue
label3.stringValue = "\(release)"
if (label3.stringValue == "RELEASE_NAME") {
label3.stringValue = "Enter a valid folder release name"
label3.textColor = NSColor.redColor()
releaseFlag = false
} else {
label3.textColor = NSColor.blackColor()
releaseFlag = true
}
// Password :: If needed
let password = passwordTextField.stringValue
label4.stringValue = "\(password)"
// Preview :: Code format for txt file
let preview = "\(project)|"+"\(description)|"+"\(release)|"+"\(password)/"
label5.stringValue = "\(preview)"
}
// Submit button behavior
#IBAction func submitButton(Sender: AnyObject) {
}
func applicationDidFinishLaunching(aNotification: NSNotification) {
// Insert code here to initialize your application
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}

if statement returning a value not working for UiLabel

my fairly new to swift and programming, I'm trying to display a value from an if statement. Here is my func within my UiLabel. I've tried a few variations along the same lines but it only every returns "calculate.fuelTank" it never seems to trigger the second part to my IF statement?
#IBOutlet weak var startingFuelDisplay: UILabel! //not working yet
func refreshUiopeningFuel() {
if calculate.totalFuel <= Double(calculate.fuelTank) {
print (Double(calculate.fuelTank)) // FuelTank
} else {
print (calculate.totalFuel) // TotalFuel
}
Do I need to add a bool argument to trigger "else"? I have also tried using the "return" function with initialised string which included the value I was trying to extract, finally I need this to work for another display.
here is my full view controller code (i'm new I'm sure it could be cleaner)
import UIKit
class ViewController: UIViewController {
let calculate = Inputs ( raceLaps: 13, fuelRate: 3.7, fuelTank: 110, laptime: 85.456, tyreWear: 0.05 )
#IBOutlet weak var rate: UITextField!
#IBOutlet weak var laps: UITextField!
#IBOutlet weak var tank: UITextField!
#IBOutlet weak var tyreWear: UITextField!
#IBOutlet weak var laptime: UITextField!
#IBOutlet var cancelKeyboard: UITapGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//Looks for single or multiple taps.
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "dismissKeyboard")
view.addGestureRecognizer(tap)
}
//Calls this function when the tap is recognized.
func dismissKeyboard() {
//Causes the view (or one of its embedded text fields) to resign the first responder status.
view.endEditing(true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
refreshUiFuel()
refreshUiStops()
refreshUiTyreLife()
refreshUiTyreLifeLaps()
refreshUiopeningFuel()
refreshUiBoxOnLap ()
}
#IBAction func calculate(sender: UIButton) {
if let rateVal = Double(rate.text!),
tankVal = Int(tank.text!),
lapVal = Int(laps.text!),
wearVal = Double(tyreWear.text!),
laptimeVal: Float = 85.456 {
let fuelModel = Inputs(raceLaps: lapVal, fuelRate: rateVal, fuelTank: tankVal, laptime: laptimeVal, tyreWear: wearVal )
totalFuelDisplay.text = ("\(Double(fuelModel.totalFuel))")
totalStopsDisplay.text = ("\(Int(fuelModel.totalStops))")
tyreLifeDisplay.text = ("\(Int(fuelModel.tyreChangesRaceDistanceTotal))")
tyreLifeLapsDisplay.text = ("\(Int(fuelModel.tyreLife))")
startingFuelDisplay.text = ("\(refreshUiopeningFuel())")
}
else {
totalFuelDisplay.text = "missing value"
totalStopsDisplay.text = "missing value"
tyreLifeDisplay.text = "missing value"
tyreLifeLapsDisplay.text = "missing value"
startingFuelDisplay.text = "missing Value"
}
}
#IBOutlet weak var totalFuelDisplay: UILabel!
func refreshUiFuel()->String {
return totalFuelDisplay.text!
}
#IBOutlet weak var totalStopsDisplay: UILabel!
func refreshUiStops()->String {
return totalStopsDisplay.text!
}
#IBOutlet weak var tyreLifeDisplay: UILabel!
func refreshUiTyreLife()->String {
return tyreLifeDisplay.text!
}
#IBOutlet weak var tyreLifeLapsDisplay: UILabel!
func refreshUiTyreLifeLaps()->String {
return tyreLifeLapsDisplay.text!
}
#IBOutlet weak var pitOnLapDisplay: UILabel!
func refreshUiBoxOnLap () {
}
#IBOutlet weak var startingFuelDisplay: UILabel! //not working yet
func refreshUiopeningFuel() ->Double {
print(calculate.fuelTank)
print(calculate.totalFuel)
if calculate.totalFuel <= Double(calculate.fuelTank) {
return Double(calculate.fuelTank) // FuelTank
} else {
return calculate.totalFuel // TotalFuel
}
}
}
all helped welcomed
Judging from the natural real-world logic, it appears you've simply reversed the if/else logic. It would seem that if totalFuel is less than the tank's capacity (the if clause), you should return totalFuel in that case, and return the tank capacity in the else clause.