IOS高级编程之二:IOS的数据存储与IO
一、应用程序沙盒
IOS应用程序职能在系统为该应用所分配的文件区域下读写文件,这个文件区域就是应用程序沙盒。所有的非代码文件如:图片、声音、映象等等都存放在此。
在mac中command+shift+G命令,然后输入users/用户名/library命令进入库,然后依次进入application support/iphone simulator/版本/applications文件夹,这里面的各个文件夹对应着各个应用程序。
Documents:除了基于NSUserDefaults的首选项设置外,应用程序的数据、文件都保存在该目录下
Library:基于NSUserDefaults的首选项参数保存在Library/Preferences下
tmp:应用程序存储临时文件,ios同步时itunes不会同步这里面的数据,当应用程序不在需要这些文件时,应当删除以避免占用空间。
获取documents路径:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *dd = [paths objectAtIndex:];
获取tmp目录:
NSString *tempPath = NSTemporaryDirectory();
那么我们在保存数据时使用哪种发式比较好呢,这个当然还要具体情况具体对待。
当保存小数据量的数据时,可以使用NSArray或者NSDictionary,调用writeToFile:atomically:方法写入一个文件,使用时读取文件内容即可。
当保存大数据量的数据时,可以选择使用sqllite,ios提供了CoreData框架。
二、应用程序参数与用户默认设置
1、使用Settings Bundle
Settings Bundle时应用程序中的一组特殊文件,用于保存较简单的各种配置信息。如果使用了Settings Bundle,ios自带的设置应用则会显示你的app
2、使用NSUserDefaults读取、保存应用程序参数
NSUserDefaults是一个单例类,每个应用程序只有一个NSUserDefaults对象,Settings Bundle设置的参数,也可以通过NSUserDefaults来读取和设置
获取NSUserDefaults的方法:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
获取NSUserDefaults对象后,可以获取和设置应用程序参数
xxForKey:(NSString *) key =>xx表示各种类型,根据key获取值
setBool:(xxx) value forKey:(NSString *) key =>设置参数
设置完参数后,调用synchronize方法进行保存。
3、属性列表
属性列表就是文章开始提到的利用NSArray和NSDictionary将数据写入到文件的保存方法。
但是有一些限制,只有下列类型的值保存到NSArray和NSDictionary中才可以直接调用writeToFile方法执行保存:
NSArray、NSMutableArray、NSDictionary、NSMutableDictionary、NSData、NSMutableData、NSString、NSMutableString、NSValue、NSNumber
如果NSArray和NSDictionary保存了我们自定义的类,那么将不能直接调用writeToFile方法执行保存。(可以考虑使用对象归档的方法进行保存)
//使用属性列表保存3个用户的账号密码
accountList = [[NSMutableArray alloc] init];
[accountList addObject:[NSDictionary
dictionaryWithObjects:[NSArray arrayWithObjects:@"loginname",@"loginpwd", nil]
forKeys:[NSArray arrayWithObjects:@"",@"", nil]]];
[accountList addObject:[NSDictionary
dictionaryWithObjects:[NSArray arrayWithObjects:@"loginname",@"loginpwd", nil]
forKeys:[NSArray arrayWithObjects:@"",@"", nil]]];
[accountList addObject:[NSDictionary
dictionaryWithObjects:[NSArray arrayWithObjects:@"loginname",@"loginpwd", nil]
forKeys:[NSArray arrayWithObjects:@"",@"", nil]]];
[accountList writeToFile:[self filePath] atomically:YES]; //使用UIActionSheet提示用户保存成功
UIActionSheet *sheet =[[UIActionSheet alloc] initWithTitle:@"保存成功" delegate:nil cancelButtonTitle:nil destructiveButtonTitle:@"确定" otherButtonTitles:nil, nil];
[sheet showInView:self.view];
4、使用Sqlite3数据库
1)为项目增加libsqlite3.dylib,这是一个原生的C函数库
常用函数:
int sqlite3_close(sqlite3 *):关闭sqlite3 *所代表的数据连接,并释放底层数据库连接资源。在调用该函数之前,必须先调用sqlite3_finalize()函数,调用sqlite3_blob_close()函数关闭所有的blob处理器,否则将会返回SQLITE_BUSY
int sqlite3_exec(sqlite3*,const char *sql, int (*callback)(void*, int ,char**,char**),void *,char **errmsg):用于执行没有返回值的sql语句
sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*):返回sqlite3代表的数据库最后一次插入行的id
int sqlite3_changes(sqlite3*):执行某条dml语句后,返回受影响行数
void sqlite3_interrupt(sqlite3*):中断一个长时间执行的查询语句
int sqlite3_complete(const char *sql):用于判断sql语句是否执行完成
int sqlite3_open(const char * filename,sqlite3 ** ppdb):打开与filename文件的链接,并让ppdb参数引用被打开的数据库连接
const char *sqlite3_sql(sqlite3_stmt *pStmt):用于提取sqlite3_stmt(预编译SQL语句产生的结果)中包装的sql语句
等等。。。太多了不一一列举了
操作sqlite数据库的大致步骤如下:
1、调用sqlite3_open方法打开与数据库的连接
2、执行语句
3、sqlite3_close函数关闭数据库连接
2)使用Core Data框架
Core Data框架是一个纯粹的面向对象的框架,允许开发者以面向对象的方式持久化操作SQLite数据库。core data底层的持久化存储方式可以是Sqlite数据库,也可以是xml,也可以是内存。
Core Data的核心概念是实体,由Core Data管理的模型对象,它必须是NSManagedObject类或者它的子类的实例。
Core Data应用中的核心API有如下几个:
托管对象模型(NSManagedObjectModel):该对象负责管理整个应用的所有实体以及实体之间的关联关系。当开发者使用Xcode的图形界面设计了实体与实体间的关联关系之后,需要使用该对象来加载、管理应用的托管对象模型
持久化存储协调器(NSPersistentStoreCoordinator):负责管理底层的存储文件,例如sqlite数据库等等
托管对象上下文(NSManagedObjectContext):该对象是Core Data的核心,增删改查都需要通过它来进行
实体描述(NSEntityDescription):关于某个实体的描述信息
抓取请求(NSFetchRequest):该对象封装了查询实体的请求,包括程序需要查询哪些实体、查询条件、排序规则等
使用Core Data持久化的步骤大致如下
1、创建NSManagedObjectModel对象来加载管理应用对应的托管对象模型
2、以NSManagedObjectModel对象为基础,根据实际需要创建NSPersistentStoreCoordinator对象,该对象确定底层数据的存储形式
3、以NSManagedObjectModel对象为基础,创建NSManagedObjectContext对象
4、对于普通的增、删、改操作,需要分别先新建实体、删除实体、修改实体,然后调用NSManagedObjectContext对象的save方法,保存修改
5、如果执行查询,需要先创建NSFetchRequest对象,在调用NSManagedObjectContext对象的executeFetchRequest:error:方法,返回所有匹配条件的实体组成的NSArray
使用Core Data的例子来和大家一起学习。
首先,创建一个创建一个Single View Application,下面有个Use Core Data选项,打上勾,之后Xcode已经为你做好了准备工作,打开AppDelete.m就可以看到
#pragma mark - Core Data stack @synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator; - (NSURL *)applicationDocumentsDirectory {
// The directory the application uses to store the Core Data store file. This code uses a directory named "esitech.Unit_3" in the application's documents directory.
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
} - (NSManagedObjectModel *)managedObjectModel {
// The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
//获取实体模型文件对应的nsurl
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Unit_3" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
} - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
} // Create the coordinator and store
//以持久化模型为基础,创建持久化存储协调器对象
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
//获取sqlite数据库文件的存储目录
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Unit_3.sqlite"];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
//设置存储协调器采用sqlite,如果失败打印失败信息
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code: userInfo:dict];
// Replace this with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
} return _persistentStoreCoordinator;
} - (NSManagedObjectContext *)managedObjectContext {
// Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
if (_managedObjectContext != nil) {
return _managedObjectContext;
} NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (!coordinator) {
return nil;
}
_managedObjectContext = [[NSManagedObjectContext alloc] init];
//设置上下文使用的持久化类型
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
return _managedObjectContext;
} #pragma mark - Core Data Saving support - (void)saveContext {
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
NSError *error = nil;
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
三个重要的对象NSManagedObjectModel、NSPersistentStoreCoordinator、NSManagedObjectContext的实例已经为你设置好了,当我们要执行相关增删改查时,直接调用委托类的managedObjectContext属性操作即可。
在创建项目后,会发现项目中有一个**.xcdatamodeld文件,点击后就会出现实体模型设计界面
#import "SqliteViewController.h"
#import "EventEntity.h"
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "AppDelegate.h" @interface SqliteViewController ()
@property (nonatomic,weak) AppDelegate *appDelete;
@property (nonatomic) int nameCount;
@end @implementation SqliteViewController - (void)viewDidLoad {
[super viewDidLoad];
self.nameCount = ;
// Do any additional setup after loading the view.
self.appDelete = (AppDelegate *)[UIApplication sharedApplication].delegate;
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//添加操作
- (IBAction)btnAdd_Tap:(id)sender {
//创建一个新实体
EventEntity *ee = [NSEntityDescription insertNewObjectForEntityForName:@"EventEntity" inManagedObjectContext:self.appDelete.managedObjectContext];
//给实体设置属性
ee.happenDate = [NSDate date];
ee.name = [NSString stringWithFormat:@"名字%d",self.nameCount++]; //定义NSError对象接收错误信息
NSError *error;
if ([self.appDelete.managedObjectContext save:&error]) {
[[[UIAlertView alloc] initWithTitle:@"添加操作" message:[NSString stringWithFormat:@"添加成功,添加的实体的name是:%@",ee.name] delegate:nil cancelButtonTitle:@"好的" otherButtonTitles:nil, nil] show];
}else
{
NSLog(@"保存时出现错误:%@,%@",error,[error userInfo]);
}
}
//删除操作
- (IBAction)btnRemove_Tap:(id)sender {
//获取要删除的实体
EventEntity *entity = [self getEntityByName:@"名字1"];
//从上下文对象中删除该实体
[self.appDelete.managedObjectContext deleteObject:entity];
NSError *error;
if (![self.appDelete.managedObjectContext save:&error]) {
NSLog(@"删除时出现错误:%@,%@",error,[error userInfo]);
}
}
5.3 修改实体
//更新操作
- (IBAction)btnUpdate_Tap:(id)sender {
//获取要删除的实体
EventEntity *entity = [self getEntityByName:@"名字1"];
//修改实体属性
entity.happenDate = [NSDate date];
NSError *error;
if (![self.appDelete.managedObjectContext save:&error]) {
NSLog(@"删除时出现错误:%@,%@",error,[error userInfo]);
}
}
5.4 查询
//根据名字查询一个对象
-(EventEntity *)getEntityByName:(NSString *) name
{
//创建抓取数据的请求对象
NSFetchRequest *request = [[NSFetchRequest alloc] init]; //设置要抓取哪种类型的实体
NSEntityDescription *des = [NSEntityDescription entityForName:@"EventEntity" inManagedObjectContext:self.appDelete.managedObjectContext]; //设置抓取实体
[request setEntity:des];
//定义抓取条件
NSPredicate * qcmd = [NSPredicate predicateWithFormat:@"name = %@ ",name];
[request setPredicate:qcmd]; NSError *error = nil;
//执行查询请求
NSArray *result = [[self.appDelete.managedObjectContext executeFetchRequest:request error:&error] copy];
if (error!=nil) {
NSLog(@"查询单个时出现错误:%@,%@",error,[error userInfo]);
return nil;
}
if (result.count==) {
return nil;
}
return result[];
} //获得所有实体
-(NSArray *)getAllEntities
{
//创建抓取数据的请求对象
NSFetchRequest *request = [[NSFetchRequest alloc] init]; //设置要抓取哪种类型的实体
NSEntityDescription *des = [NSEntityDescription entityForName:@"EventEntity" inManagedObjectContext:self.appDelete.managedObjectContext]; //设置抓取实体
[request setEntity:des]; NSError *error = nil;
//执行查询请求
NSArray *result = [[self.appDelete.managedObjectContext executeFetchRequest:request error:&error] copy];
//如果没有数据返回nil
if (error!=nil && result == ) {
return nil;
}
return result; }
IOS高级编程之二:IOS的数据存储与IO的更多相关文章
- iOS高级编程之XML,JSON数据解析
解析的基本概念 所谓“解析”:从事先规定好的格式串中提取数据 解析的前提:提前约定好格式.数据提供方按照格式提供数据.数据获取方按照格式获取数据 iOS开发常见的解析:XML解析.JSON解析 一.X ...
- [深入浅出Cocoa]iOS网络编程之Socket
http://blog.csdn.net/kesalin/article/details/8798039 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[+] [深入浅出Co ...
- iOS多线程编程之NSThread的使用
目录(?)[-] 简介 iOS有三种多线程编程的技术分别是 三种方式的有缺点介绍 NSThread的使用 NSThread 有两种直接创建方式 参数的意义 PS不显式创建线程的方法 下载图片的例子 ...
- iOS多线程编程之NSThread的使用(转)
本文由http://blog.csdn.net/totogo2010/原创 1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation ...
- [转] iOS多线程编程之Grand Central Dispatch(GCD)介绍和使用
介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其他的对称多处理系统的系统.这建立在任务并行执行的线程池模式的基础上的.它首 ...
- [转]iOS多线程编程之NSThread的使用
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1..NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue ...
- iOS 多线程编程之Grand Central Dispatch(GCD)
介绍: Grand Central Dispatch 简称(GCD)是苹果公司开发的技术,以优化的应用程序支持多核心处理器和其它的对称多处理系统的系统.这建立在任务并行运行的线程池模式的基础上的. 它 ...
- iOS多线程编程之NSThread的使用(转载)
1.简介: 1.1 iOS有三种多线程编程的技术,分别是: 1.NSThread 2.Cocoa NSOperation (iOS多线程编程之NSOperation和NSOperationQueue的 ...
- [转] iOS多线程编程之NSOperation和NSOperationQueue的使用
<iOS多线程编程之NSThread的使用> 介绍三种多线程编程和NSThread的使用,这篇介绍NSOperation的使用. 使用 NSOperation的方式有两种, 一种是用定义好 ...
随机推荐
- 关闭/开启 ubuntu 自动更新提示
发现vps登陆后只有apt update后才知道有多少包需要更新不是很傻么,本地的ubuntu在登录时就有很好的提示,并且还能告知系统负载情况,很有用,这里就想开起来.首先这个提示的名字叫Motd. ...
- Objective-c中定义成员变量
ios定义成员变量的方法: 如果只是内部访问,完全可以直接用_xxx(下划线),无需自己定义,编译器会自动生成 如果需要外部访问这个变量,可以用 @property xxx ; @synthesize ...
- Scala 深入浅出实战经典 第79讲:单例深入讲解及单例背后的链式表达式
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- 在Android Studio进行“简单配置”单元测试(Android Junit)
起因 在Android studio 刚出.本人就想弄单元测试,可惜当时Android studio不知道抽什么风(准确来说,应该是我不会弄而已).无法执行到相应的代码.后来今天突然自己又抽风.又想去 ...
- Flipping elements with WPF
http://yichuanshen.de/blog/2010/11/13/flipping-elements-with-wpf/ Have you already seen ForgottenTim ...
- HL AsySocket 服务开发框架 - 总体思路与架构
一 背景 最近在园子了浏览了几篇有关Socket文章,得到了一些启发萌生了想要重构公司在2000年用.NET Framework 2.0 与 Visual Studio 2005开发的AsySocke ...
- mac系统如何关闭root账户
第一步:系统偏好设置 ->用户与群组 第二步:登录选项 ->解锁 ->单击网络帐户服务器加入 第三步:打开目录实用工具 第四步:菜单栏 ->编辑 ->停用 Root 用户 ...
- DIV实现纵向滚动条overflow-y
DIV实现纵向滚动条overflow-y:scroll的使用, 1.首先设置固定div的宽高2.overflow-y:scroll如果设置overflow:auto;表示当你内容超过div高度出现滚动 ...
- 飞思卡尔9S12X系列双核中的协处理器XGATE使用方法
http://adi.chinaaet.com/analog/blogdetail/24482.html
- bootstrap fileinput 文件上传工具
这是我上传的第二个plugin 首先第一点就是因为这个好看 符合bootstrap的界面风格 第二是可以拖拽(虽然我不常用这个功能 但是这样界面看起来就丰满了很多) 最后不得不吐槽这个的回发事件 我百 ...