IOS数据存储之CoreData使用优缺点
前言:
学习了Sqlite数据之后认真思考了一下,对于已经习惯使用orm数据库的开发者或者对sql语句小白的开发者来说该如何做好数据库开发呢?这个上网搜了一下?看来总李多虑了!apple 提供了一种数据方式,它就是今天的主角:CoreData!我们一起来探究它是否能够满足我们项目开发的需要呢?
CoreData介绍:
Core Date是ios3.0后引入的数据持久化解决方案,它是是苹果官方推荐使用的,不需要借助第三方框架。Core Date实际上是对SQLite的封装,提供了更高级的持久化方式。在对数据库操作时,不需要使用sql语句,也就意味着即使不懂sql语句,也可以操作数据库中的数据。
CoreData优点:
Core Data实际上是将数据库的创建、表的创建、对象和表的转换等操作封装起来,极大的简化了我们的操作。Core Date与SQLite相比较,SQLite比较原始,操作比较复杂,使用的是C的函数对数据库进行操作,但是SQLite可控性更强,并且能够跨平台。
CoreData缺点:
存储性能一般,默认建立的表没有主键,效率低,复杂的查询更是不敢想像。CoreData 对批量数据的处理执行的不太好,查资料好像说IOS8推出了批量处理的一些方式。对于多线程的支持也不太好,我是xcode 7上开发的每一个entity都要生成4个类,打个比方一个项目中要建10个表那就要维护40个类,你说累不累?
怎么使用CoreData?
第一步:在项目中引入CoreData.framework
第二步:创建xxxx.xcdatamodeld
第三步:模型对象的实体
接下来就是具体实现:具体实现之前先来认识如下几个对象
(1)NSManagedObjectModel(被管理的对象模型)
相当于实体,不过它包含 了实体间的关系
(2)NSManagedObjectContext(被管理的对象上下文)
操作实际内容
作用:插入数据 查询 更新 删除
(3)NSPersistentStoreCoordinator(持久化存储助理)
相当于数据库的连接器
(4)NSFetchRequest(获取数据的请求)
相当于查询语句
(5)NSPredicate(相当于查询条件)
(6)NSEntityDescription(实体结构)
为了方便实现,本文整理一个数据管理类来测试CoreData:CoreDataManager
CoreDataManager.h
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h> @interface CoreDataManager : NSObject<NSCopying> @property(strong,nonatomic,readonly)NSManagedObjectModel* managedObjectModel;//管理数据模型 @property(strong,nonatomic,readonly)NSManagedObjectContext* managedObjectContext;//管理数据内容 @property(strong,nonatomic,readonly)NSPersistentStoreCoordinator* persistentStoreCoordinator;//持久化数据助理 //创建数据库管理者单例
+(instancetype)shareManager; //插入数据
-(void)insertData:(NSString*)tempName; //删除数据
-(void)deleteData; //删除数据
-(void)deleteData:(NSString*)tempName; //查询数据
-(void)queryData; //根据条件查询
-(void)queryData:(NSString*)tempName; //更新数据
-(void)updateData:(NSString*)tempName; @end
CoreDataManager.m
#import "CoreDataManager.h"
#import "Car.h" static CoreDataManager *shareManager=nil; @implementation CoreDataManager @synthesize managedObjectContext =_managedObjectContext; @synthesize managedObjectModel = _managedObjectModel; @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; //实例化对象
-(instancetype)init
{
self=[super init];
if (self) { }
return self;
} //创建数据库管理者单例
+(instancetype)shareManager
{
//这里用到了双重锁定检查
if(shareManager==nil){
@synchronized(self){
if(shareManager==nil){
shareManager =[[[self class]alloc]init];
}
}
}
return shareManager;
} -(id)copyWithZone:(NSZone *)zone
{ return shareManager;
} +(id)allocWithZone:(struct _NSZone *)zone
{
if(shareManager==nil){
shareManager =[super allocWithZone:zone];
}
return shareManager;
} //托管对象
-(NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel!=nil) {
return _managedObjectModel;
} NSURL* modelURL=[[NSBundle mainBundle] URLForResource:@"myCoreData" withExtension:@"momd"];
_managedObjectModel=[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
} //托管对象上下文
-(NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext!=nil) {
return _managedObjectContext;
} NSPersistentStoreCoordinator* coordinator=[self persistentStoreCoordinator];
if (coordinator!=nil) {
_managedObjectContext=[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];//NSMainQueueConcurrencyType NSPrivateQueueConcurrencyType [_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
} //持久化存储协调器
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator!=nil) {
return _persistentStoreCoordinator;
}
NSString* docs=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSURL* storeURL=[NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"myCoreData.sqlite"]];
NSLog(@"path is %@",storeURL);
NSError* error=nil;
_persistentStoreCoordinator=[[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"Error: %@,%@",error,[error userInfo]);
}
return _persistentStoreCoordinator;
} //插入数据
-(void)insertData:(NSString*)tempName
{
//读取类
Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext];
car.name=tempName;
//保存
NSError *error;
[self.managedObjectContext save:&error];
} //删除数据
-(void)deleteData
{
//创建读取类
NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接
NSFetchRequest* request=[[NSFetchRequest alloc] init];
[request setEntity:entity]; //启动查询
NSError *error;
NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error];
if(deleteArr.count){
for (Car *car in deleteArr) {
[self.managedObjectContext deleteObject:car];
}
NSError *error;
[self.managedObjectContext save:&error];
}else{
NSLog(@"未查询到可以删除的数据");
} } //删除数据
-(void)deleteData:(NSString*)tempName;
{
//创建读取类
NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接
NSFetchRequest* request=[[NSFetchRequest alloc] init];
[request setEntity:entity]; //创建检索条件
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName];
[request setPredicate:predicate]; //启动查询
NSError *error;
NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error];
if(deleteArr.count){
for (Car *car in deleteArr) {
[self.managedObjectContext deleteObject:car];
}
NSError *error;
[self.managedObjectContext save:&error];
}else{
NSLog(@"未查询到可以删除的数据");
}
} //查询数据
-(void)queryData
{
//创建读取类
NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接
NSFetchRequest* request=[[NSFetchRequest alloc] init];
[request setEntity:entity]; //启动查询
NSError *error;
NSArray *carArr=[self.managedObjectContext executeFetchRequest:request error:&error];
for(Car *car in carArr){
NSLog(@"car---->%@",car.name);
} } -(void)queryData:(NSString*)tempName
{
//创建读取类
NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接
NSFetchRequest* request=[[NSFetchRequest alloc] init];
[request setEntity:entity]; //创建检索条件
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName];
[request setPredicate:predicate]; //启动查询
NSError *error;
NSArray *carArr=[self.managedObjectContext executeFetchRequest:request error:&error];
for(Car *car in carArr){
NSLog(@"car---->%@",car.name);
} } //更新数据
-(void)updateData:(NSString*)tempName
{
//创建读取类
NSEntityDescription *entity =[NSEntityDescription entityForName:@"Car" inManagedObjectContext:self.managedObjectContext]; //创建连接
NSFetchRequest* request=[[NSFetchRequest alloc] init];
[request setEntity:entity]; //创建检索条件
NSPredicate *predicate =[NSPredicate predicateWithFormat:@"name=%@",tempName];
[request setPredicate:predicate]; //启动查询
NSError *error;
NSArray *deleteArr=[self.managedObjectContext executeFetchRequest:request error:&error];
if(deleteArr.count){
for (Car *car in deleteArr) {
car.name=@"test";
}
NSError *error;
[self.managedObjectContext save:&error];
}else{
NSLog(@"未查询到可以删除的数据");
} } @end
具体使用方式
//清空数据
[[CoreDataManager shareManager]deleteData];
//插入10条数据
for(int i=;i<;i++){
NSString *string = [[NSString alloc] initWithFormat:@"%d",i];
[[CoreDataManager shareManager]insertData:string];
}
//然后查询一下
[[CoreDataManager shareManager]queryData];
//然后删除一条数据
[[CoreDataManager shareManager]deleteData:@""];
//然后查询一下
[[CoreDataManager shareManager]queryData];
// 更新数据
[[CoreDataManager shareManager]updateData:@""];
//然后查询一下
[[CoreDataManager shareManager]queryData]; //清空数据
[[CoreDataManager shareManager]deleteData]; //然后查询一下
[[CoreDataManager shareManager]queryData];
测试一下效率:测试数据10000条
NSMutableArray *testArray =[[NSMutableArray alloc]init];
int testMaxCount =;
for(int i=;i<testMaxCount;i++){
NSString *string = [[NSString alloc] initWithFormat:@"%d",i];
[testArray addObject:string];
} //测试一下效率 第1种
CFAbsoluteTime start = CFAbsoluteTimeGetCurrent();
for(NSString *tempName in testArray){
[[CoreDataManager shareManager]insertData:tempName];
}
CFAbsoluteTime end=CFAbsoluteTimeGetCurrent();
NSLog(@"coreData数据插入 time cost: %0.3f", end - start); //测试一下效率 第2种
start = CFAbsoluteTimeGetCurrent();
[[CoreDataManager shareManager]insertDatas:testArray];
end=CFAbsoluteTimeGetCurrent();
NSLog(@"coreData数据插入 time cost: %0.3f", end - start);
insertData函数:
//插入数据
-(void)insertData:(NSString*)tempName
{
//读取类
Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext];
car.name=tempName;
//保存
NSError *error;
[self.managedObjectContext save:&error];
}
insertDatas函数:
//插入数据
-(void)insertDatas:(NSArray*)tempNames
{
for(NSString *name in tempNames){
Car *car=[NSEntityDescription insertNewObjectForEntityForName:@"Car" inManagedObjectContext:self.managedObjectContext];
car.name=name;
}
NSError *error;
[self.managedObjectContext save:&error]; }
运行结果:
第一种:8.408
第二种:0.162
但是有个超级大的问题,第二种方式虽然效率高,但是插入数据乱序。第一种正常但是效率超低,同样近似的数据量sqlite效率比这个高不知多少倍。如果用这个来做数据库开发我觉得是无爱了。批量操作支持的不太好。对于它的数据库升级也不想过多了解。所以就随便查了下,得出如下结论:CoreData 的数据模型升级兼容性比较差,如果模型不对,会导致程序连起都起不来。虽然提供了模型升级代码,但是在客户端的管理模型版本管理也会相对复杂。
IOS数据存储之CoreData使用优缺点的更多相关文章
- iOS数据存储之对象归档
iOS数据存储之对象归档 对象归档 对象归档是iOS中数据持久化的一种方式. 归档是指另一种形式的序列化,但它是任何对象都可以实现的更常规的类型.使用对模型对象进行归档的技术可以轻松将复杂的对象写入文 ...
- iOS数据存储之属性列表理解
iOS数据存储之属性列表理解 数据存储简介 数据存储,即数据持久化,是指以何种方式保存应用程序的数据. 我的理解是,开发了一款应用之后,应用在内存中运行时会产生很多数据,这些数据在程序运行时和程序一起 ...
- iOS数据存储类型 及 堆(heap)和栈(stack)
iOS数据存储类型 及 堆(heap)和栈(stack) 一般认为在c中分为这几个存储区: 1栈 -- 由编译器自动分配释放. 2堆 -- 一般由程序员分配释放,若程序员不释放,程序结束时可能由O ...
- iOS数据存储
[reference]http://www.infoq.com/cn/articles/data-storage-in-ios 谈到数据储存,首先要明确区分两个概念,数据结构和储存方式.所谓数据结构就 ...
- iOS - 数据存储方式(本地化)
iOS中数据存储方式 一般使用以下4种:(已更新) .NSKeyedAchiever//序列化 存放对象 .NSUserDefaults//本质是plist存储 NSData.NSString.NSN ...
- IOS数据存储之Sqlite数据库
前言: 之前学习了数据存储的NSUserDefaults,归档和解档,沙盒文件存储,但是对于数据量比较大,需要频繁查询,删除,更新等操作的时候无论从效率上还是性能上,上述三种明显不能满足我们的日常开发 ...
- IOS数据存储之文件沙盒存储
前言: 之前学习了数据存储的NSUserDefaults,归档和解档,对于项目开发中如果要存储一些文件,比如图片,音频,视频等文件的时候就需要用到文件存储了.文件沙盒存储主要存储非机密数据,大的数据. ...
- 最全的iOS数据存储方法
目的 项目准备运用的Core Data进行本地数据存储,本来打算只写一下Core Data的,不过既然说到了数据存储,干脆来个数据存储基础大总结!本文将对以下几个模块进行叙述. 沙盒 Plist Pr ...
- iOS数据存储-钥匙串存储
2017.11.20 14:41* 字数 227 阅读 678评论 0喜欢 0 钥匙串介绍 1. 表示设备唯一号的标识,在IOS7中要么被禁止使用,要么重新安装程序后两次获取的标识符不一样. 2. ...
随机推荐
- 移动web前端下拉刷新效果
直接复制粘贴 放在页面中即可 <script> window.onload = function(){ window.addEventListener('touchstart', touc ...
- sublime下安装ctags
sublime下安装ctags 标签: sublime 当我们阅读代码时, 会遇到很多不明确的函数名, 此时, 我们需要查看这个函数的定义的地方, 在sublime下我们需要安装一个插件, Cta ...
- Git分布式版本控制系统学习笔记
Git是一个开源的分布式版本控制系统,用以有效.高速的处理从很小到非常大的项目版本管理.[4] Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本 ...
- js微博发布框的实现
观察了微博发布框, 1.发现他的剩余文字是动态改变的, 2.且文字为零时 发布框颜色为暗色 3.文字不符合标准时提交不通过 整理了一下思路 js会主要用到的方法 1.onclick() //点击发布时 ...
- 玩转SQL Server复制回路の变更数据类型、未分区表转为分区表
玩转SQL Server复制回路の变更数据类型.未分区表转为分区表 复制的应用: 初级应用:读写分离.数据库备份 高级应用:搬迁大型数据库(跨机房).变更数据类型.未分区表转为分区表 京东的复制专家 ...
- 跨平台移动开发UI语言 -XAML
Xamarin.Forms 把XAML (Extensible Application Markup Language, XAML) 带进了ios,android的界面开发,也就使得使用Xamarin ...
- EF遇到的一些问题
环境:EntityFramework 版本号:4.1.0.0 问题一:“数据读取器与指定的“.......”不兼容.某个类型为“...”的成员在同名的数据读取器中没有对应的列.”. 使用方式:rep. ...
- MVC学习一:EF
目录 一.EF修改和删除的多种方法 二.标准查询where 三.include 四.skip take 五.反射获取实例属性 六.EF DLL数据访问帮助类 一.EF修改和删除的多种方法 方法1:官方 ...
- 一个App完成入门篇(七)- 完成发现页面
第七章是入门篇的倒数第二篇文章了,明天整个APP将进入收官. 本节教程主要要教会大家使用二维码扫描和用do_WebView组件加在html页面. 导入项目 do_WebView组件 扫描功能 自定义事 ...
- MySQL 游标
概述 本章节介绍使用游标来批量进行表操作,包括批量添加索引.批量添加字段等.如果对存储过程.变量定义.预处理还不是很熟悉先阅读我前面写过的关于这三个概念的文章,只有先了解了这三个概念才能更好的理解这篇 ...