如标题所述,由于某种原因,以下(简化)代码无法正常工作:
extension InputView: {
func updateTable(text: String) {
NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(loadPlaces(text:)), object: nil)
//NSObject.cancelPreviousPerformRequests(withTarget: self)
self.perform(#selector(loadPlaces(text:)), with: text, afterDelay: 0.5)
prevSearch = inputField.text!;
}
//Private wrapper function
@objc private func loadPlaces(text: String) {
print("loading results for: \(text)")
// locator?.searchTextHasChanged(text: text)
}
}
每当用户编辑
updateTable
时,我都会调用UITextField
,后者会调用localPlaces
,后者会调用查询Google的在线places API(已注释掉)的函数。不幸的是,每次调用updateTable之后,都会调用loadPlaces中的打印行。从我的目视检查来看,似乎实际上是对打印语句的延迟,但是旧的调用不会取消。我尝试查看许多StackOverflow线程,但是找不到Swift 3的更新内容。我打错了吗?PS。如果我改用注释掉的单参数
cancelPreviousPerformRequests
。它因某些原因起作用。编辑:我已经能够在一个单独的项目中复制此错误。因此,我100%确信上面的代码是错误的。如果您想复制此错误,请打开一个新的iOS项目,并将以下代码粘贴到默认的
ViewController
中:class InputView: UIView {
func updateTable(text: String) {
NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(loadPlaces(text:)), object: nil)
self.perform(#selector(loadPlaces(text:)), with: text, afterDelay: 0.5)
}
//Private wrapper function
@objc private func loadPlaces(text: String) {
print("loading results for: \(text)")
// locator?.searchTextHasChanged(text: text)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let input = InputView()
for i in 0..<200 {
input.updateTable(text: "Call \(i)")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
最佳答案
Duncan C的答案中的解释不适用于这种情况。
在 cancelPreviousPerformRequests(withTarget:selector:object:)
的引用中:
讨论区
具有与aTarget
相同的目标,与anArgument
相同的参数以及与选择器相同的目标的所有执行请求都被取消。aSelector
。
所以,当你有这样的一行:
<aTarget>.perform(<aSelector>, with: <anArgument>, afterDelay: someDelay)
您可以使用以下方法取消它:NSObject.cancelPreviousPerformRequests(withTarget: <aTarget>, selector: <aSelector>, object: <anArgument>)
仅当aTarget
,aSelector
和anArgument
都匹配时。请尝试执行以下操作,然后查看您看到的内容:
class InputView: UIView {
var lastPerformArgument: NSString? = nil
func updateTable(text: String) {
NSObject.cancelPreviousPerformRequests(withTarget: self, selector: #selector(loadPlaces(text:)), object: lastPerformArgument)
lastPerformArgument = text as NSString
self.perform(#selector(loadPlaces(text:)), with: lastPerformArgument, afterDelay: 0.5)
}
//Private wrapper function
@objc private func loadPlaces(text: String) {
print("loading results for: \(text)")
// locator?.searchTextHasChanged(text: text)
}
}