我使用UIProgressView
并使用observedProgress
属性。然后我有一个观察到的Progress
类型的变量。
现在我在后台线程上写入Core Data,然后更新completedUnitCount
但它崩溃了。
以下是代码:
var downloadProgress: Progress
init() {
downloadProgress = Progress()
}
func saveStuff() {
let stuff: [[String: Any]] = //some array of dictionaries
downloadProgress.totalUnitCount = Int64(stuff.count)
persistentContainer.performBackgroundTask { (context) in
for (index, item) in stuff.enumerated() {
// create items to be saved
context.perform {
do {
try context.save()
self.downloadProgress.completedUnitCont = Int64(index + 1)
} catch {
// handle error
}
}
}
}
}
所以它在self.downloadProgress.completedUnitCont = Int64(index + 1)
线上崩溃了。我在写这篇文章时意识到我应该使用weak
或unowned
self来停止保留周期,但还有其他问题吗?
答案 0 :(得分:3)
所有与UI相关的代码都必须从主线程执行,因此您必须将调用self.downloadProgress.completedUnitCont = Int64(index + 1)
分派给主线程。像这样:
DispatchQueue.main.async {
self.downloadProgress.completedUnitCont = Int64(index + 1)
}
答案 1 :(得分:1)
在主线程以外的线程上更新UI是一个常见错误,可能导致错过UI更新,视觉缺陷,数据损坏和崩溃。
因此,无论何时在后台线程上执行任何任务并且需要在此过程中进行任何ui更新,请使用以下块中的所有代码。
private bool IsTokenValid(HttpContextBase httpContext)
{
var username = httpContext.User.Identity.Name;
var userTokens = UserAccessToken.Instance.UserDictionary;
var tokenToAccess = httpContext.Request.Headers["Authorization"];
tokenToAccess = tokenToAccess.Replace("Bearer ", "");
if (userTokens.ContainsKey(username))
{
var token = userTokens[username];
if (token == tokenToAccess) return true;
}
return true;
}