Objective-C之数据持久化-属性列表

来源:互联网 发布:java web工作内容 编辑:程序博客网 时间:2024/05/17 22:18

泛舟湖上,波光闪,迷了眼
夜幕降临,珠光闪,醉了心

(图引自百度图库)

上一站已介绍了数据持久化,不再赘述,这站我们开始一起学习属性列表、对象归档、SQLite数据库和Core Data。

这一站我们讲解属性列表。

属性列表我们之前其实已经有所接触,即plist文件,全称property list。属性列表文件是一种XML文件,Foundation框架中的数组和字典等都可以与属性列表文件互相转换。一般用于应用配置,也可以存储少量数据。在以前接触过的应用中比较常见的是存储配置信息、消息等,这样我们修改配置等时,不用去去修改代码,直接对plist文件进行增删改即可。

我们以第9站导航控制器的demo为例介绍。

属性列表文件可以有多个,另外在工程创建时会自动创建一个Info.plist文件(文件名大小写敏感),它包含了一些应用重要的配置元信息。Info.plist文件多数情况下是以UTF-8进行编码,并且其内部的配置内容其实是以XML格式进行组织。该文件不可删除,只会有一个,在以前的版本中,一般是“工程名-Info.plist",在工程中图中所标注位置指定。

1

现在我们来看如何创建一个plist文件:(一般放在Resource文件夹中)

2

(Resource文件是自己创建的,也可以通过”File→New→File“)

5

选择Resource中的Property List,点击Next:

3

输入plist名称,在此我根据所存储内容命名为Country.plist,选择要创建的位置,我们选择Resource文件,Create:

4

60

自此创建完成,我们自己创建的plist文件属于资源文件,一般会创建一个Resource文件夹存放,与其他系统应用类似。生成应用后会存放在Bundle中。

Plist结构:

plist最外层根节点有两种类型,数组和字典,根据需要而定,使用Dictionary居多。

1

选中行,该行会出现+图标,点击会在下方生成一个新的节点,如图(Root节点是不可删除的根节点):

12

如下图,plist中节点类型由Array、Dictionary、Boolean、Data、Date、Number、String:

2

注:除Root根节点以外,其他节点如果是Array或Dictionary,左侧箭头展开时点“+”是增加的子节点,左侧箭头收缩状态时点“+”是增加的兄弟节点。

如图为不同类型的节点,其中Array和Dictionary和在代码中对象一样可以嵌套:

11

擅长xml的也可以作为xml编辑,如图:

1

显示如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Array</key>
<array>
<string>I am belong to a array.</string>
</array>
<key>String</key>
<string>I am a string.</string>
<key>Boolean</key>
<true/>
<key>Data</key>
<data></data>
<key>Date</key>
<date>2015-09-14T23:43:47Z</date>
<key>Number</key>
<integer>123</integer>
<key>Dictionary</key>
<dict>
<key>key1</key>
<string>Iam belong to a dictionary.</string>
</dict>
</dict>
</plist>

通过代码进行增删改查:

之前做好的Country.plist:第一层是根节点类型为Dictionary,第二层是洲,key值为洲名,类型为Array,数组中存放的时Dictionary数组,每个item为该洲的一个国家,每个Dictioanry元素中固定存的是字符串类型的name,flag,capital,map,其中flag和map存放的是资源名。

1

先说明,我们创建在工程中的plist资源文件是只读的,生成程序app后所在位置是应用本身,不能通过代码去修改。如果我们想要通过代码去修改,需要放到沙盒下去读写。

app中的plist读取:

// 工程中创建的plist文件存放在app程序包路径,通过NSBundle对象的pathForResource:ofType:方法取得,第一个参数是文件名,第二个参数是后缀名。
// app包中的资源文件都可以通过它取得。
NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"Country" ofType:@"plist"];
// NSDictionary和NSArray类自带函数可以直接从plist文件读取Root,使用NSDictionary还是NSArray取决于plist中Root是Dictionary还是Array.
NSDictionary *continentList = [NSDictionary dictionaryWithContentsOfFile:resourcePath];

读出来后,就和平时的字典数组一样处理了,方式和安卓,Java等类似。针对上面这个例子,在导航控制器章中已有代码。

另:NSDictionary相关方法:

读取:
+ (NSDictionary *)dictionaryWithContentsOfFile:(NSString *)path;
+ (NSDictionary *)dictionaryWithContentsOfURL:(NSURL *)url;
- (NSDictionary *)initWithContentsOfFile:(NSString *)path;
- (NSDictionary *)initWithContentsOfURL:(NSURL *)url;
写入:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atomically;

NSArray相关方法:

读取:
+ (NSArray *)arrayWithContentsOfFile:(NSString *)path;
+ (NSArray *)arrayWithContentsOfURL:(NSURL *)url;
- (NSArray *)initWithContentsOfFile:(NSString *)path;
- (NSArray *)initWithContentsOfURL:(NSURL *)url;
写入:
- (BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
- (BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atomically;

plist读取写入:(前面说过,app中的plist只能读,不能通过代码修改,所以需要拷贝一份到沙盒下去操作)

读:

// 获取NSFileManager单例
NSFileManager *fileManager = [NSFileManager defaultManager];

// 获取沙盒documents路径,沙盒路径获取代码上一篇已详细讲过。
NSString *document = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

// 手动拼接出plist文件路径,stringByAppendingPathComponent方法会在document和参数之间自动添加"/"
NSString *plistPath = [document stringByAppendingPathComponent:@"Country.plist"];

//判断该路径是否存在,即documents下是否有Country.plist文件。如果没有则将app下的Country.plist原版文件拷贝过来。
if (![fileManager fileExistsAtPath:plistPath]) {
NSString *defaultPlistPath = [[NSBundle mainBundle] pathForResource:@"Country" ofType:@"plist"];
NSError *error;
// 使用NSFileManager对象的copyItemAtPath:toPath:error:方法拷贝。
BOOL success = [fileManager copyItemAtPath:defaultPlistPath toPath:plistPath error:&error];
if (!success) {
NSAssert1(0, @"copy出错:%@.", [error localizedDescription]);
}
}

NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath];

删除、添加和修改与查询前面一样,只是对读取出来的dictionary进行增删改后,再重新写入。

以添加为例说明,删除和修改不再说明(查找到指定节点修改或删除后,重新写入)

// 读取同上

NSMutableArray * array = [dictionary objectForKey:@"大洋洲"];
NSMutableDictionary *country = [[NSMutableDictionary alloc] init];
[country setObject:@"Fiji" forKey:@"name"];
[country setObject:@"Flag Fiji.png" forKey:@"flag"];
[country setObject:@"Suva" forKey:@"capital"];
[country setObject:@"Map Fiji.png" forKey:@"map"];
[array addObject:country];
[dictionary setObject:array forKey:@"大洋洲"];

// writeToFile:atomically:将字典或数组写入到指定属性列表文件中,第一个参数是目标文件路径,第二个参数为是否使用辅助文件,如果为YES,则先写入到一个辅助文件,再将辅助文件重命名为目标文件,如果为NO,直接写入目标文件。完全覆盖。
[dictionary writeToFile:plistPath atomically:YES];

0 0
原创粉丝点击