IOS开发——UI进阶篇(十一)应用沙盒,归档,解档,偏好设置,plist存储,NSData,自定义对象归档解档

1、iOS应用数据存储的常用方式
XML属性列表(plist)归档
Preference(偏好设置)
NSKeyedArchiver归档(NSCoding)
SQLite3
Core Data

2、应用沙盒
每个iOS应用都有自己的应用沙盒(应用沙盒就是文件系统目录),与其他文件系统隔离。应用必须待在自己的沙盒里,其他应用不能访问该沙盒
应用沙盒的文件系统目录,如下图所示(假设应用的名称叫Layer)
模拟器应用沙盒的根路径在: (apple是用户名, 8.0是模拟器版本)
/Users/apple/Library/Application Support/iPhone Simulator/8.0/Applications

3、应用沙盒结构分析
应用程序包:(上图中的Layer)包含了所有的资源文件和可执行文件
Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录

tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录

Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据

Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录

4、plist文件
1.plist存储,生成一个plist文件.
2.plist不是数组就是字典,plist存储就是用来存储字典或者数组.
注意:Plist不能存储自定义对象

5、应用沙盒目录的常见获取方式
// 获取沙盒路径
1、NSHomeDirectory()

2、tmp:NSString *tmp = NSTemporaryDirectory();

3、Library/Caches:(跟Documents类似的2种方法)
利用沙盒根目录拼接”Caches”字符串
利用NSSearchPathForDirectoriesInDomains函数(将函数的参数改为:NSCachesDirectory即可)

// directory:获取哪个文件夹
    // domainMask:在哪个范围内搜索,NSUserDomainMask:表示在用户的手机上查找
    // expandTilde:是否展开全路径 YES:表示展开全路径 NO:不会展开全路径,会把应用沙盒的路径用波浪号(~)代替
    // 获取到Caches文件夹路径
    NSString *cachePath = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];

    // 拼接文件名
    NSString *filePath = [cachePath stringByAppendingPathComponent:@"arr.plist"];

    // 1、存储plist,File:文件的全路径
    [arr writeToFile:filePath atomically:YES];
    // 2、读取plist,之前是什么类型存储的,读取也是什么
    NSArray *arr = [NSArray arrayWithContentsOfFile:filePath];

4、Library/Preference:通过NSUserDefaults类存取该目录下的设置信息

6、属性列表
属性列表是一种XML格式的文件,拓展名为plist
如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,就可以使用writeToFile:atomically:方法直接将对象写到属性列表文件中

7、属性列表-归档NSDictionary
将一个NSDictionary对象归档到一个plist属性列表中

// 将数据封装成字典
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"母鸡" forKey:@"name"];
[dict setObject:@"15013141314" forKey:@"phone"];
[dict setObject:@"27" forKey:@"age"];
// 将字典持久化到Documents/stu.plist文件中
[dict writeToFile:path atomically:YES];

8、属性列表-恢复NSDictionary

读取属性列表,恢复NSDictionary对象

9、偏好设置
很多iOS应用都支持偏好设置,比如保存用户名、密码、字体大小等设置,iOS提供了一套标准的解决方案来为应用加入偏好设置功能
每个应用都有个NSUserDefaults实例,通过它来存取偏好设置
比如,保存用户名、字体大小、是否自动登录
以字典的形式进行偏好设置,用法跟字典一样.
偏好设置好处: 1.不需要关心文件名 2.快速进行键值对存储 3.直接存储基本数据类型

保存:

    // 获取单例
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    // @"123" key:pwd
    [defaults setObject:@"123" forKey:@"pwd"];

    // bool
    [defaults setBool:YES forKey:@"isOn"];

    // int
    [defaults setInteger:10 forKey:@"num"];

读取也很简单

    // 利用NSUserDefaults单例
   NSString *pwd = [[NSUserDefaults standardUserDefaults] objectForKey:@"pwd"];
   NSInteger i = [[NSUserDefaults standardUserDefaults] integerForKey:@"num"];

10、NSData
使用archiveRootObject:toFile:方法可以将一个对象直接写入到一个文件中,但有时候可能想将多个对象写入到同一个文件中,那么就要使用NSData来进行归档对象
NSData可以为一些数据提供临时存储空间,以便随后写入文件,或者存放从磁盘读取的文件内容。可以使用[NSMutableData data]创建可变数据空间
(图)

1)NSData-归档2个Person对象到同一文件中

归档(编码)

// 新建一块可变数据区
NSMutableData *data = [NSMutableData data];
// 将数据区连接到一个NSKeyedArchiver对象
NSKeyedArchiver *archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
// 开始存档对象,存档的数据都会存储到NSMutableData中
[archiver encodeObject:person1 forKey:@"person1"];
[archiver encodeObject:person2 forKey:@"person2"];
// 存档完毕(一定要调用这个方法)
[archiver finishEncoding];
// 将存档的数据写入文件
[data writeToFile:path atomically:YES];

2)NSData-从同一文件中恢复2个Person对象

恢复(解码)

// 从文件中读取数据
NSData *data = [NSData dataWithContentsOfFile:path];
// 根据数据,解析成一个NSKeyedUnarchiver对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
Person *person1 = [unarchiver decodeObjectForKey:@"person1"];
Person *person2 = [unarchiver decodeObjectForKey:@"person2"];
// 恢复完毕
[unarchiver finishDecoding];

3)利用归档实现深复制
比如对一个Person对象进行深复制

// 临时存储person1的数据
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];
// 解析data,生成一个新的Person对象
Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
// 分别打印内存地址
NSLog(@"person1:0x%x", person1); // person1:0x7177a60
NSLog(@"person2:0x%x", person2); // person2:0x7177cf0

归档:
存储自定义对象

    Person *p = [[Person alloc] init];
    p.age = 18;
    p.name = @"a";
    // 获取tem文件夹路径
    NSString *tempPath = NSTemporaryDirectory();
    // 拼接文件名
   NSString *filePath = [tempPath stringByAppendingPathComponent:@"person.data"];
    // NSKeyedArchiver专门用来做自定义对象归档
    [NSKeyedArchiver archiveRootObject:p toFile:filePath];

在person.m

// 什么时候调用:当一个对象要归档的时候就会调用这个方法归档
// 作用:告诉苹果当前对象中哪些属性需要归档
- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:_name forKey:@"name"];
    [aCoder encodeInt:_age forKey:@"age"];
}

解档:

    // 获取tem文件夹路径
    NSString *tempPath = NSTemporaryDirectory();

    // 拼接文件名
    NSString *filePath = [tempPath stringByAppendingPathComponent:@"person.data"];
   // 解档
   Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];

什么时候调用:当一个对象要解档的时候就会调用这个方法解档

// 作用:告诉苹果当前对象中哪些属性需要解档
// initWithCoder什么时候调用:只要解析一个文件的时候就会调用
- (id)initWithCoder:(NSCoder *)aDecoder
{
    #warning  [super initWithCoder]
    // 这里不能用[super initWithCoder],什么时候调用[super initWithCoder:aDecoder]:只要父类遵守了NSCoding协议,就调用
    if (self = [super init]) {
        // 解档
        // 注意一定要记得给成员属性赋值
      _name = [aDecoder decodeObjectForKey:@"name"];
      _age = [aDecoder decodeIntForKey:@"age"];
    }
    return self;
}

11.数据存储(数据持久化)
1> 介绍iOS数据存储的5种方式
2> 介绍应用沙盒(应用程序的文件夹)
• 如何找到应用沙盒的路径?首先需要显示隐藏文件。
• 点击前往->个人->资源库->Application Support->iPhone Simulator->7.1->里面全是应用沙盒
3> 应用沙盒怎么多文件夹保存,在哪个文件夹。介绍沙盒里的每一个文件夹。

12.plist存储
• 把一些系统自带的OC对象生成pilst文件存储起来。
1> 了解数据存储:数据存储一般有两个操作,一个存,一个取。拖两个按钮,一个用来存,一个用来取
2> plist存储原理:
• 只要有writeToFile的对象,就能进行plist存储,调用writeToFile就能自动生成plist格式的文件。
• 一般常用的Foundation对象都有这个方法,数组,字典,字符串等
3> 如何写入到沙盒,需要获取沙盒路径。
• 获取Documents路径
• 拼接文件名,因为数据是写入到文件中,不是写入到文件夹中。路径之间通过/分开的,为了避免自己写/,会用stringByAppendingPathCompent,自动在文件夹与文件之间添加/。
4> 如何读取,存储是什么类型存储,读取出来也是什么类型,直接用存储的类型,解析文件就好,用ContentsOfFile解析。
5> 注意plist存储,不能存储自定义对象,会失败的。

13> 偏好设置
1> 什么是偏好设置存储:就是保存一些基本的信息,账号,密码,状态。
2> 偏好设置原理:不需要关心文件名,直接通过NSUserDefaults操作,默认就存到偏好设置里面了。
• 通过NSUserDefaults就能直接访问软件的偏好设置(Library/Preferences)
3> 怎么利用偏好设置存储?利用NSUserDefaults调用setObject:forKey存储。
• 偏好设置底层实现原理:底层其实就是利用一个字典,存储一些键值对。
• 偏好设置好处:能快速存储一些键值对,如果用字典去存储,还需要获取文件名比较麻烦。
• 偏好设置坏处:不能及时存储,需要做同步操作,把内存中的数据同步到硬盘上。
4> 怎么利用偏好设置读取?和字典一样,根据刚刚存储的Key读取。

14> 自定义对象归档(归档:数据存储)
1> 自定义对象如何归档:用NSKeyedArchiver,调用archiveRootObject:toFile:方法,需要传一个对象,自定义一个对象,传进去。
• 会报错,说对象没有encodeWithCoder方法,说明归档的时候默认会调用这个方法,去实现这个方法。
• 默认打不出encodeWithCoder,必须遵守NSCoding协议才能实现这个方法。
• encodeWithCoder什么时候调用:对象归档时候调用
• encodeWithCoder作用:告诉系统对象里的哪些属性需要归档,怎么去归档,根据一个key去归档,目的就是以后取的时候,也根据这个key去取数据。
2> 自定义对象如何解档:用NSKeyedUnarchiver,调用unarchiveObjectWithFile方法,需要传一个文件名。
• 会报错,说对象没有initWithCoder方法,说明解档的时候默认会调用这个方法,去实现这个方法。
• initWithCoder什么时候调用:对象解档时候调用
• initWithCoder作用:告诉系统对象里的哪些属性需要解档,怎么去解档,根据之前存储的key去解档
• initWithCoder是一个初始化方法,需要先初始化父类的,但是不能调用[super initWithCoder:],因为父类NSObject没有遵守NSCoding协议。
3> initWithCoder什么时候需要调用[super initWithCoder:]
• initWithCoder原理:只要解析文件就会调用,xib,storyboard都是文件,因此只要解析这两个文件,就会调用initWithCoder。
• 因此如果在storyboard使用自定义view,重写initWithCoder方法,一定要调用[super initWithCoder:],因为只有系统才知道怎么解析storyboard,如果没有调用,就解析不了这个文件。

时间: 2024-10-24 21:06:55

IOS开发——UI进阶篇(十一)应用沙盒,归档,解档,偏好设置,plist存储,NSData,自定义对象归档解档的相关文章

IOS开发——UI进阶篇(十五)Quartz2D介绍

一.Quartz2D简介 1.什么是Quartz2DQuartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作绘制图形 : 线条\三角形\矩形\圆\弧等绘制文字绘制\生成图片(图像)读取\生成PDF截图\裁剪图片自定义UI控件 2.Quartz2D实例Quartz 2D能做很多强大的事情,例如 裁剪图片 涂鸦\画板 手势解锁 报表:折线图\饼状图\柱状图 二.自定义view 1.Quartz2D在iOS开发中的价值为了便于搭建美观的UI界面,iOS提供了UI

IOS开发——UI进阶篇(十七)CALayer,核心动画基本使用

一.CALayer简介 1.CALayer在iOS中,文本输入框.一个图标等等,这些都是UIView你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层 @property(nonatomic,readonly,retain) CALayer *layer; 当UIView需

IOS开发——UI进阶篇(十六)Quartz2D实战小例子

一.画线 只有在drawRect中才能获取到跟view相关联的上下文 - (void)drawRect:(CGRect)rect {} 一条线 // 1.获取跟当前View相关联的layer上下文(画板) // 总结:目前获取的所有上下文都是以UIGraphics开头 // CGContextRef:上下文类型 // CG:CoreGraphics Ref:引用 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.绘制内容,拼接路径 //

IOS开发——UI进阶篇(七)程序启动原理

一.Info.plist常见的设置 1.建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 在旧版本Xcode创建的工程中,这个配置文件的名字就叫“Info.plist” 项目中其他Plist文件不能带有“Info”这个字眼,不然会被错认为是传说中非常重要的“Info.plist” 项目中还有一个InfoPlist.strings的文件,跟Info.plist文件的本地化相关 2.常见属性

IOS开发——UI进阶篇(十二)事件处理,触摸事件,UITouch,UIEvent,响应者链条,手势识别

触摸事件 在用户使用app过程中,会产生各种各样的事件 一.iOS中的事件可以分为3大类型 触摸事件加速计事件远程控制事件 响应者对象在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件.我们称之为“响应者对象” UIApplication.UIViewController.UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件 二.UIResponder UIResponder内部提供了以下方法来处理事件触摸事件- (v

IOS开发——UI进阶篇—UITableView,索引条,汽车数据展示案例

一.什么是UITableView 在iOS中,要实现展示列表数据,最常用的做法就是使用UITableViewUITableView继承自UIScrollView,因此支持垂直滚动,而且性能极佳 UITableView的两种样式UITableViewStylePlainUITableViewStyleGrouped 二.如何展示数据 UITableView需要一个数据源(dataSource)来显示数据 UITableView会向数据源查询一共有多少行数据以及每一行显示什么数据等 没有设置数据源的

iOS开发——UI进阶篇(十九)UISearchBar控件简介

最近用到搜索功能.总结一下 搜索,无疑可以使用UISearchBar控件! 那就先了解一下UISearchBar控件吧! UISearchBar控件就是要为你完成搜索功能的一个专用控件.它集成了很多你意想不到的功能和特点! 首先,还是来普及一下UISearchBar控件API相关的属性和方法吧! UISearchBar属性相关 _searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];// 初始化,不解释 [self.searchBa

IOS开发——UI进阶篇(十)导航控制器、plist存储、微博详情页

一.导航控制器出栈 1.initWithRootViewController本质 UIViewController *vc = [[OneViewController alloc] init]; // 创建导航控制器 // 导航控制器必须要有一个根控制器 UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; // 会调用push方法 // initWithRoot

IOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果

一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // rect:裁剪图片的尺寸,传递是像素 CGImageRef norImage = CGImageCreateWithImageInRect(norBigImage.CGImage, clipRect); 2.每次点击按钮立马变为选中状态,并且取消上次的按钮的选中状态 当然还要重写- (void)setH