iOS开发-数据持久化
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开发-数据持久化的更多相关文章
- IOS开发--数据持久化篇之文件存储(一)
前言:个人觉得开发人员最大的悲哀莫过于懂得使用却不明白其中的原理.在代码之前我觉得还是有必要简单阐述下相关的一些知识点. 因为文章或深或浅总有适合的人群.若有朋友发现了其中不正确的观点还望多多指出,不 ...
- IOS开发--数据持久化篇文件存储(二)
前言:个人觉得开发人员最大的悲哀莫过于懂得使用却不明白其中的原理.在代码之前我觉得还是有必要简单阐述下相关的一些知识点. 因为文章或深或浅总有适合的人群.若有朋友发现了其中不正确的观点还望多多指出,不 ...
- iOS开发——数据持久化Swift篇&使用Core Data进行数据持久化存储
使用Core Data进行数据持久化存储 一,Core Data介绍 1,Core Data是iOS5之后才出现的一个数据持久化存储框架,它提供了对象-关系映射(ORM)的功能,即能够将对象转化成 ...
- iOS开发——数据持久化Swift篇&(一)NSUserDefault
NSUserDefault //******************** 5.1 NSUserDefault和对象归档 func useNSUserDefault() { //通过单利来创建一个NSU ...
- iOS开发——数据持久化Swift篇&文件目录路径获取(Home目录,文档目录,缓存目录等)
文件目录路径获取(Home目录,文档目录,缓存目录等) iOS应用程序只能在自己的目录下进行文件的操作,不可以访问其他的存储空间,此区域被称为沙盒.下面介绍常用的程序文件夹目录: 1,Home ...
- iOS开发——数据持久化Swift篇&iCloud云存储
iCloud云存储 import UIKit class ViewController: UIViewController { override func viewDidLoad() { super. ...
- iOS开发——数据持久化OC篇&plist文件增删改查操作
Plist文件增删查改 主要操作: 1.//获得plist路径 -(NSString*)getPlistPath: 2.//判断沙盒中名为plistname的文件是否存在 -(BOOL ...
- iOS开发——数据持久化Swift篇&(四)CoreData
CoreData import CoreData class ViewController: UIViewController { override func viewDidLoad() { supe ...
- iOS开发——数据持久化Swift篇&(三)SQLite3
SQLite3 使用 //******************** 5.3 SQLite3存储和读取数据 func use_SQLite3() { //声明一个Documents下的路径 var db ...
随机推荐
- Android、iPhone和Java三个平台一致的加密工具
先前一直在做安卓,最近要开发iPhone客户端,这其中遇到的最让人纠结的要属Java.Android和iPhone三个平台加解密不一致的问题. 因为手机端后台通常是用JAVA开发的Web Servic ...
- Xcode中如何启用或禁用某些文件的ARC
经常会有工程中涉及到第三方的代码, 但这些代码有的是ARC的, 有的不是. 这样的话, 在与你的工程中集成的时候就会出现问题. 如果你的工程是开启ARC的, 那就需要对某些文件禁用ARC, (-fno ...
- SQL Server 2005的XML数据修改语言(XML DML)
转:http://www.microsoft.com/china/msdn/library/data/sqlserver/XMLDML.mspx?mfr=true 作为对XQuery语言的扩展,XML ...
- ubuntu鼠标突然不能使用的解决方法
今天发现鼠标(usb即插即用)不能用了,最后发现需要接通充电才可以!!!用电池的时候居然不可以用鼠标?
- java AES加密算法
package com.siro.tools; import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import j ...
- 1047图的深度优先遍历c语言
描述 图(graph)是数据结构 G=(V,E),其中V是G中结点的有限非空集合,结点的偶对称为边(edge):E是G中边的有限集合.设V={0,1,2,……,n-1},图中的结点又称为顶点(vert ...
- acdream 1056 (黑白染色)
题意:给你一些关系,每个关系是两只马的名字,表示这两个马不能在一个分组里,问你能否将这些马分成两组. 黑白染色,相邻的点染不同颜色.bfs搞即可,水题. /* * this code is made ...
- Tableau学习笔记之二
2张图片解析下Tableau 9.0界面的功能 1.数据加载界面: 2.数据分析界面:
- netty的入门
netty是什么? netty是一个基于NIO的通信框架,对于传统计算机,系统的瓶颈一直在输入输出设备上,计算速度超过IO速度,所以对于i o的性能提高异常重要. 什么是NIO? 非阻塞IO,N表示n ...
- Leetcode Largest Number c++ solution
Total Accepted: 16020 Total Submissions: 103330 Given a list of non negative integers, arrange t ...