Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

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

$
0
0

一只简单的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()
        }
    }
}
作者:mydo 发表于2017/1/6 8:23:52 原文链接
阅读:12 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>