gpt4 book ai didi

ios - swift |强制取消执行代码

转载 作者:搜寻专家 更新时间:2023-11-01 06:12:56 25 4
gpt4 key购买 nike

I know there have been I would say similar questions, but none of them fits my case -> see my already tried attempts below.

所以我想做的是制作一个高级搜索栏。因此,每次 searchParam 更改时,我都需要执行代码来检查我的 TableViewItems(数组)是否符合条件 -> 过滤器。

当 smo.例如输入 3 个字符,我的代码检查这个字符串。但这需要一段时间才能获得所有结果。

问题:当 smo。然后键入第 4 个字符,我想停止之前的执行并开始一个新的字符串 4。


我的尝试:

  • 使用 DispatchWorkItem:

    这里的问题是它只改变了一个 bool 值,代码需要 10 秒以上的时间才能识别它改变了。如果我执行 .sync 而不是 .async 就可以工作,但它会使应用卡住超过 10 秒

  • 使用 DispatchQueue:

    无法停止,只能暂停 -> 所以会保留在内存中 -> 会垃圾内存

  • 在每个 for 循环 中检查 bool 值:

    与 DispatchWorkItem 相同,需要 10 秒以上才能识别更改


当前代码:(不是很重要)

func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
self.stop = true
if people != nil {

if searchText.isEmpty {
searchedPeople = people
self.stop = false
} else {
self.searchedPeople = []
self.tableView.reloadData()
workItem = DispatchWorkItem(qos: .userInitiated, flags: []) {
outter: for i in 0...searchText.count - 1 {
if self.stop { self.stop = false;break outter } //
if i == 0 {
inner: for person in self.people! {
if self.stop { self.stop = false;break outter } //
let name = (person.Vorname != nil ? person.Vorname! + " " : "") + (person.Nachname ?? "")
if name.lowercased().contains(searchText.lowercased()) {
print("Found: \(name), \(searchText), Exact Match")
self.searchedPeople?.append(person);DispatchQueue.main.async { self.tableView.reloadData()}; continue inner
}
}
} else {
let firstP = searchText.prefix(i+1)
let lastP = searchText.suffix(searchText.count - i + 1)

inner2: for person in self.people! {
if self.stop { self.stop = false;break outter } //
let name = (person.Vorname != nil ? person.Vorname! + " " : "") + (person.Nachname ?? "")
if name.lowercased().contains(firstP.lowercased()) && (name.lowercased().contains(lastP.lowercased())) {
print("Found: \(name), \(searchText), First: \(firstP), Last: \(lastP)")
self.searchedPeople?.append(person)
DispatchQueue.main.async { self.tableView.reloadData()}
continue inner2
}
}
}
}
}
//execute
DispatchQueue.async(execute: workItem)

}
}
}

最佳答案

从本质上讲,您的问题是,当您应该检查本地状态时,您却在检查全局状态。假设您正在进行操作“L”,并且您刚刚键入了“e”,因此操作“Le”将开始。这是大致发生的事情:

func updateMyPeepz() {
// At this point, `self.workItem` contains operation 'L'

self.workItem.cancel() // just set isCancelled to true on operation 'L'
self.workItem = DispatchWorkItem { /* bla bla bla */ }
// *now* self.workItem points to operation 'Le'!
}

稍后,在操作“L”的工作项中,您执行以下操作:

if self.workItem.isCancelled { /* do something */ }

不幸的是,此代码在操作“L”中运行,但 self.workItem 现在指向操作“Le”!因此,当操作“L”被取消而操作“Le”没有被取消时,操作“L”会看到 self.workItem——即操作“Le”——没有被取消。因此,检查始终返回 false,并且操作“L”实际上从未停止。

当您使用全局 bool 变量时,您会遇到同样的问题,因为它是全局的,并且不会区分应该仍在运行的操作和不应该运行的操作(除了原子性问题之外,您已经如果您不使用信号量保护变量,将要介绍)。

修复方法如下:

func updateMyPeepz() {
var workItem: DispatchWorkItem? = nil // This is a local variable

self.currentWorkItem?.cancel() // Cancel the one that was already running

workItem = DispatchWorkItem { /* bla */ } // Set the *local variable* not the property

self.currentWorkItem = workItem // now we set the property
DispatchQueue.global(qos: whatever).async(execute: workItem) // run it
}

现在,这是关键部分。在你的循环中,像这样检查:

if workItem?.isCancelled ?? false // check local workItem, *not* self.workItem!
// (you can also do workItem!.isCancelled if you want, since we can be sure this is non-nil)

在 workItem 的末尾,将 workItem 设置为 nil 以摆脱保留周期(否则会泄漏):

workItem = nil // not self.workItem! Nil out *our* item, not the property

或者,您可以将 [weak workItem] in 放在 workItem block 的顶部以防止循环——这样您就不必在结束了,不过你一定要用?? false 而不是 ! 因为你总是想假设一个弱变量可以随时变为 nil。

关于ios - swift |强制取消执行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51506072/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com