在Swift中计算方程:

huangapple go评论85阅读模式
英文:

Calculate equation in Swift

问题

抱歉,你的代码片段中包含了许多 HTML 实体编码(如 "),它们在翻译中没有意义。以下是修复后的代码部分:

import UIKit

class SelectAttributesViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {

    @IBOutlet weak var kitPickerView: UIPickerView!
    @IBOutlet weak var reactionVolumeLabel: UILabel!
    @IBOutlet weak var numberOfSampleTextField: UITextField!
    @IBOutlet weak var volumeOfTemplateDNATextField: UITextField!
    @IBOutlet weak var slider: UISlider!
    @IBOutlet weak var calculateButton: UIButton!

    let kits = ["kit 1", "Kit 2"]
    let pArray = [10, 20, 50]

    override func viewDidLoad() {
        super.viewDidLoad()
        self.numberOfSampleTextField.delegate = self
        self.volumeOfTemplateDNATextField.delegate = self
        kitPickerView.dataSource = self
        kitPickerView.delegate = self

        let tap = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:)))
        view.addGestureRecognizer(tap)
    }

    func pInterval() {
        slider.minimumValue = 0
        slider.maximumValue = Float(pArray.count)
        slider.isContinuous = false
    }

    @IBAction func reactionVolumeSlider(_ sender: UISlider) {
        print(Int(sender.value))
        let currentValue = pArray[Int(sender.value)]
        reactionVolumeLabel.text = "\(currentValue) μL"
    }

    func numberOfComponents(in pickerView: UIPickerView) -> Int {
        return 1
    }

    func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
        return kits.count
    }

    func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
        if row == 0 {
            print(kits[row])
        } else if row == 1 {
            createAlert(title: "Kit not available", message: "More kits will be added soon!")
            calculateButton.isEnabled = false
        }
    }

    func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
        return kits[row]
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let oldText = textField.text, let r = Range(range, in: oldText) else {
            return true
        }

        let newText = oldText.replacingCharacters(in: r, with: string)
        let isNumeric = newText.isEmpty || (Double(newText) != nil)
        let numberOfDots = newText.components(separatedBy: ".").count - 1

        let numberOfDecimalDigits: Int
        if let dotIndex = newText.firstIndex(of: ".") {
            numberOfDecimalDigits = newText.distance(from: dotIndex, to: newText.endIndex) - 1
        } else {
            numberOfDecimalDigits = 0
        }

        return isNumeric && numberOfDots <= 1 && numberOfDecimalDigits <= 2
    }

    func createAlert(title: String, message: String) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
        alert.addAction(UIAlertAction(title: "Ok", style: UIAlertAction.Style.default, handler: { (action) in
            alert.dismiss(animated: true, completion: nil)
        }))
        self.present(alert, animated: true, completion: nil)
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        let masterMix = segue.destination as! MasterMixTableViewController
        masterMix.loadViewIfNeeded()

        // The line below is where I tried to implement this function
        // masterMix.waterVolumeLabel!.text = 

        masterMix.bufferVolumeLabel.text = String(Double(numberOfSampleTextField.text!)! * 10)
        masterMix.dNTPsVolumeLabel.text = numberOfSampleTextField!.text
        masterMix.forwardPrimerLabel.text = String(Double(numberOfSampleTextField.text!)! * 2.5)
        masterMix.reversePrimerLabel.text = String(Double(numberOfSampleTextField.text!)! * 2.5)
        masterMix.dnaPolymeraseLabel.text = String(Double(numberOfSampleTextField.text!)! * 0.5)
    }

    @IBAction func calculatePressed(_ sender: Any) {
        if numberOfSampleTextField.text != "" {
            performSegue(withIdentifier: "masterMixSegue", sender: self)
        }
    }
}

希望这对你有所帮助!如果你有其他问题或需要进一步的翻译,请随时告诉我。

英文:

Hello every one i am fairly new to Swift and I have an app where I need to get a users input and put it into an equation to show on a different view controller. Im having trouble entering this equation as follows...

masterMix.waterVolumeLabel.text = numberOfSamplesTextField(50 - dNTPsVolumeLabel.text - forwardPrimerLabel.text - reversePrimerLabel.text - dnaPolymeraseLabel.text - volumeOfTemplateDNAtextfield.text - masterMix.bufferVolumeLabel)

The total from inside the parentheses need to be multiplied by numberOfSamplesTextField

How would i write this in swift? The equation is inside prepare for segue.

import UIKit
class SelectAttributesViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITextFieldDelegate {
@IBOutlet weak var kitPickerView: UIPickerView!
@IBOutlet weak var reactionVolumeLabel: UILabel!
@IBOutlet weak var numberOfSampleTextField: UITextField!
@IBOutlet weak var volumeOfTemplateDNATextField: UITextField!
@IBOutlet weak var slider: UISlider!
@IBOutlet weak var calculateButton: UIButton!
let kits = [&quot;kit 1&quot;, &quot;Kit 2&quot;]
let pArray = [10,20,50]
override func viewDidLoad() {
super.viewDidLoad()
self.numberOfSampleTextField.delegate = self
self.volumeOfTemplateDNATextField.delegate = self
kitPickerView.dataSource = self
kitPickerView.delegate = self
//slider.addTarget(self, action: &quot;reactionVolumeSlider&quot;, for: .valueChanged)
let tap = UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:)))
view.addGestureRecognizer(tap)
// Do any additional setup after loading the view.
}
func pInterval() {
slider.minimumValue = 0
slider.maximumValue = Float(pArray.count)
slider.isContinuous = false
}
@IBAction func reactionVolumeSlider(_ sender: UISlider) {
print(Int(sender.value))
let currentValue = pArray[Int(sender.value)]
reactionVolumeLabel.text = &quot;\(currentValue) μL&quot;
}
func numberOfComponents(in pickerView: UIPickerView) -&gt; Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -&gt; Int {
return kits.count
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if row == 0{ print(kits[row])
}else if row == 1{
createAlert(title: &quot;Kit not available&quot;, message: &quot;More kits will be added soon!&quot;)
calculateButton.isEnabled = false
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -&gt; String? {
return kits[row]
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -&gt; Bool {
guard let oldText = textField.text, let r = Range(range, in: oldText) else {
return true
}
let newText = oldText.replacingCharacters(in: r, with: string)
let isNumeric = newText.isEmpty || (Double(newText) != nil)
let numberOfDots = newText.components(separatedBy: &quot;.&quot;).count - 1
let numberOfDecimalDigits: Int
if let dotIndex = newText.firstIndex(of: &quot;.&quot;) {
numberOfDecimalDigits = newText.distance(from: dotIndex, to: newText.endIndex) - 1
} else {
numberOfDecimalDigits = 0
}
return isNumeric &amp;&amp; numberOfDots &lt;= 1 &amp;&amp; numberOfDecimalDigits &lt;= 2
}
func createAlert (title: String, message: String){
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert)
alert.addAction(UIAlertAction(title: &quot;Ok&quot;, style: UIAlertAction.Style.default, handler: { (Action) in
alert.dismiss(animated: true, completion: nil)
}))
self.present(alert, animated: true, completion: nil)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let masterMix = segue.destination as! MasterMixTableViewController
masterMix.loadViewIfNeeded()
// The line below is where I tried to implement this function
// masterMix.waterVolumeLabel!.text = 
masterMix.bufferVolumeLabel.text = String(Double(numberOfSampleTextField.text!)! * 10)
masterMix.dNTPsVolumeLabel.text = numberOfSampleTextField!.text // done
masterMix.forwardPrimerLabel.text = String(Double(numberOfSampleTextField.text!)! * 2.5) //done
masterMix.reversePrimerLabel.text = String(Double(numberOfSampleTextField.text!)! * 2.5) //done
masterMix.dnaPolymeraseLabel.text = String(Double(numberOfSampleTextField.text!)! * 0.5) //done
//answer.text = String(Int(entry.text)! * 2)
}
@IBAction func calculatePressed(_ sender: Any) {
if numberOfSampleTextField.text != &quot;&quot;{
performSegue(withIdentifier: &quot;masterMixSegue&quot;, sender: self)
}
}
}

答案1

得分: 1

有一些问题与你尝试做的事情有关。首先,你不应该在prepareForSegue中设置目标视图控制器中视图的内容。你可以计算该值,然后像Phillip建议的那样传递它。首先,你需要计算它。另一个问题是,你不能对文本运行数学运算,这似乎是你试图做的事情。你可以将一个字符串转换为Int或Double,并且它将作为可选值返回,以防文本实际上不包含数字。最安全的做法是始终有条件地解包,但我认为在你的情况下,你可以做一些像这样的事情,添加一个字符串的扩展来返回文本的非可选双精度值,如果它是nil,则返回零(这样不会对结果产生任何影响)。因此,在你的项目中,在任何类之外添加这个:

extension String {
    func doubleValue() -> Double {
        return Double(self) ?? 0
    }
}

现在,在你的第一个视图控制器中,你可以添加下面的函数来执行你的计算。我假设你留下了一些代码,因为在你提供的代码中,你没有声明许多不同的标签和文本字段(例如dNTPsVolumeLabelforwardPrimerLabel等)。所以假设你已经将它们作为你的第一个视图控制器的一部分,类似于这样的代码应该可以正常工作:

func getWaterVolumeLabelText() -> String? {
    return numberOfSamplesTextField.text?.doubleValue() * (50.0 - dNTPsVolumeLabel.text?.doubleValue() - forwardPrimerLabel.text?.doubleValue() - reversePrimerLabel.text?.doubleValue() - dnaPolymeraseLabel.text?.doubleValue() - volumeOfTemplateDNAtextfield.text?.doubleValue() - bufferVolumeLabel.text?.doubleValue())
}

现在你有一个在触发segue时运行计算的函数。你所需要做的就是将它传递给目标视图控制器。最简单的方法是在目标视图控制器中添加一个字符串属性,类似于这样:

class MasterMixTableViewController: UIViewController {
    
    // 这将是你目标视图控制器中的标签
    @IBOutlet weak var waterVolumeLabel: UILabel!
    
    // 添加这个
    public var waterVolumeText: String?
    
    override func viewWillAppear(_ animated: Bool) {
        // 在这里,你可以对传递进来的字符串进行任何操作
        waterVolumeLabel.text = waterVolumeText
    }
}

现在回到你的SelectAttributesViewController中的prepare for segue方法,只需将它更改为这样:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    let masterMix = segue.destination as! MasterMixTableViewController
    masterMix.loadViewIfNeeded()

    // 这将传递该值
    masterMix.waterVolumeText = getWaterVolumeLabelText()
}
英文:

There's some issues with what you're trying to do. First you shouldn't be setting the content of a view in your destination view controller in prepareForSegue. You can calculate the value, and then pass it as Phillip suggested. First you'll have to calculate it. One other issue is that you can't run mathematical operators on text, which is what it looks like you're trying to do. You can cast a String into an Int or a Double, and it will return as optional just in case the text doesn't actually contain a number. It would be safest to always conditionally unwrap, but I think for your case you could do something like add an extension on String to return either the non-optional double value of the text, or zero if it's nil (that way it wouldn't have any impact on the result). So add this to your project outside of any classes:

extension String {
func doubleValue() -&gt; Double {
return Double(self) ?? 0
}
}

Now in your first VC, you can add this function below to do your calculation. I'm going to assume that you left some code out, because in the code you provided you haven't declared a lot of these different labels and textFields (dNTPsVolumeLabel, forwardPrimerLabel, etc). So assuming you already have those as a part of your first VC, something like this should work fine:

func getWaterVolumeLabelText() -&gt; String? {
numberOfSamplesTextField.text?.doubleValue() * (50.0 - dNTPsVolumeLabel.text?.doubleValue() - forwardPrimerLabel.text?.doubleValue() - reversePrimerLabel.text?.doubleValue() - dnaPolymeraseLabel.text?.doubleValue() - volumeOfTemplateDNAtextfield.text?.doubleValue() - bufferVolumeLabel.text?.doubleValue())
}

Now you have a function that will run your calculation for you when the segue is fired. All you have to do is pass it to the destination ViewController. The easiest way to do this would be to just add a string property in your destination view controller, something like this:

class MasterMixTableViewController: UIViewController{
// This is would be your label in your destination view controller
@IBOutlet weak var waterVolumeLabel: UILabel!
// Add this
public var waterVolumeText: String?
override func viewWillAppear(_ animated: Bool) {
// Here you can do whatever with the passed-in string
waterVolumeLabel.text = waterVolumeText
}
}

Now go back to the prepare for segue method in your SelectAttributesViewController and just change it to this:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let masterMix = segue.destination as! MasterMixTableViewController
masterMix.loadViewIfNeeded()
// This will pass the value along
masterMix.waterVolumeText = getWaterVolumeLabelText()
}

huangapple
  • 本文由 发表于 2020年1月6日 02:36:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/59603021.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定