ios - 如何快速终止操作?

标签 ios swift

我想终止操作并隐藏键盘,以便用户在多次按下计算按钮时可以获得相同的结果。我的代码如下

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!

    @IBOutlet weak var result: UILabel!
    var myArray = [Int]() // empty array of int

    func convert(a:Character) -> Int {
        if (a == "1") {
           return 1;
        }
        else {
            return 0;
        }            
    }

    func power(a:Int , b:Int) -> Int {
        var result = 1
        for var i = 0; i < b; i++ {
            result *= a
        }
        return result
    }

    @IBAction func binaryNumber(sender: AnyObject) {
        var text = textField.text.toInt() // for checking whether or not user left the textfield empty
        if text != nil {            
            for  i in textField.text {
                myArray += [convert(i)]                
            }

            var exponent =  myArray.count - 1;

            //Multiplying binary number with power of 2
            for var i = 0; i < myArray.count; i++ {
                var base = 2;
                myArray[i] = myArray[i] * power(base, b: exponent)
                exponent--
            }

            // add up
            var sum = 0
            for var i = 0; i < myArray.count; i++ {
                sum += myArray[i]
            }

            result.text = "\(sum)"
        }
        else {
          result.text = "Please enter binary number"
        }            
    }

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {            
        self.view.endEditing(true)
    }
}

最佳答案

在我原来的回答(在这个问题的末尾),我回答了一个更复杂的问题,即如何终止一个耗时的计算。

但是,正如 Sultan 指出的那样,您可能会问一个简单得多的问题,即如何重新计算,以便在您第二次计算时得到相同的结果。

问题的根源在于您定义了 myArray成为一个属性(在调用 binaryNumber 之间持续存在),而它应该是 binaryNumber 内部的局部变量.

例如:

// do not define `myArray` here:
//
// var myArray = [Int]()

@IBAction func binaryNumber(sender: AnyObject) {

    // instead, define it here:

    var myArray = [Int]()

    // now the rest of your method continues as before 

    var text = textField.text.toInt() // for checking whether or not user left the textfield empty
    if text != nil {            
        for  i in textField.text {
            myArray += [convert(i)]                
        }

        var exponent =  myArray.count - 1;

        //Multiplying binary number with power of 2
        for var i = 0; i < myArray.count; i++ {
            var base = 2;
            myArray[i] = myArray[i] * power(base, b: exponent)
            exponent--
        }

        // add up
        var sum = 0
        for var i = 0; i < myArray.count; i++ {
            sum += myArray[i]
        }

        result.text = "\(sum)"
    }
    else {
      result.text = "Please enter binary number"
    }            
}

或者,您可以离开 myArray作为属性(property),但随后改变binaryNumber手动重置它:

@IBAction func binaryNumber(sender: AnyObject) {
    myArray = [Int]()

    // the rest of your method here
}

就我个人而言,我更喜欢前一种方法(将 myArray 改为局部变量;它解决了问题并避免了意外后果),但任何一种方法都可以解决您的问题。

顺便说一句,下面是我最初的回答,讨论了如何取消长时间运行的操作。

--

几个想法:

  1. 如果你想取消一个操作,添加一个 bool 属性来指示它是否被取消,并在计算循环中检查该变量的状态以确定是否中止计算。

  2. 不过,要使其正常工作,您确实必须在后台线程中进行该计算。因此后台线程将进行计算,主线程将处理 UI 以及启动/取消计算操作。

  3. 一个优雅的模式是将计算包装在 NSOperation 中具有现有 cancelled 的子类您可以检查并确定是否要取消操作的属性。

    因此,将计算包装在 NSOperation 中:

    class CalculationOperation : NSOperation {
    
        var inputString: String
        var completionHandler: (Int)->()
    
        init(string: String, completion: (Int)->()) {
            inputString = string
            self.completionHandler = completion
    
            super.init()
        }
    
        func convert(character: Character) -> Int {
            if character == "1" {
                return 1
            } else {
                return 0
            }
        }
    
        override func main() {
            // get the array of numeric values for the characters
    
            let digitValues = inputString.characters.map { convert($0) }
    
            // convert to binary
    
            var sum = 0
            var exponent = digitValues.count - 1;
    
            for var i = 0; i < digitValues.count; i++ {
                if cancelled { return }            // check to see if the user canceled the operation, and if so, quit
    
                let digit = digitValues[i]
                let value = digit * 1 << exponent  // using bitwise shift is more efficient than `power`
                sum += value
                exponent--
            }
    
            dispatch_async(dispatch_get_main_queue()) {
                self.completionHandler(sum)
            }
        }
    }
    

    然后是你的IBAction可以将此操作添加到 NSOperationQueue为了在后台执行操作,首先取消对该队列的任何其他操作:

    lazy var queue = NSOperationQueue()
    
    @IBAction func binaryNumber(sender: AnyObject) {
        textField.endEditing(true)
    
        queue.cancelAllOperations()
    
        let operation = CalculationOperation(string: textField.text!) { result in
            self.resultLabel.text = "\(result)"
        }
        queue.addOperation(operation)
    }
    
  4. 对了,上面NSOperation中的二进制转换例程使用函数式编程可以使子类更加高效:

    override func main() {
        let digitValues = inputString.characters.map { convert($0) }
        let binaryValue = digitValues.reduce(0) { $0 << 1 + $1 }
    
        dispatch_async(dispatch_get_main_queue()) {
            self.completionHandler(binaryValue)
        }
    }
    

    不过请注意,map 的这些功能方法和 reduce没有“取消”功能,但它们非常高效,我认为您永远不需要。无论如何,如果你实现了 main这样,您就可以在启动操作时消除对取消逻辑的需求。

  5. 我不会检查用户是否输入了有效的二进制数,而是确保他们只能输入数字 01在开始的文本字段中。只需将 View Controller 指定为 UITextField 的委托(delegate)即可, 然后实现 shouldChangeCharactersInRange只接受二进制数字。

    let nonBinaryCharacterSet = NSCharacterSet(charactersInString: "01").invertedSet
    
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        if string.rangeOfCharacterFromSet(nonBinaryCharacterSet) != nil {
            return false
        } else {
            return true
        }
    }
    
  6. 正如您将在上面看到的,您不需要编写 power方法。有一个内置函数,pow已经这样做了。或者您可以使用位移运算符 << ,这是计算二进制指数的有效方法。例如。 2 的四次方可以表示为 1 << 4 .

关于ios - 如何快速终止操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32911087/

相关文章:

iphone - 从带有自定义单元格的 UITableView 内的 UITextView 打开键盘时避免查看

ios - 为什么 label.text 更新没有反射(reflect)在屏幕上?

ios - 如何防止 UITextView 文本在打字时移动到顶部?

ios - Skoobler界面导航

ios - 实例变量在 ViewDidLoad() 处重置为 nil

swift - 将大 Storyboard拆分为单独的子 Storyboard

javascript - 如何在循环时忽略特定值

java - Java 如何解决 Swift 旨在解决的类初始化问题?

ios - 在快速编程语言中隐藏文本字段的键盘

Objective-c 用它的后代类型覆盖委托(delegate)