一.应用程序沙盒
1.应用程序沙盒基本概念
(1)每个iOS应用都有自己独立封闭的一套文件系统,这个系统就称为应用程序沙盒(App Sandbox)
(2)iOS应用只能在自己的沙盒内部读写文件,基本不可以去其他地方访问文件.所有需要使用的资源文件都需要保存在沙盒内部,如图片,声音,文本等.
(3)iOS应用所请求的数据都要进行权限检测,如果不符合条件的话该请求将不会被执行.
(4)沙盒是一种安全体系,其核心内容就是对iOS应用的操作进行权限控制
2.为什么要使用沙盒
(1)防止你的应用被其他应用恶意访问/更改或删除
(2)防止其他应用访问你应用当中的个人数据
(3)应用数据清理十分方便,不会在其他地方遗留痕迹
3.沙盒文件体系
(1)MyApp.app
存放应用程序束(App Bundle)的文件夹.应用程序束中存放有App的可执行代码文件以及其相关资源.
应用在安装的时候会给该文件夹进行数字签名,在每次应用启动前进行签名认证.如果对该文件夹进行了修改,那么也会将数字签名破坏,导致应用不能启动.
这个文件夹的内容在进行iTunes同步的时候只会备份一次,除非该应用发生版本变更或者被移除.
(2)Documents
①作用
- Documents文件夹用来存储非常大的文件或需要非常频繁更新的数据,但是基于NSUserDefaults的首选项存储数据并不会保存在其中.
- 能够进行iTunes或者iCloud备份.
②获取
NSArray *documentDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
//因为documentDirectory数组只有一个元素,所以取第一个或者最后一个都是一样的
NSString *myDocPath1 = [documentDirectory firstObject];
//或
NSString *myDocPath2 = [documentDirectory lastObject];
(3)Library
①作用
- Library文件夹用来存储系统文件.可以在该文件夹中创建新的子文件夹来存储数据.
- Library目录下有Preferences和Caches目录.
- 其中Preferences用来存放应用程序的设置数据,比如NSUserDefaults相关数据就是存储在~/Library/Preferences文件夹中.
- Caches与Documents相似,可以存放应用程序的数据,用来存储数据库缓存文件/缓存内容(新闻,地图数据等).要注意的是,该文件夹并不会被备份.
(4)tmp
①作用
- tmp文件夹用来存储临时数据,应用应当及时删除该文件夹中的数据来释放空间
如果应用没有运行,并且系统内存不够,那么iOS会自动移除该文件夹内的文件来释放空间 - iTunes或iCloud不会备份该文件夹内的文件
②获取
NSString *tmpDirectory = NSTemporaryDirectory();
二.数据持久化
1.数据持久化是什么:
数据持久化就是将内存中的数据模型转换成存储模型,以及将存储模型转换为内存中的数据模型的统称.
2.数据持久化的方式
3.数据持久化的基本操作
①保存:把数据保存到存储模型中
②更新:修改存储模型中的对象
③删除:从存储模型中删除存储对象
④加载:把存储模型中存储对象加载到内存当中
⑤查询:在存储模型中查询满足一定条件的存储对象并加载到内存
三.NSUserDefaults
1.NSUserDefaults基本概念
(1)NSUserDefaults类提供了一个与系统默认设置进行交互的编程接口,它可以用来保存,恢复应用程序相关的偏好设置,配置数据等.
(2)NSUserDefaults类将数据对象存储在一个叫”默认系统”的地方.默认系统中所有的内容都能够在整个应用程序的生命周期内进行访问,并且任何存储到默认系统内的数据都会被应用持久化到设备的存储中.
(3)NSUserDefaults是一个单例,在整个程序中只有一个实例对象.
(4)NSUserDefaults存储形式类似于NSDictioanry,适合存储轻量级的本地数据
(5)NSUserDefaults只能存放系统对象,不能存放自定义类型对象(归档可以存放自定义类型对象)
2.NSUserDefaults可以存储的数据类型
3.代码举例
NSUserDefaults *account = [NSUserDefaults standardUserDefaults];
if (![account objectForKey:@"name"]) {
[account setObject:@"Story5" forKey:@"name"];
//键值改变后需要同步一下
[account synchronize];
}
四.Setting Bundle
1.Setting Bundle基本概念
(1)Setting Bundle是在自己应用中创建的一组文件利用它可以告诉设备中”设置”应用,我们的应用都有哪些设置项.
(2)用户在”设置”应用中可以对应用进行偏好设置,然后应用中的对应项也会发生相应的变化
五.通用文件存储(plist)
1.通用文件存储基本概念
(1)通用文件又叫属性列表文件/plist文件,实质是一种XML文件,Foundation框架中的数组和字典都可以与属性列表文件互相转换
(2)通用文件存储比起NSUserDefaults来说有着更为广阔的应用空间,因为如果使用了Setting Bundle来进行首选项设置的话,那么NSUserDefaults就不再适宜存储其它类型的数据了,以免造成数据冲突
(3)通用文件存储可以用来存储序列化对象(serialized object).
序列化对象是指可以转换为字节流以便于存储到文件中或通过网络进行传输的对象,虽然说任何对象都可以被序列化,但是只能将某些对象放置到集合类中才能将它们存储到通用文件当中
2.可以进行对象序列化的类
3.通用文件存储存在的问题
(1)无法将自定义对象序列化到属性列表中
(2)只能序列化前面2所提的固定的几个类
(3)无法创建派生的或者需要计算的属性,并且给控制器类增加了运算负担
(4)通用文件存储面对复杂的数据模型和海量数据时力不从心
六.对象归档
1.对象归档基本概念
(1)对象归档(Archive):
对象归档是一种序列化方式.为了便于数据传输,先将归档对象序列化为一个文件,然后通过反归档将数据恢复到对象中.
(2)对象反归档(Unarchive):
将数据从文件中读出并且自动重建对象
2.归档优缺点
归档技术可以实现数据的持久化,不过在大量数据和频繁读写的情况下,它就不太适合了.
3.归档要求
对一个对象进行归档,该对象必须实现NSCoding协议,而且每个成员变量应该是基本数据类型或都是实现NSCoding协议的某个类的实例.
4.归档方法详解
(1)与NSData关联性
归档类NSKeyedArchiver和反归档NSKeyedUnarchiver总与NSData关联在一起.NSData封装了字节数据的缓存类,提供了读写数据的方法.
①从文件中创建NSData对象
// 1.它是静态方法,用于从文件中读取数据来创建NSData对象.
+ (nullable instancetype)dataWithContentsOfFile:(NSString *)path;
/**2.它是静态方法,用于从文件中读取数据来创建NSData对象.
* options参数是指定读取数据选项
* error参数是返回读取数据的错误
*/
+ (nullable instancetype)dataWithContentsOfFile:(NSString *)path options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;
// 3.它是实例构造器,用于从文件读取数据来创建NSData对象
- (nullable instancetype)initWithContentsOfFile:(NSString *)path;
/**4.它是实例构造器,用于从文件读取数据来创建NSData对象
* options参数是指定读取数据选项
* error参数是返回读取数据的错误
*/
- (nullable instancetype)initWithContentsOfFile:(NSString *)path options:(NSDataReadingOptions)readOptionsMask error:(NSError **)errorPtr;
②将NSData对象写入文件
// 1.通过提供是否使用辅助文件,将NSData对象写入到文件中
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
/**2.通过提供写入选项,将NSData对象写入到文件中
* options参数是指定读取数据选项
* error参数是返回读取数据的错误
*/
- (BOOL)writeToFile:(NSString *)path options:(NSDataWritingOptions)writeOptionsMask error:(NSError **)errorPtr;
(2)归档和反归档过程
①归档过程
首先将归档数据写入到NSData对象中,最后再将NSData对象使用NSKeyedArchiver对象写入到归档文件中.
②反归档过程
从归档文件中读取到NSData对象,再利用NSKeyedUnarchiver对象从NSData对象中反归档出数据
(3)系统类归档和反归档
①方法
//归档
+ (BOOL)archiveRootObject:(id)rootObject toFile:(NSString *)path;
//反归档
+ (nullable id)unarchiveObjectWithFile:(NSString *)path;
②程序举例:
NSString *desktopPath = @"Users/Story5/Desktop";
NSArray *array = [NSArray arrayWithObjects:@"Story5",@"is",@"very",@"handsome", nil];
NSString *path = [desktopPath stringByAppendingString:@"/stringArchiverFile"];
//1.归档
[NSKeyedArchiver archiveRootObject:array toFile:path];
//2.反归档
NSArray *arrayUnarchiver = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
(4)自定义类归档和反归档
①只有遵守了协议的类的对象才能进行归档和反归档操作.
②方法
- (void)encodeWithCoder:(NSCoder *)aCoder;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
③程序举例
#import "Student.h"
@implementation Student
//当类的对象进行归档操作的时候,自动调用
- (void)encodeWithCoder:(NSCoder *)aCoder{
//- (void)encodeInt:(int)intv forKey:(NSString *)key;
//作用:对int型数据进行归档
//intv:归档的int型数据
//key:归档的格式,以什么样的格式进行归档,就需要以该格式进行反归档
[aCoder encodeInt:_age forKey:@"age"];
//- (void)encodeObject:(id)objv forKey:(NSString *)key;
//作用:归档oc对象
[aCoder encodeObject:_name forKey:@"name"];
}
//但类的对象进行反归档操作的时候,自动调用
- (id)initWithCoder:(NSCoder *)aDecoder{
//- (int)decodeIntForKey:(NSString *)key;
//作用:反归档int型数据
_age = [aDecoder decodeIntForKey:@"age"];
//- (id)decodeObjectForKey:(NSString *)key;
//作用:反归档oc对象
_name = [aDecoder decodeObjectForKey:@"name"];
return self;
}
@end
七.Sqlite
Sqlite是一款轻型的数据库,现在最新版本为Sqlite3.
Sqlite是开源的,它采用C语言编写,具有可移植性强,可靠性高,小而容易使用的特点.
在存储和检索大量数据方面非常有效,它还能够对数据进行复杂的聚合,与NSUserDefaults,数据归档等方式相比,获取结果的速度更快.
关于Sqlite的简单使用,可以参考本人的这篇文章《iOS 下Sqlite的简单使用》,这里就不过多的作介绍了
八.Core Data
1.Core Data是什么?
CoreData是苹果为Mac OS X和iOS系统应用开发提供的数据持久化技术.它基于高级数据持久化API,其底层最终是Sqlite数据库,二进制文件和内存数据保存,这样开发人员不用再关心数据存储的细节问题,不用再使用SQL语句,不用面对Sqlite的C语言函数.
2.ORM是什么?
- Core Data是一种ORM(对象关系映射)技术.ORM是关系数据模型和对象模型类之间的一个纽带.
- 我们知道,为了描述和构建应用系统,我们引进了两种模型,关系模型和对象模型
- 对于基础的概念实体,在关系模型中代表着一条数据,而在对象模型中代表类的一个对象.
- 关系模型和对象模型是有区别的,对象模型更加先进,能够描述继承,实现,关联,聚合和组成等复杂的关系,而关系模型只能描述一对一,一对多和多对多的关系.
这两种模型之间的不和谐称为阻抗不匹配问题,而ORM恰好可以解决这个问题.
3.Core Data堆栈
(1)被管理对象模型,持久化存储协调器,被管理对象上下文和持久化对象存储一起构成了Core Data堆栈
通过Core Data堆栈可以实现数据CRUD(插入/查询/修改/删除)操作
(2)Core Data堆栈如下图所示,
持久化对象存储与底层存储文件关联.
一个持久化存储协调器可以管理多个被管理对象模型.一个持久化存储协调器就意味着一个Core Data堆栈.
4.为工程添加Core Data支持
我们可以使用Xcode模板中的以下两个模板,直接在创建工程的时候添加Core Data支持.使用时需选中Use Core Data
复选框
5.代码分析
通过模板生成的代码,其主要代码在AppDelegate中
(1)AppDelegate.h
//
// AppDelegate.h
// CoreDataDemo
//
// Created by Story5 on 7/12/16.
// Copyright © 2016 Story5. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
@end
Objective-C类 | 说明 | 作用 |
---|---|---|
NSManagedObjectModel | 被管理对象模型类(Managed Object Model,MOM) | 系统中的实体,与数据库中的表等对象对应 |
NSPersistentStoreCoordinator | 持久化存储协调器类(Persistent Store Coordinator,PSC) | 1.在持久化对象存储之上提供了一个接口,可以把它看作数据库的连接. 2.执行所有底层的从对象到数据的转换,并负责打开和关闭数据文件. 3.它有3种持久化实现方式:Sqlite,二进制文件和内存形式 |
NSManagedObjectContext | 被管理对象上下文类(Managed Object Context,MOC) | 在上下文中可以查找/删除/插入对象/然后通过栈同步到持久化对象存储 |
(2)AppDelegate.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 "com.Story5.CoreDataDemo" 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 *modelURL = [[NSBundle mainBundle] URLForResource:@"CoreDataDemo" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
// The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it.
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
// Create the coordinator and store
//实例化PSC对象
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataDemo.sqlite"];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
/**为PSC对象添加新的持久化数据存储
* 其中addPersistentStoreWithType参数用于指定存储类型,其取值如下
* NSSQLiteStoreType,持久化数据类型为SQLite数据
* NSXMLStoreType,持久化数据类型为XML数据
* NSBinaryStoreType,持久化数据类型为二进制文件
* NSInMemoryStoreType,持久化数据类型为内存形式
*/
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:9999 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] initWithConcurrencyType:NSMainQueueConcurrencyType];
//设置PSC数据持久化类型
[_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();
}
}
}
Function | 返回类型 | 函数功能 |
---|---|---|
- (NSURL *)applicationDocumentsDirectory; | 返回类型为NSURL | 返回应用程序沙箱Documents目录 |
- (NSManagedObjectModel *)managedObjectModel; | 返回MOM对象 | |
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator | 返回PSC对象 | |
- (NSManagedObjectContext *)managedObjectContext | 返回MOC对象 | |
- (void)saveContext | 返回void | 用于保存被管理对象上下文 |
九.iCloud
1.iCloud基本概念
(1)iCloud云服务支持存储两种类型的数据,一种是iOS可识别的文档,另一种是字典对象.这些信息都可以实时存储在iCloud云中,也可以实时从iCloud云中获得数据
(2)iCloud云服务提供了一个区域,名为:Ubiquity Container.iCloud云服务与iOS设备通过这个区域来相互交换数据,从而达到备份或者更新的目的
(3)iOS系统在处理文件的时候会将文件分成小块,如果用户对文档进行了修改,那么iOS只会将修改的部分上传,达到流量网络的最佳使用
(4)iOS系统需要主动地请求同步某个文件,而且只能单独进行,如果需要同步多个文件的话,必须一个文件一个文件的进行同步