我想终止操作并隐藏键盘,以便用户在多次按下计算按钮时可以获得相同的结果。我的代码如下
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
改为局部变量;它解决了问题并避免了意外后果),但任何一种方法都可以解决您的问题。
顺便说一句,下面是我最初的回答,讨论了如何取消长时间运行的操作。
--
几个想法:
如果你想取消一个操作,添加一个 bool 属性来指示它是否被取消,并在计算循环中检查该变量的状态以确定是否中止计算。
不过,要使其正常工作,您确实必须在后台线程中进行该计算。因此后台线程将进行计算,主线程将处理 UI 以及启动/取消计算操作。
一个优雅的模式是将计算包装在
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) }
对了,上面
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
这样,您就可以在启动操作时消除对取消逻辑的需求。我不会检查用户是否输入了有效的二进制数,而是确保他们只能输入数字
0
和1
在开始的文本字段中。只需将 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 } }
正如您将在上面看到的,您不需要编写
power
方法。有一个内置函数,pow
已经这样做了。或者您可以使用位移运算符<<
,这是计算二进制指数的有效方法。例如。 2 的四次方可以表示为1 << 4
.
关于ios - 如何快速终止操作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32911087/