正如标题所述,由于某种原因,以下(简化)代码不起作用:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
updateTable每当用户编辑一个UITextField调用时localPlaces,我就会调用,调用哪个调用调用google的在线位置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.
}
}
Run Code Online (Sandbox Code Playgroud)
Duncan C的答案中的解释不适合这种情况.
在参考cancelPreviousPerformRequests(withTarget:selector:object:):
讨论
取消所有执行请求,其目标与
aTarget,参数anArgument和选择器相同aSelector.
所以,当你有一条像:
<aTarget>.perform(<aSelector>, with: <anArgument>, afterDelay: someDelay)
Run Code Online (Sandbox Code Playgroud)
你可以用以下方法取消它:
NSObject.cancelPreviousPerformRequests(withTarget: <aTarget>, selector: <aSelector>, object: <anArgument>)
Run Code Online (Sandbox Code Playgroud)
只有当所有的3样东西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)
}
}
Run Code Online (Sandbox Code Playgroud)