我收到以下警告:
SWIFT任务继续误用:saveAndClose()泄露了它的续篇!
在for循环中,在执行了几个项目之后,在其中一个项目处,在保存和关闭函数中,它被阻塞,并表示上面的错误,并且不移动到下一个项目,因此无法返回结果。
这里可能有什么问题,有什么方法可以优化这些片段吗?
private func processTags(reqItems: [FTShelfItemProtocol], selectedTags: [String]) async throws -> FTShelfTagsResult { let items: [FTDocumentItemProtocol] = reqItems.filter({ ($0.URL.downloadStatus() == .downloaded) }).compactMap({ $0 as? FTDocumentItemProtocol })
var totalTagItems: [FTShelfTagsItem] = [FTShelfTagsItem]()
for case let item in items where item.documentUUID != nil {
guard let docUUID = item.documentUUID else { continue }//, item.URL.downloadStatus() == .downloaded else { continue }
let destinationURL = FTDocumentCache.shared.cachedLocation(for: docUUID)
print(destinationURL.path)
// move to post processing phace
do {
let document = await FTNoteshelfDocument(fileURL: destinationURL)
let isOpen = try await document.openDocument(purpose: FTDocumentOpenPurpose.read)
if isOpen {
let tags = await document.documentTags()
let considerForResult = selectedTags.allSatisfy(tags.contains(_:))
if considerForResult && !tags.isEmpty {
var tagsBook = FTShelfTagsItem(shelfItem: item, type: .book)
tagsBook.tags = tags
totalTagItems.append(tagsBook)
}
}
let tagsPage = await document.fetchSearchTagsPages(shelfItem: item, selectedTags: selectedTags)
totalTagItems.append(contentsOf: tagsPage)
_ = await document.saveAndClose()
} catch {
cacheLog(.error, error, destinationURL.lastPathComponent)
}
}
cacheLog(.success, totalTagItems.count)
let result = FTShelfTagsResult(tagsItems: totalTagItems)
return result
}
func saveAndClose() async -> Bool {
return await withCheckedContinuation({ continuation in
self.saveAndCloseWithCompletionHandler { isSuccess in
continuation.resume(returning: isSuccess)
}
})
}
func saveAndCloseWithCompletionHandler(_ onCompletion :((Bool) -> Void)?)
{
FTCLSLog("Doc: Save and Close");
self.prepareForClosing();
self.saveDocument { (saveSuccess) in
if(saveSuccess) {
self.closeDocument(completionHandler: { (_) in
onCompletion?(saveSuccess);
});
}
else {
onCompletion?(saveSuccess);
}
}
}
需要修复以避免-
SWIFT任务继续误用:saveAndClose()泄露了它的续篇!
并在执行for循环的所有项后正确返回result。
1条答案
按热度按时间lf3rwulv1#
考虑错误:
SWIFT任务继续误用:saveAndClose()泄露了它的续篇!
这意味着您有一些从未调用其完成处理程序的执行路径,因此延续被泄露。(这并不是说您调用了完成处理程序太多次,因为这是不同的错误消息。)
我没有看到一个明显的执行路径,其中忽略了调用完成处理程序。到目前为止,您与我们分享的代码中似乎没有问题:但是您也有自定义方法,这些方法有自己的完成处理程序,例如
saveDocument
和closeDocument
,您没有与我们共享,所以可能其中一个方法有一个执行路径,它无法调用其完成处理程序。因此,我们不能确切地说你的问题在哪里。但是,底线是,您可能没有在某处调用完成处理程序。您可能需要插入一些日志记录语句和/或断点,并查看是否可以诊断在哪里未能调用相关的完成处理程序。考虑这个问题的可重复的例子。下面的基于completion-handler的例程在1秒后返回某个数字的平方根(我只是模拟一些遗留的异步进程):
显然,我不想计算负数的平方根。但是上面的描述是不正确的,因为不是每个执行路径都会调用它的完成处理程序。(这是我们更喜欢Swift并发而不是完成处理程序模式的原因之一,因为这个问题不会在原生Swift并发代码中发生。
无论如何,让我们假设我们为这个遗留函数编写了一个
async
Package 器:如果我用一个正值调用它,一切都很好:
但是如果我用一个负值调用它,我会得到“leaked its continuation”错误(因为我的遗留函数有一个错误,只有在值为正时才调用闭包):
显然,解决方法是每个执行路径都必须调用其完成处理程序。