如果应用程序值需要保存程序参数、选项相关的少量数据,则可使用NSUserDefaults进行保存;
如果应用程序只是少量数据需要保存,那使用属性列表文件就可以了;
如果应用程序有大量数据需要存储、访问,就需要借助于数据库.iOS系统内置了SQLite数据库,SQLite数据库是一个真正轻量级的数据库,他没有后台进程,整个数据库就对应于一个文件,这样就可以非常方便的在不同设备之间移植.iOS为访问SQLite数据库提供了两套API:基于C语言风格的libsqlite3.dylib和面向对象的Core Data.
为了提供更好的安全机制,iOS提供了应用程序沙盒机制,这种机制保证每个应用程序只能访问本沙盒内的数据,避免与其他应用形成冲突.在OS X系统中查看应用沙盒,有两种方式:
注意:Xcode 5和Xcode 6的模拟器路径比较
①、Xcode 5中模拟器路径为:/Users/用户名/Library/Application Support/iPhone Simulator
②、Xcode 6中模拟器路径为:/Users/用户名/ Library/Developer/CoreSimulator
其中Devices文件夹下的16个文件对应Xcode6下的16个模拟器,可以根据各个文件夹下的device.plist文件得到具体的是哪个模拟器:
注意:Xcode 5和Xcode 6的沙盒路径比较
①、Xcode 5中沙盒的路径为:/Users/用户名/Library/Application Support/iPhone Simulator/7.1-64/Applications/对应应用程序文件夹
Document
②、Xcode 6中沙盒的路径为:/Users/用户名/Library/ Developer/CoreSimulator/Devices/模拟器UDID/data/Containers/Bundle/Applications/对应应用程序文件夹
注意:Xcode 5和Xcode 6的偏好设置目录比较
①、Xcode 5中偏好设置目录的路径为:/Users/用户名/Library/Application Support/iPhone Simulator/7.1-64/Applications/对应应用程序文件夹/Library/Preferences
②、Xcode 6中偏好设置目录的路径为:使用NSUserDefault方式创建的plist文件的具体路径为:/Users/用户名/Library/ Developer/CoreSimulator/Devices/模拟器UDID/data/Library/Preferences
显示:defaults write com.apple.finder AppleShowAllFiles -bool true
隐藏:defaults write com.apple.finder AppleShowAllFiles -bool false
打开任何应用程序的文件夹,都可以看到如下文件结构:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];
/Users/osx2014/Library/Developer/CoreSimulator/Devices/C99ACFA5-7162-497A-BA7F-0FF93C7F6867/data/Containers/Data/Application/FBFAF7C5-3053-45AA-A1A4-72B98E858A24/Documents
由于NSSearchPathForDirectoriesInDomains()函数并不是专门为iOS设计的,它最初是为了OS X系统设计的,因此在使用该函数的很多选项都不会返回任何值.该函数的第一个参数代表正在查找Documents文件夹,NSUserDomainMask参数代表仅查找当前用户的Home目录.
NSString* tmpPath = NSTemporaryDirectory();
/Users/osx2014/Library/Developer/CoreSimulator/Devices/C99ACFA5-7162-497A-BA7F-0FF93C7F6867/data/Containers/Data/Application/FBFAF7C5-3053-45AA-A1A4-72B98E858A24/tmp/
NSArray *cachePaths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDir = [cachePaths objectAtIndex:0];
/Users/osx2014/Library/Developer/CoreSimulator/Devices/C99ACFA5-7162-497A-BA7F-0FF93C7F6867/data/Containers/Data/Application/BB4C3035-9A66-4DDA-A74B-0B7FC10CC901/Library/Caches
NSString* homePaht = NSHomeDirectory();
/Users/osx2014/Library/Developer/CoreSimulator/Devices/C99ACFA5-7162-497A-BA7F-0FF93C7F6867/data/Containers/Data/Application/BB4C3035-9A66-4DDA-A74B-0B7FC10CC901
当应用程序需要把运行状态、用户数据保存下来时,通常会选择保存在应用程序沙盒的Documents文件夹下,除了基于NSUserDefaults的数据会保存在Library/Prefereences目录下(Xcode 5),一些应用程序的临时文件会选择保存在tmp目录下—一旦该文件失去作用,应用程序应该立即删除该临时文件,释放手机上宝贵的存储空间.
使用多文件保存数据的优缺点如下:
应用程序保存少量的数据(字符串、标量类型等),比如应用程序的各种配置信息(如是打开音效,是否使用振动效果等)、游戏的玩家信息(用户名,密码之类的)等,iOS提供了Settings Bundle来管理.
使用Settings Bundle设置应用程序参数的最大优势在于:无须程序员开发界面,应用的设置界面完全由Setting应用提供,开发者只要提供Settings Bundle这组文件即可.开发者为应用提供了Settings Bundle之后,该应用的参数设置界面由系统的Settings应用提供,用户设置的程序参数也由Settings负责保存,每次打开Settings进行设置时,Settings负责读取用户设置的参数…..应用程序的参数设置界面、数据存储、读取逻辑的都由系统的Settings应用负责.
为项目增加一个Settings Bundle,步骤如下:
在Xcode中打开Settings.bundle包含的Root.plist文件,可以看到如下:
在iPhone Settings Schema节点下包含两个子节点:
注意:plist属性文件的本质就是NSDictionary或NSArray,只不过plist属性文件对应的NSDictionary的key只能是NSString类型,而value可以是Boolean、NSData、NSDate、NSNumber、NSString、NSArray、NSDictionary类型.
单击右键,选择”Show Raw Keys/Values”菜单项,该属性编辑器将会显示更真实的、未经处理的key和value,如下图:
Item0、Item1、Item2、Item3每项对应Settings应用中的一个设置条目,每个设置条目用于设置一个应用程序参数,每项通常可指定如下4个通用项目:
(2)、Type:该项配置应用程序参数的类型.Type支持如下几个属性值.
(3)、Key:该项用于指定保存应用程序参数的key—系统底层会采用NSDictionary来保存这些应用程序参数,每个应用程序参数存入NSDctionary中都需要指定一个key,该项设置的值将会作为应用程序参数的key.
(2)、设置文本框参数
将Type设为”PSTextFieldSpecifier”代表文本框参数–这个程序参数允许用户自由的输入参数值.文本框参数同样可通过Title、Key、Default指定参数的显示标题、保存参数的key、默认值.除此之外,文本款参数还可指定如下选项:
(3)、设置UISwitch参数
将Type设为”PSSwitchSpecifier”代表只支持YES或NO的参数–这个程序参数允许用户通过UISwitch控件来设置参数值.UISwitch参数同样可通过Key、Title、Default指定参数的保存参数的key、显示标题、默认值.
(4)、设置UISlider参数
将Type设为”PSSliderSpecifier”代表只支持浮点值的参数–这个程序参数允许用户通过UISlider控件设置参数值.UISlider参数同样可通过Key、Default指定保存参数的key、默认值.除此之外,UISlider还支持如下设置:
注意:需要将图片放在Settings Bundle中,才能被Settings Bundle访问.不能直接拖近Settings Bundle中,需要显示包内容,还有将图片复制进去.
(5)、设置多值参数
将Type设置”PSMultiValueSpecifier”,用于配置一个多值列表参数、用户可通过列表选择参数值.多值参数同样可通过Title、Key、Default指定参数的显示标题、保存参数的key、默认值.除此之外,多值参数还支持如下设置:
(6)、设置子设置视图
将Item5的Type设为”PSGroupSpecifier”和Item6的Type设为”PSChildPaneSpecifier”,用于配置子设置视图,子设置视图可通过Title设置显示标题,也可通过File设置子设置视图的plist文件名.
注意:该子设置视图需要一个My.plist文件,与Root.plist格式完全相同,需要创建一个My.plist文件,然后显示包内容,复制到Settings Bundle中.
获取NSUserDefaults单例:
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
获取NSUserDefault对象之后,可通过如下方法来获取、设置参数:
例如:
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"你好,女神" forKey:@"key"];
[defaults synchronize];
NSString* name = [defaults objectForKey:@"key"];
注意:此处可读取,设置上述Settings Bundle中的值
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
NSLog(@"%@",[defaults objectForKey:@"name"]);
NSLog(@"%d",[defaults boolForKey:@"musicOn"]);
NSLog(@"%f",[defaults floatForKey:@"gameSpeed"]);
NSLog(@"%@",[defaults objectForKey:@"race"]);
如果程序需要保存一个自定义的实例,则可让该类实现NSCoding协议,并实现该协议中定义的 - (id)initWithCoder:(NSCoder )aDecoder; - (void)encodeWithCoder:(NSCoder )aCoder;两个方法,接下来可使用NSKeyedArchive进行归档,当程序需要回复该对象时,可使用NSKeyedUnarchive进行恢复.
①、创建文件夹:mkdir sqlite;
②、创建表:create table(if not exists)表名(字段名1,字段名2…);
③、显示表:.table;
④、删除表:drop table 表名;
⑤、插入语句:insert into 表名(字段名 1,字段名 2…) values(值 1,值 2…)
⑥、显示表内内容:select *from 表名;
⑦、删除表内数据:delete from 表名 —删除所有的数据
delete from 表名 where 条件 —删除一条数据
⑧、修改:update 表名 set 字段名 1= 值 1,字段名 2=值 2… where 条件;
⑨、查询:select 字段名 from 表名;
select 字段名 from 表名 limit n;查询n条数据
查询排序:select 字段名 from 表名 order by 字段名(desc);降序;
查询多个:select count(*) from 表名;表名数据项数;
select sum(uid) from 表名;uid的和
select avg(uid) from 表名;uid的平均
⑩、退出:.quit;
主要:主键 create table WUGONG(wid integer primary key auto increment name,uid);
在项目中使用iOS的SQLite编程API,需要先完成下面两步:
①、为项目正价libsqlite3.dylib
②、在需要使用SQLite API的Objective-C类中使用如下代码导入libsqlite3.dylib
#import <sqlite3.h>
一般情况下,我们可以使用第三方数据库FMDBDemo开使用数据库,添加头文件
#import "FMDatabase.h"
//首先需要获取数据库存储路径
NSString* path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/data.db"];
_db = [[FMDatabase alloc] initWithPath:path];
//然后创建数据库:
//打开数据库
BOOL res = [_db open];
if (res == NO) {
NSLog(@"打开失败");
return;
}
//创建表
res = [_db executeUpdate:@"create table if not exists USER(name,image)"];
if (res == NO) {
NSLog(@"创建表失败");
[_db close];
return;
}
//插入数据
//NSNumber,NSString,NSData
NSData* data = UIImagePNGRepresentation(_imageView.image);
res = [_db executeUpdate:@"insert into USER values(?,?)",_nameField.text,data];
if (res == NO) {
NSLog(@"插入数据失败");
}
//关闭数据库
[_db close];
BOOL res = [_db open];
if (res == NO) {
NSLog(@"打开失败");
return;
}
res = [_db executeUpdate:@"delete from USER where name=?",_nameField.text];
if (res == NO) {
NSLog(@"删除失败");
[_db close];
return;
}
NSLog(@"删除成功");
[_db close];
BOOL res = [_db open];
if (res == NO) {
NSLog(@"打开失败");
return;
}
//查询
FMResultSet *set = [_db executeQuery:@"select *from USER"];
while ([set next]) {
//int
//int a = [set intForColumn:]
//NSNumber
//NSNumber* num = [set objectForColumnName:]
NSString *name = [set stringForColumn:@"name"];
//NSData *data = [set dataForColumn:@"image"];
NSLog(@"name = %@",name);
}
[_db close];
BOOL res = [_db open];
if (res == NO) {
NSLog(@"打开失败");
return;
}
NSData *data = UIImagePNGRepresentation(_imageView.image);
//修改name;
//res = [_db executeUpdate:@"update USER set name=? where image=?",_nameField.text,data];
//修改image
res = [_db executeUpdate:@"update USER set image=? where name=?",data,_nameField.text];
if (res == NO) {
NSLog(@"修改失败");
[_db close];
return;
}
NSLog(@"修改成功");
[_db close];
Core Data是一个纯粹的面向对象框架,可用于管理实体以及实体之间的关联关系的持久化—所谓的持久化,指的是Core Data可以将实体保存到持久化存储设备中,也可以在需要的时候将他们取出来;
Core Data底层的持久化存储方式可以是SQLite数据库,也可以是XML文档,甚至可以直接以内存作为持久化存储备(如果选择内存作为持久化存储设备,那么应用重启时,数据就会丢失);
Core Data的核心概念是实体.实体是由Core Data管理(简称被托管)的模型对象,它必须是NSManagedObject类或其子类的实例.实体与实体之间存在1-1,1-N,N-N的关联关系,整个应用的所有实体以及的关联关系被称为托管模型(NSManagedObjectModel);
Core Data的核心对象时托管对象上下文(NSManagedObjectContext,有时也简称上下文),所有实体都处于托管对象上下文管理中,Core Data应用对实体所做的任何增、删、改、查操作都必须通过托管对象上下文来完成.
Core Data应用中的核心API有如下几个:
使用Core Data持久化操作的步骤大致如下:
步骤如下:
①、为该项添加CoreData.framework框架;
②、创建一个”Data Model”文件;
③、初始化Core Data应用必须得核心API对象:NSManagedObjectModel、NSPersistentStoreCoordinator、NSManagedObjectContext.
例如:这些核心API对象都属于全局可用的对象,因此程序一般会在应用程序委托类中执行初始化:
应用程序委托类的接口部分:
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property(strong,nonatomic,readonly)NSManagedObjectModel* managedObjectModel;
@property(strong,nonatomic,readonly)NSManagedObjectContext* managedObjectContext;
@property(strong,nonatomic,readonly)NSPersistentStoreCoordinator* persistentStoreCoordinator;
@end
应用接口委托类的实现部分
@synthesize managedObjectContext = _managedObjectContext;
@synthesize manageObjectModel = _manageObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
- (void)saveContext{
NSError *error = nil;
//获取应用的托管对象的上下文
NSManagedObjectContext* managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
//如果托管对象上下文中包含了未保存的修改,则执行保存,如果保存失败则记录错误信息
if ([managedObjectContext hasChanges]&&![managedObjectContext save:&error]) {
NSLog(@"保存出现错误:%@,%@",error,[error userInfo]);
}
}
}
//托管对象
-(NSManagedObjectModel *)managedObjectModel
{
//如果_managedObjectModel已经被初始化,则直接返回该对象
if (_managedObjectModel!=nil) {
return _managedObjectModel;
}
//获取实体模型文件对象的NSURL
NSURL* modelURL=[[NSBundle mainBundle] URLForResource:@"User" withExtension:@"momd"];
//加载应用的实体模型文件,并初始化NSManagedObjectModel对象
_managedObjectModel=[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
// _managedObjectModel=[NSManagedObjectModel mergedModelFromBundles:nil];
return _managedObjectModel;
}
//持久化存储协调器
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator{
//如果_persistentStoreCoordinator已经被初始化过,则直接返回该对象
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
//获取SQLite数据库文件的存储目录
NSURL* storeURL = [[self applicationDocumentDirectory]URLByAppendingPathComponent:@"Books.sqlite"];
NSError* error;
//以持久化对象模型为基础,创建NSPersistentStoreCoordinator对象
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]initWithManagedObjectModel:[self manageObjectModel]];
//设置持久化存储协调器底层采用SQLite存储机制,如果设置失败记录错误信息
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
NSLog(@"保存出现错误:%@,%@",error,[error userInfo]);
//异常退出
abort();
}
return _persistentStoreCoordinator;
}
//获取目录的Document目录
- (NSURL *)applicationDocumentDirectory{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]lastObject];
}
//初始化应用的托管上下文
- (NSManagedObjectContext *)managedObjectContext{
//如果_managedObjectContext已经被初始化过,则直接返回该对象
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
//获取持久化存储协调器
NSPersistentStoreCoordinator* coordinator = [self persistentStoreCoordinator];
//如果持久化存储协调器不为nil
if (coordinator != nil) {
//创建NSManagedObjectContext对象
_managedObjectContext = [[NSManagedObjectContext alloc]init];
//为NSManagedObjectContext对象配置持久化存储协调器
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
- (void)applicationWillTerminate:(UIApplication *)application {
[self saveContext];
}
每个实体也可以添加如下3种属性:
添加实体、抓取请求、配置的按钮;
为实体添加属性的按钮;
切换显示方式的按钮;
实体列表;
抓取请求列表;
配置列表;
此处列出指定实体的所有属性;
此处列出指定实体的所有关联关系;
实例:添加一个简单的实体
提示:长按”Add Attribute”按钮,该按钮将会显示Add Attribute、Add Relationship、Add Fetched Property列表,开发者可以选择其中一项来添加属性、关联关系、抓取属性.开发者也可以通过属性栏,关联关系栏、抓取属性栏下放的”+”、”-“按钮进行添加、删除.
步骤如下:
例如如下代码:
self.appDelegate =[UIApplication sharedApplication].delegate;
CXUser* event = [NSEntityDescription insertNewObjectForEntityForName:@"CXUser" inManagedObjectContext:self.appDelegate.managedObjectContext];
// 为新实体设置属性
[event setName:@"xioaixao"];
// 定义一个NSError对象,用于接收错误信息
NSError* error;
//设置完实体属性之后,调用托管对象上下文的save:方法将实体写入数据库,如果保存成功
if ([self.appDelegate.managedObjectContext save:&error]) {
NSLog(@"保存成功");
}else{
NSLog(@"保存实体出错:%@,%@",error,[error userInfo]);
}
删除实体的步骤如下:
例如:
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setIncludesPropertyValues:NO];
[request setEntity:entity];
NSError *error = nil;
NSArray *datas = [self.appDelegate.managedObjectContext executeFetchRequest:request error:&error];
if (!error && datas && [datas count])
{
for (NSManagedObject *obj in datas){
[self.appDelegate.managedObjectContext deleteObject:obj];
}
if (![self.appDelegate.managedObjectContext save:&error])
{
NSLog(@"error:%@",error);
}else{
NSLog(@"删除成功");
}
}
修改实体的步骤如下:
例如:
NSEntityDescription *entity = [NSEntityDescription entityForName:@"CXUser" inManagedObjectContext:self.appDelegate.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setIncludesPropertyValues:NO];
[request setEntity:entity];
NSArray *datas = [self.appDelegate.managedObjectContext executeFetchRequest:request error:&error];
if (!error && datas && [datas count])
{
for (CXUser *obj in datas){
if ([obj.name isEqualToString:@"xiaoxiao"]) {
[obj setName:@"bukuang"];
}
}
if (![self.appDelegate.managedObjectContext save:&error])
{
NSLog(@"error:%@",error);
}else{
NSLog(@"修改成功");
}
}
查询实体的步骤如下:
例如:
//设置想要抓取那种类型的实体
NSEntityDescription *entity = [NSEntityDescription entityForName:@"CXUser" inManagedObjectContext:self.appDelegate.managedObjectContext];
//创建抓取数据的请求对象
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setIncludesPropertyValues:NO];
//设置抓取实体
[request setEntity:entity];
//设置抓取条件
// 设置条件过滤(搜索name中包含字符串"xiaoxiao"的记录,注意:设置条件过滤时,数据库SQL语句中的%要用*来代替,所以%xiaoxiao%应该写成*Itcast-1*)
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@", @"*xiaoxiao*"];
request.predicate = predicate;
NSError* error;
NSArray *datas = [self.appDelegate.managedObjectContext executeFetchRequest:request error:&error];
if (!error && datas && [datas count])
{
for (CXUser* user in datas) {
NSLog(@"user = %@“,user.name); } }
以后再续;