iOS中四种最常用的将数据持久存储在iOS文件系统的机制

前三种机制的相同点都是需要找到沙盒里面的Documents的目录路径,附加自己相应的文件名字符串来生成需要的完整路径,再往里面创建、读取、写入文件

而第四种则是与委托有关,下面给出代码(有修改过的部分)。

这里做的示例是用四个TextField来显示内容,如图

一、属性列表(.plist)

//
// ViewController.m
// Persistence
//
// Created by Kim Topley on 7/31/14.
// Copyright (c) 2014 Apress. All rights reserved.
// #import "ViewController.h" @interface ViewController () @property (strong, nonatomic) IBOutletCollection(UITextField) NSArray *lineFields; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) {
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
for (int i = ; i < ; i++) {
UITextField *theField = self.lineFields[i];
theField.text = array[i];
}
} UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification
object:app];
} - (void)applicationWillResignActive:(NSNotification *)notification {
NSString *filePath = [self dataFilePath];
NSArray *array = [self.lineFields valueForKey:@"text"];
[array writeToFile:filePath atomically:YES];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} - (NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:];
return [documentsDirectory stringByAppendingPathComponent:@"data.plist"];
}
@end

ViewController.m

二、对象归档

1、遵循NSCoding协议

2、遵循NSCopying协议

3、对数据对象进行归档和取消归档

//
// FourLines.h
// Persistence
//
// Created by Jierism on 16/7/27.
// Copyright © 2016年 Jierism. All rights reserved.
// #import <Foundation/Foundation.h> @interface FourLines : NSObject<NSCoding,NSCopying> @property(copy,nonatomic)NSArray *lines; @end

FourLines.h

//
// FourLines.m
// Persistence
//
// Created by Jierism on 16/7/27.
// Copyright © 2016年 Jierism. All rights reserved.
// #import "FourLines.h" static NSString * const kLinesKey = @"kLinesKey"; @implementation FourLines #pragma mark - Coding
// 回复我们之前归档的对象
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.lines = [aDecoder decodeObjectForKey:kLinesKey];
}
return self;
} // 将所有实例变成编码成aCoder
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.lines forKey:kLinesKey];
} #pragma mark - Copying - (id)copyWithZone:(NSZone *)zone
{
// 新建一个新的FourLines对象,并将字符串数组复制进去
FourLines *copy = [[[self class] allocWithZone:zone] init];
NSMutableArray *linesCopy = [NSMutableArray array];
for ( id line in self.lines) {
[linesCopy addObject:[line copyWithZone:zone]];
}
copy.lines = linesCopy;
return copy;
} @end

FourLines.m

//
// ViewController.m
// Persistence
//
// Created by Jierism on 16/7/27.
// Copyright © 2016年 Jierism. All rights reserved.
// #import "ViewController.h"
#import "FourLines.h" static NSString * const kRootKey = @"kRootKey";
@interface ViewController () @property(strong,nonatomic)IBOutletCollection(UITextField) NSArray *lineFields; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. NSString *filePath = [self dataFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) { // 从归档中重组对象,对数据进行解码
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:filePath];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
FourLines *foueLines = [unarchiver decodeObjectForKey:kRootKey];
[unarchiver finishDecoding]; for (int i = ; i < ; i++) {
UITextField *theFiled = self.lineFields[i];
theFiled.text = foueLines.lines[i];
} } // 订阅,获取通知
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification
object:app];
} // 接收通知,告诉应用在终止运行或者进入后台之前保存数据
- (void) applicationWillResignActive:(NSNotification *)notification
{
NSString *filePath = [self dataFilePath]; // 将对象归档到data实例中
FourLines *fourLines = [[FourLines alloc] init];
fourLines.lines = [self.lineFields valueForKey:@"text"];
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:fourLines forKey:kRootKey];
[archiver finishEncoding];
[data writeToFile:filePath atomically:YES];
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} // 获取数据文件的完整路径(两步)
- (NSString *)dataFilePath
{
//1.查找Documents目录
NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [path objectAtIndex:];
//2.在后面附加数据文件的文件名
return [documentsDirectory stringByAppendingPathComponent:@"data.archive"];
} @end

ViewController.m

三、iOS的嵌入式关系数据库SQLite3

链接到数据库

在项目导航面板中顶部选中项目名称,按下图操作即可

1、创建或打开数据库

2、绑定变量

//
// ViewController.m
// SQLite Persistence
//
// Created by Jierism on 16/7/27.
// Copyright © 2016年 Jierism. All rights reserved.
// #import "ViewController.h"
#import <sqlite3.h> @interface ViewController () @property (strong,nonatomic) IBOutletCollection(UITextField) NSArray *lineFields; @end @implementation ViewController - (NSString *)dataFilePath
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:];
return [documentsDirectory stringByAppendingString:@"data.sqlite"];
} // 数据库在应用打开时才打开用于加载数据,加载完毕后会关闭
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. // 打开数据库,如果在打开时遇到问题则关闭,并抛出断言错误
sqlite3 *database;
if (sqlite3_open([[self dataFilePath] UTF8String],&database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(, @"Failed to open database");
} // 建立一个表来保存我们的数据,用IF NOT可以防止数据库覆盖现有数据:如果已有相同名的表则此命令不执行操作
NSString *createSQL = @"CREATE TABLE IF NOT EXISTS FIELDS "
"(ROW INTEGER PRIMAY KEY,FIELD_DATA TEXT);";
char *errorMsg;
if (sqlite3_exec (database,[createSQL UTF8String],NULL,NULL,&errorMsg) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(, @"Error creating table:%s",errorMsg);
} // 数据库中没一行包含一个整型(从0计数)和一个字符串(对应行的内容),加载内容
NSString *query = @"SELECT ROW,FIELD_DATA FROM FIELDS ORDER BY ROW";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database,[query UTF8String],-,&statement,nil) == SQLITE_OK) {
// 遍历返回的每一行
while (sqlite3_step(statement) == SQLITE_ROW) {
// 抓取行号存储在一个int变量中,抓取字段数据保存在char类型的字符串中
int row = sqlite3_column_int(statement,);
char *rowData = (char *)sqlite3_column_text(statement,);
// 利用从数据库中获取的值设置相应的字段
NSString *fieldValue = [[NSString alloc] initWithUTF8String:rowData];
UITextField *field = self.lineFields[row];
field.text = fieldValue;
}
// 关闭数据库连接
sqlite3_finalize(statement);
}
sqlite3_close(database); UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:app]; } - (void)applicationWillResignActive:(NSNotification *)notification
{
// 打开数据库
sqlite3 *database;
if (sqlite3_open([[self dataFilePath] UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(, @"Failed to open database");
} // 遍历数据库每一行,更新里面的数据
for (int i = ; i < ; i++) {
UITextField *field = self.lineFields[i];
char *update = "INSERT OR REPLACE INTO FIELDS (ROW,FIELD_DATA)"
"VALUES(?,?)";
char *errorMsg = NULL; // 声明一个指向语句的指针,然后为语句添加绑定变量,并将值绑定到两个绑定变量
sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(database, update, -, &stmt, nil) == SQLITE_OK) {
sqlite3_bind_int(stmt,,i);
sqlite3_bind_text(stmt,,[field.text UTF8String],-,NULL);
}
// 调用sqlite3_step来执行更新,检查并确定其运行正常,然后完成语句,结束循环
if (sqlite3_step(stmt) != SQLITE_DONE) {
NSAssert(, @"Error updating table:%s",errorMsg);
}
sqlite3_finalize(stmt);
}
// 关闭数据库
sqlite3_close(database);
} @end

ViewController.m

四、苹果公司提供的持久化工具Core Data

1、键-值编码(KVC)

2、在上下文中结合

3、创建新的托管对象

4、获取托管对象

//
// AppDelegate.h
// Core Data Persistance
//
// Created by Jierism on 16/7/27.
// Copyright © 2016年 Jierism. 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

AppDelegate.h

#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 "jie.Core_Data_Persistance" 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:@"Core_Data_Persistance" 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 _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Core_Data_Persistance.sqlite"];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
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] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_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();
}
}
} @end

AppDelegate.m

//
// ViewController.m
// Core Data Persistance
//
// Created by Jierism on 16/7/27.
// Copyright © 2016年 Jierism. All rights reserved.
// #import "ViewController.h"
#import "AppDelegate.h" static NSString * const kLineEntityName = @"Line";
static NSString * const kLineNumberKey = @"lineNumber";
static NSString * const kLineTextKey = @"lineText"; @interface ViewController () @property (strong,nonatomic) IBOutletCollection(UITextField) NSArray *lineFields; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. // 获取对应用委托的引用,使用这个引用获得为我们创建的托管对象上下文
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [appDelegate managedObjectContext]; // 创建一个获取请求并将实体描述传递给它,以便请求指导要检索的对象类型
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:kLineEntityName]; // 检索存储中所有Line对象,上下文返回库中每一个Line对象。确保返回的是有效数组,否则记录相应日志
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil) {
NSLog(@"There was an error!"); // 进行适当错误处理
} // 使用快熟枚举遍历已获取托管对象的数组,从中提取每个托管对象的lineNum和lineText的值,并用该信息更新用户界面上的文本框
for (NSManagedObject *oneObject in objects) {
int lineNum = [[oneObject valueForKey:kLineNumberKey] intValue];
NSString *lineText = [oneObject valueForKey:kLineTextKey]; UITextField *theField = self.lineFields[lineNum];
theField.text = lineText;
} // 在应用终止时获取通知,保存更改
UIApplication *app = [UIApplication sharedApplication];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:app];
} - (void)applicationWillResignActive:(NSNotification *)notification
{ // 与上面一样,获取对应用委托的引用,使用引用获取指向应用的默认托管对象上下文的指针
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
NSManagedObjectContext *context = [appDelegate managedObjectContext]; NSError *error; // 获得每一个字段对应的索引
for (int i = ; i < ; i++) {
UITextField *theField = self.lineFields[i]; // 为Line实体创建获取请求,创建一个谓词确认存储中是否已经有一个与这个字段对应的托管对象
NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:kLineEntityName];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"(%K = %d)",kLineNumberKey,i]; // 谓词
[request setPredicate:pred]; // 在上下文中执行后去请求,并检查objects是否为nil NSArray *objects = [context executeFetchRequest:request error:&error];
if (objects == nil) {
NSLog(@"There was an error!");
} // 声明一个指向NSManagedObject的指针并设置为nil。因为我们不知道要从持久存储中加载托管对象,还是创建新的托管对象。
// 因此,可以检查与条件匹配的返回对象。如果返回有效的对象就进行加载,否则就创建一个新的托管对象来保存这个字段的文本
NSManagedObject *theLine = nil;
if ([objects count] > ) {
theLine = [objects objectAtIndex:];
}else{
theLine = [NSEntityDescription insertNewObjectForEntityForName:kLineEntityName inManagedObjectContext:context];
} // 使用键-值编码(KVC)来设置行号以及此托管对象的文本
[theLine setValue:[NSNumber numberWithInt:i] forKey:kLineNumberKey];
[theLine setValue:theField.text forKey:kLineTextKey];
}
// 完成循环,保存更改
[appDelegate saveContext];
} @end

ViewController.m

iOS开发-数据持久化的更多相关文章

  1. IOS开发--数据持久化篇之文件存储(一)

    前言:个人觉得开发人员最大的悲哀莫过于懂得使用却不明白其中的原理.在代码之前我觉得还是有必要简单阐述下相关的一些知识点. 因为文章或深或浅总有适合的人群.若有朋友发现了其中不正确的观点还望多多指出,不 ...

  2. IOS开发--数据持久化篇文件存储(二)

    前言:个人觉得开发人员最大的悲哀莫过于懂得使用却不明白其中的原理.在代码之前我觉得还是有必要简单阐述下相关的一些知识点. 因为文章或深或浅总有适合的人群.若有朋友发现了其中不正确的观点还望多多指出,不 ...

  3. iOS开发——数据持久化Swift篇&使用Core Data进行数据持久化存储

    使用Core Data进行数据持久化存储   一,Core Data介绍 1,Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成 ...

  4. iOS开发——数据持久化Swift篇&(一)NSUserDefault

    NSUserDefault //******************** 5.1 NSUserDefault和对象归档 func useNSUserDefault() { //通过单利来创建一个NSU ...

  5. iOS开发——数据持久化Swift篇&文件目录路径获取(Home目录,文档目录,缓存目录等)

    文件目录路径获取(Home目录,文档目录,缓存目录等)   iOS应用程序只能在自己的目录下进行文件的操作,不可以访问其他的存储空间,此区域被称为沙盒.下面介绍常用的程序文件夹目录:   1,Home ...

  6. iOS开发——数据持久化Swift篇&iCloud云存储

    iCloud云存储 import UIKit class ViewController: UIViewController { override func viewDidLoad() { super. ...

  7. iOS开发——数据持久化OC篇&plist文件增删改查操作

    Plist文件增删查改   主要操作: 1.//获得plist路径    -(NSString*)getPlistPath: 2.//判断沙盒中名为plistname的文件是否存在    -(BOOL ...

  8. iOS开发——数据持久化Swift篇&(四)CoreData

    CoreData import CoreData class ViewController: UIViewController { override func viewDidLoad() { supe ...

  9. iOS开发——数据持久化Swift篇&(三)SQLite3

    SQLite3 使用 //******************** 5.3 SQLite3存储和读取数据 func use_SQLite3() { //声明一个Documents下的路径 var db ...

随机推荐

  1. sqlserver 导入/导出Excel

    --从Excel文件中,导入数据到SQL数据库中,很简单,直接用下面的语句: /*=========================================================== ...

  2. python模拟http请求

    下文主要讲述如何利用python自带的库模拟http请求,为以后利用python做API测试做准备. 只讲述模拟http的过程,具体到自己用的时候,要以自己的应用为准做出适当的调整. #!coding ...

  3. tomcat启动中提示 - consider increasing the maximum size of the cache

    tomcat启动过程中提示: org.apache.catalina.webresources.Cache.getResource Unable to add the resource at xxx ...

  4. TCP协议的一些问题

    1 连接握手三次 解释1:已失效的连接请求报文段 情况下如下:client发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达server.本 ...

  5. POJ 2096-Collecting Bugs(概率dp入门)

    题意: 有n种bug和s种系统bug,每天发现一种bug(可能已经发现过了)所有种bug被发现的概率相同,求所有bug被发现的期望天数. 分析: dp[i][j]发现i种bug,j种系统bug期望天数 ...

  6. <转>亲手缔造DNS体系,创建DNS私有根:DNS系列之六

    打造DNS私有根 我们现在已经从前面的博文中了解到了很多DNS的相关知识,今天我们用一个综合性的实验把前面的内容都串起来复习一下,这个有趣的实验就是DNS的私有根.私有根顾名思义是由个人或企业自行创建 ...

  7. 你是怎么理解“MVC”的

    MVC就是三个字母的组合,M-模型, V-视图, C-控制器. 这些在百度上随便一索就可以索到,而且网上对这三个部分的解释又过于笼统,使人没法完全理解MVC的含义.   这里我简单的谈谈我对MVC这三 ...

  8. BestCoder Round #76 解题报告

    DZY Loves Partition [思路] 贪心 [代码] #include <iostream> using namespace std; typedef long long ll ...

  9. Spark系列(七)Master中的资源调度

    资源调度 说明: Application的调度算法有两种,分别为spreadOutApps和非spreadOutApps spreadOutApps 在spark-submit脚本中,可以指定要多少个 ...

  10. 一站式Hadoop&Spark云计算分布式大数据和Android&HTML5移动互联网解决方案课程(Hadoop、Spark、Android、HTML5)V2的第一门课程

    Hadoop是云计算的事实标准软件框架,是云计算理念.机制和商业化的具体实现,是整个云计算技术学习中公认的核心和最具有价值内容. 如何从企业级开发实战的角度开始,在实际企业级动手操作中深入浅出并循序渐 ...