Core Data 多线程操作实战篇

最近在解决百度音乐iPhone客户端偶现数据库操作crash的问题,顺手整理了下CoreData的多线程原则,以及实际开发时应该如何遵守这些原则。

Core Data多线程操作的基本原则

  1. 不允许跨线程访问MOC: 在某一个MOC上的CRUD操作只能在它的操作线程上进行
  2. 不允许跨线程访问MO:对MO的操作只能在它所属的MOC的操作线程上进行。需要注意的是,访问一个FRC的fetchedObjects数组也只能在FRC所属的MOC的操作线程上进行

Core Data的新版本

所谓的新版本,其实是从iOS 5.0就开始支持了。新版本的Core Data废弃了confinement context,替代它的是queue context。这两种context的区别在于,使用confinement context必须自己保证CRUD操作只在创建它的线程上执行,也就是说创建这个confinement context的线程就是它的操作线程。 而使用queue context则只需要用-performBlock:或者-performBlockAndWait:方法执行CRUD操作,这些操作都被dispatch到context持有的serial _dispatchQueue上执行。

Magical Record的新版本(coming soon)

根据Magical Record的说明,从3.0版本起,MagicalRecord中的-MR_contextForCurrentThread将被弃用。刚开始我没想清楚其中的原因,后来通过在github上提问,Magical Record的维护者之一tonyarnold给出的原因是:

  1. Core Data已经废弃了confinement context
  2. Core Data中新的queue context内部使用serial dispatch_queue来保证线程安全
  3. MR中的-MR_contextForCurrentThread方法是把一个queue context存储在一个thread的字典里。这样会导致调用这个方法的线程一定不是queue context的操作线程.

我是这么理解的:

  1. 我们使用-MR_contextForCurrentThread这个方法通常的习惯是,拿到这个方法返回的context之后,直接在这个context上进行CRUD操作。这在旧版本使用confinement context的Core Data是没有问题的。因为这个confinement context的创建线程就是它的合法操作线程
  2. 对于queue context, 如果我们继续按照1中的方式使用这个context是有问题。原因就是tonyarnold给出的第三点。正确的做法应该是把CRUD操作都放在-performBlock:-performBlockAndWait:
  3. 我认为,如果我们能用正确的方式使用-MR_contextForCurrentThread方法返回的context, 那么是没有问题的

App中应该如何遵守Core Data的多线程操作原则

如果你App也使用了Magical Record, 那么建议你按照官方说明上的方式替换掉它打算废弃的API。比如用每次创建一个新的-MR_context的方式来替换掉-MR_contextForCurrentThread的使用。

下面是我在修改百度音乐iPhone客户端的数据库操作时总结的几个方法:

  1. 每个入参有MO的方法

    1. 自己保证(不是由调用者保证)对MO的访问和修改在MO.managedObjectContext的操作线程上执行
    2. 此方法应该仅把DB操作放在MO.managedObjectContext的操作线程上。 这么要求是为了避免修改数据库操作之外的任务的线程安排
    3. 注意,不要把FRC.fetchedObjects作为参数传递。对这个数组做遍历、或者取大小等的操作必须要在FRC.managedObjectContext中进行,而仅由传入的FRC.fetchedObjects无法获取此信息
  2. MO的category中的方法
    1. -方法,没有必要用-performBlock:-performBlockAndWait:包起来。因为调用者应该有这样的意识:对MO的操作需要在它所属的MOC上进行。这点和CoreData的要求是一致的
    2. +方法需要自己保证不违反线程操作原则。 这点和MagicalRecord保持一致

Core Data有关的Debug方式

  • -com.apple.CoreData.ConcurrencyDebug 3
  • -com.apple.CoreData.SQLDebug 3
  • -com.apple.CoreData.SyntaxColoredLogging YES

转载于:https://www.cnblogs.com/mindyme/p/5089454.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/404424.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分布式系统和元数据

------俗解:---------------------------------------------------- 什么是分布式系统: 1:通俗点说分布式系统就是能把服务器端程序分开部署到多台机器上。 2:跟分层毫无关系, 跟它容易搞混的是集群 分布式就是把一个系统分布在不…

移植gdb到DM368 IPNC中 linux arm gdb

From: http://blog.csdn.net/ghostyu/article/details/8081897 移植gdb到嵌入式的ipnc中,大多数人习惯使用printf调试,但是遇到像”segment fault“这的错误也是后就很难定位,这时候gdb的作用就体现出来了 在pc使用gdb调试应用程序前&…

[react] react是哪个公司开发的

[react] react是哪个公司开发的 facebook 个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

Silverlight实用窍门系列:56.Silverlight中的Binding使用(一)【附带实例源码】

本文将详细讲述Silverlight中Binding,包括Binding的属性和用法,Binding的数据流向。 Binding:一个完整的Binding过程是让源对象中的某个属性值通过一定流向规则进行转换和验证之后绑定到目标对象的某个属性上面。这个源对象由ElementName指定&#xff0c…

linux下如何产生core,调试core

From: http://blog.163.com/redhumor126/blog/static/19554784201131791239753/ 在程序不寻常退出时,内核会在当前工作目录下生成一个core文件(是一个内存映像,同时加上调试信息)。使用gdb来查看core文件,可以指示出…

[react] react中怎样阻止组件渲染?

[react] react中怎样阻止组件渲染? class组件 使用shouldComponentUpdate生命周期,return false继承React.PureComponent只要prop没有改变(浅比较),就不会执行render函数 函数式组件 使用React.memo包裹组件函数,props没有改变就…

嵌套滚动demo

https://github.com/luv135/NestedScrollingDemo https://github.com/ggajews/nestedscrollingchildviewdemo ViewParentCompat是一个和父view交互的兼容类,它会判断api version,如果在Lollipop以上,就是用view自带的方法,否则判断…

jqGrid + JSON + WebService 完整示例

真没找到这样的例子,于是自已写了个,分享出来。 第一步,首先在WebService上,添加[System.Web.Script.Services.ScriptService]属性标签,让WebServer支持JSON. namespace jqGrid_JSON_WebService_Sample.Services{/// &…

[react] 在react中页面重新加载时怎样保留数据?

[react] 在react中页面重新加载时怎样保留数据? 使用浏览器localstorage来保存应用程序的状态 个人简介 我是歌谣,欢迎和大家一起交流前后端知识。放弃很容易, 但坚持一定很酷。欢迎大家一起讨论 主目录 与歌谣一起通关前端面试题

Sublime Text 3 代码格式化插件推荐 CodeFormatter

CodeFormatter CodeFormatter has support for the following languages: * PHP - By PHP_Beautifier* JavaScript/JSON - By JSBeautifier* HTML - By JSBeautifier* CSS - By JSBeautifier* Python - By PythonTidy (only ST2) 支持,php,js,html,css 默认快捷键 …

[react-router] React-Router 4中<Router>组件有几种类型?

[react-router] React-Router 4中<Router>组件有几种类型&#xff1f; HashRouter&#xff1a;老浏览器的history,主要通过hash来实现&#xff0c;对应createHashHistory()BrowserRouter&#xff1a;高版本浏览器,通过html5里面的history&#xff0c;对应createBrowserH…

交叉编译和交叉调试环境搭建及使用

From: http://blog.chinaunix.net/uid-25119314-id-226230.html 1. 交叉编译器 1.1 交叉编译器介绍 在一种计算机环境中运行的编译程序&#xff0c;能编译出在另外一种环境下运行的代码&#xff0c;我们就称这种编译器支持交叉编译。这个编译过程就叫交叉编译。简单地说&…

struts2文件上传中,如何限制上传的文件类型

这个在struts2的doc中已经有所说明&#xff0c;但是说得并不详细,而且他给的例子是有错误的&#xff0c;下面我将列出文件上传并限制类型的具体步骤struts2版本是2.1.6struts2是根据contentType来限制的&#xff0c;并不是文件的扩展名比如我想仅上传image/png,image/gif,image…

CGContextRef CIImageRef详解

第一种 先用UIImage对象加载一张图片 然后转化成CGImageRef放到CGContext中去编辑 第二种 用CGImageCreate函数创建CGImageRef 然后把CGImageRef放到CGContext中去编辑 第三种 用CGImageCreateCopy 或者 CGImageCreateCopyWithColorSpace 函数拷贝 CGImageRef CGImageCreate ( …

[react] react怎么拿到组件对应的DOM元素?

[react] react怎么拿到组件对应的DOM元素&#xff1f; 在Class组件中 import React from react; class CComponent extends React.Component {refDiv React.createRef();componentDidMount () {console.log(this.refDiv.current)}render () {return <div><div class…

linux缩小lv发生文件系统错误

众所周知&#xff0c;linux lvm 扩大lv是先扩大lv&#xff0c;然后再扩大文件系统&#xff0c;所以有的人就认为缩小lv也是先缩小lv,再缩小文件系统&#xff0c;当然博主刚开始也那么认为&#xff0c;导致lvresize 以后&#xff0c;lv的大小小于文件系统大小而无法挂载&#xf…

Fedora12上编译安装gdb-7.2

在Fedora12上编译安装gdb-7.2&#xff1a;编译安装gdb和gdbserver 1. 下载gdb7.2: ftp://sourceware.org/pub/gdb/releases/gdb-7.2a.tar.bz2 2. 编译安装gdb 2.1 解压&#xff1a; [zcm~ #1]$cd /mnt/hgfs/opensource/ [zcmopensource #2]$ls a52dec ffmpeg-1.2…

[react-router] react的路由和普通路由有什么区别?

[react-router] react的路由和普通路由有什么区别&#xff1f; React路由是前端的路由&#xff0c;普通路由指的是后端的路由React路由不管是hash还是browser的模式&#xff0c;都是在响应了hash/browser的change之后&#xff0c;再变更页面的DOM结构&#xff0c;由于是单页应…

UITableView 性能优化

网络图片异步加载&#xff0c;SDWebImage。文字直接 drawInRect/drawAtPoint 绘制&#xff0c;参考 ABTableViewCell&#xff0c;AdvancedTableViewCells。本地图片也可以直接绘制&#xff0c;或者用 CALayer 来添加显示。cell 重用机制。cell 内容尽量避免透明效果。如非必要&…

Hello Views之Spinner(yaozq翻译,仅供参考)

Spinner是一种类似于下拉列表的widget。 在这个教程中&#xff0c;你将创建一个简单的用于展示星球列表的spinner组件。当选择列表中的一项时&#xff0c;将会弹出一个表示所选项的toast信息。下面是具体步骤&#xff1a; 1&#xff0c;新建一个名为HelloSpinner的项目。 2&…