从后台线程更新UIProgressView进度

时间:2018-04-19 10:04:03

标签: ios swift core-data

我使用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)线上崩溃了。我在写这篇文章时意识到我应该使用weakunowned self来停止保留周期,但还有其他问题吗?

2 个答案:

答案 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;
    }