CoreData应用UI活动指示器不显示的解决

来源:互联网 发布:破解windows开机密码 编辑:程序博客网 时间:2024/05/22 10:55

一只简单的CoreData应用,UI界面左上角按钮触发一段耗时的代码,App本意是在执行耗时代码时将按钮暂时变为一个活动指示器,等到代码运行完毕再恢复原来的按钮.但是App运行时活动指示器从未显示过!

这是一个典型的主线程阻塞的情况,因为添加活动指示器是一个UI操作,所以它会被耗时操作阻塞,它会被执行,但没有效果(或者说结果未定义,在这里就是没有效果):

func handle(){    navigationItem.leftBarButtonItem = activityIndicatorBarButtonItem()//耗时的CoreData操作self.navigationItem.leftBarButtonItem = self.exportBarButtonItem()}

我们下意识的做法是将耗时操作放到非main队列中去,like this:

func handle(){    navigationItem.leftBarButtonItem = activityIndicatorBarButtonItem()    DispatchQueue.global().async {        //耗时的CoreData操作        DispatchQueue.main.async{            self.navigationItem.leftBarButtonItem = self.exportBarButtonItem()        }    }}

这样执行下来貌似没有问题,但实际上你在私有queue执行的context没有跨线程的安全性!

来看一下我们是如何创建context对象的:

lazy var context: NSManagedObjectContext = {    var managedObjectContext = NSManagedObjectContext(      concurrencyType: .mainQueueConcurrencyType)    managedObjectContext.persistentStoreCoordinator = self.psc    return managedObjectContext    }()

注意我们使用的选项是在main队列上的并发!

这就是私有context的用途了,我们可以临时创建一个在私有队列上运行的context来解决此问题:

func handle(){    navigationItem.leftBarButtonItem = activityIndicatorBarButtonItem()        let privateContext = NSManagedObjectContext(concurrencyType: .privateQueueConcurrencyType)        privateContext.persistentStoreCoordinator = coreDataStack.context.persistentStoreCoordinator        privateContext.perform {            //耗时的CoreData代码            DispatchQueue.main.async{            self.navigationItem.leftBarButtonItem = self.exportBarButtonItem()        }    }}
0 0
原创粉丝点击