用NSData和NSFileManager保存内存中的对象
曾经接触过iOS开发,并且开发过两个应用,纵然青涩,也算是一断美好的回忆。转眼就已经一年多了!现在回过头来决定再次拿起iOS开发。
下面讲NSData:
NSdata的概念
1、使用文件时需要频繁地将数据读入一个临时存储区,它通常称为缓冲区
2、NSdata类提供了一种简单的方式,它用来设置缓冲区,将文件的内容读入缓冲区,或者将缓冲区内容写到一个文件。
3、对于32位应用程序,NSdata缓存最多2GB
4、我们有两种定义 NSData(不可变缓冲区),NSMutableData(可变缓冲区)
上面的描述有点片面,再补充一些:
NSData就是字节流的数据,它为字节流提供面向对象的存储空间,能够把一些字符串或图片等等一些非常复杂的数据类型转换成01字节流。在Objective-c中几乎所有的对象类型都可以转换成NSData(字符串也属于对象类型),基本数据类型需要先封装成对象,再转换成NSData。
在iOS中将对象序列化时,就需要将对象转换成为字节流数据即NSData类型的数据。
在要求将数据进行网络传输的场合,也需要将数据转化成为字节流才能进行传输。无论是向服务器写数据、还是从服务器返回的数据都应该是NSData类型的。
字定义保存内存中对象的方法
数据流图如下:
Object <-----> NSKeyedArchiver/NSKeyedUnarchiver <------> NSData <-----> NSString( file's name )
在Objective-c中要将对象转换成为NSData类型时,对象的类必须遵守NSCoding协议。NSCoding协议规定了两个必须实现的方法:initWithCoder:和encodeWithCoder:。initWithCoder:方法使用给定的状态初始化一个新对象,也称为反序列化,或者解码。encodeWithCoder:方法接收一个带状态的对象,并对其进行序列化,或者称为编码。您可以把encodeWithCoder:方法理解成将对象打包准备传输,把initWithCoder:方法理解成将接收到的数据解包成可用的对象。
许多常用的类,例如NSString、NSArray、NSNumber以及许多其他的类,已经实现了NSCoding协议。对于自定义的类,就需要用户自己实现NSCoding协议的initWithCoder:方法和encodeWithCoder:方法。这并不是很麻烦的事,可以看到一个实现NSCoding协议的例子:
@interface BigData : NSObject <NSCoding>
#pragma mark NSCoding
#define kTitleKey @"Title"
#define kRatingKey @"Rating" - (void) encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:_title forKey:kTitleKey];
[encoder encodeFloat:_rating forKey:kRatingKey];
} - (id)initWithCoder:(NSCoder *)decoder { NSString *title = [decoder decodeObjectForKey:kTitleKey];
float rating = [decoder decodeFloatForKey:kRatingKey];
return [self initWithTitle:title rating:rating]; }
在encodeWithCoder中,我们传入一个NSCoder对象,通过helper 方法把它编码成细小的数据片。这些helper方法有: encodeObject,encodeFloat,encodeInt等等。
在每一次encode的时候需要提供一个key用于以后decode的时候查找。通常,我们会对这些类加一个field,减一个field。为了让你的程序更健壮,在你decode一个field的时候,最好判断一下它的值是不是nil或者零,然后给它赋一个合适的默认值。
操作文件结构并保存
上代码,一个.m源文件:
#import "DataModel.h"
#import "NotePage.h" @implementation DataModel -(DataModel *)init{ [self loadPages];
return self;
} #pragma mark file storage
-(NSString*)documentsDirectory{ NSArray *paths =
NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentsDirectory = [paths firstObject];
return documentsDirectory;
} -(NSString*)filePathOfPage:(NotePage *)page{ return [[self documentsDirectory]
stringByAppendingPathComponent:[NSString stringWithFormat:@"page%d.plist",page.pageID]]; } -(void)savePage:(NotePage *)page{ NSMutableData *data = [[NSMutableData alloc]init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver
alloc]initForWritingWithMutableData:data];
[archiver encodeObject:page forKey:[NSString stringWithFormat:@"page%d.plist",page.pageID] ];
[archiver finishEncoding];
[data writeToFile:[self filePathOfPage:page] atomically:YES];
} -(void)removePage:(NotePage *)page{ NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *path = [self filePathOfPage:page ];
NSError * error;
[fileManager removeItemAtPath:path error:&error];
int index = [self.pages indexOfObject:page];
[self.pages removeObjectAtIndex:index]; } -(void)loadPages{ self.pages = [[NSMutableArray alloc]initWithCapacity:];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *documentsPath = [self documentsDirectory];
NSError *error;
NSArray *fileList = [fileManager contentsOfDirectoryAtPath:documentsPath error:&error]; NSString *path;
NSData * data;
NSKeyedUnarchiver *unarchiver;
for (int i = ; i< fileList.count ; i++) {
if([[fileList[i] substringWithRange:NSMakeRange(, )] isEqualToString:@"page"]){
path = [documentsPath stringByAppendingPathComponent:fileList[i]];
data = [[NSData alloc]initWithContentsOfFile:path];
unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
NotePage *page = [unarchiver decodeObjectForKey:fileList[i]];
[self.pages addObject:page];
}
}
} @end
保存对象:
进程执行一个archiver对象中的方法,把对象编码成字节流保存到一个data对象中;然后执行data对象中的方法,把它保存的字节流写到一个文件中。
取出对象:
进程执行一个data对象中的方法,把文件中的字节流读出来;然后执行一个unarchiver对象中的方法,把data对象中的字节流解码还原成对象。
注意,编码和解码方法在要保存的对象内。
参考上文中的数据流图。
JAVA中的文件操作
数据流图如下:
BufferedReader <-------> InputStreamReader <-------> FileInputStream <------> File ( file's pointer )
ps:
另外博主找了一篇文章,算是概述的形式回顾一下iPhone开发吧! http://www.cnblogs.com/jy578154186/archive/2013/02/27/2934881.html
用NSData和NSFileManager保存内存中的对象的更多相关文章
- JavaScript 变量类型 保存内存中的位置 和 引用
1. JavaScript变量 基本类型值在内存中占据固定大小的空间 因此被保存在栈内存中. 从一个变量向另一个变量复制基本来下的值 会创建这个值得一个副本. 引用类型的值是对象 保存在堆内存中. 包 ...
- 浅谈Java虚拟机内存中的对象创建,内存布局,访问定位
参考于 深入理解Java虚拟机 这里介绍HotSpot虚拟机(自带的虚拟机) 1.对象的创建 对于程序员来说,创建对象的方法: User user1 = new User(); User user2 ...
- java内存中的对象
前记:几天前,在浏览网页时偶然的发现一道以前就看过很多遍的面试题,题目是:“请说出‘equals’和‘==’的区别”,当时我觉得我还是挺懂的,在心里答了一点(比如我们都知道的:‘==’比较两个引用是否 ...
- 图解JVM在内存中申请对象及垃圾回收流程
http://longdick.iteye.com/blog/468368 先看一下JVM的内存模型: 从大的方面来讲,JVM的内存模型分为两大块: 永久区内存( Permanent space )和 ...
- linq读书笔记2-查询内存中的对象
上次我们说到了linq对数组内容的检索,自.net2.0以后,泛型成了很常见的一种应用技术,linq对泛型的检索也提供了完善的支持 如对list类型的支持,范例如下: class Program ...
- 内存中 OLTP - 常见的工作负荷模式和迁移注意事项(二)
----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<In-Memory OLTP – Comm ...
- PHP对象类型在内存中的分配
对象类型和整型.字符串等类型一样,也是PHP中的一种数据类型.都是在程序中用于存储不同类型数据使用的,在程序运行时它的每部分内容都要先加载到内存中再被使用.那么对象类型的数据在内存中是如何分配的呢?先 ...
- java中的各种数据类型在内存中存储的方式
原文地址:http://blog.csdn.net/aaa1117a8w5s6d/article/details/8251456 1.Java是如何管理内存的 java的内存管理就是对象的分配和释放问 ...
- 详解Python变量在内存中的存储
这篇文章主要是对python中的数据进行认识,对于很多初学者来讲,其实数据的认识是最重要的,也是最容易出错的.本文结合数据与内存形态讲解python中的数据,内容包括: 引用与对象 可变数据类型与不可 ...
随机推荐
- DelayedOperationPurgatory之purgatory的实现
purgatory的超时检测 当一个DelayedOpeartion超时(timeout)时,它需要被检测出来,然后调用它的回调方法.这个事情看起来很简单,但做好也并不容易. 0.8.x的Kafka的 ...
- Unity3D脚本中文系列教程(五)
http://dong2008hong.blog.163.com/blog/static/4696882720140302848544/?suggestedreading&wumii Unit ...
- Unity3D研究院之IOS全自动打包生成ipa
接着上一篇文章, 自动生成framework,这篇文章我把shell自动化打包ipa整理了一下,希望大家喜欢,嘿嘿.. 建议大家先看一下上一篇文章.http://www.xuanyusong.com/ ...
- DataGridView之行的展开与收缩
很多数据都有父节点与子节点,我们希望单击父节点的时候可以展开父节点下的子节点数据. 比如一个医院科室表,有父科室与子科室,点击父科室后,在父科室下面可以展现该科室下的所有子科室. 我们来说一下在Dat ...
- POJ 2251 Dungeon Master(广搜,三维,简单)
题目 简单的3d广搜,做法类似与 hdu 的 胜利大逃亡 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<str ...
- HDU 1540 / POJ 2892 Tunnel Warfare (单点更新,区间合并,求包含某点的最大连续个数)
题意:一条线上有n个点,D x是破坏这个点,Q x是表示查询x所在的最长的连续的点的个数,R是恢复上一次破坏的点. 思路:这题的关键是查询. 将被毁的村庄看成空位,当查询某个点的时候,如果我们知道它左 ...
- java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁
1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数 ...
- lintcode :Trailing Zeros 尾部的零
题目: 尾部的零 设计一个算法,计算出n阶乘中尾部零的个数 样例 11! = 39916800,因此应该返回 2 挑战 O(logN)的时间复杂度 解题: 常用方法: 也许你在编程之美中看到,通过求能 ...
- *[codility]Country network
https://codility.com/programmers/challenges/fluorum2014 http://www.51nod.com/onlineJudge/questionCod ...
- iOS开发--SWRevealViewController
SWRevealViewController 是一个比较好的实现Sliding功能的第三方类. 今天跟大家分享一下如何使用SWRevealViewController实现左右菜单滑动功能. 首先,在工 ...