【转】基本数据持久性(一) 使用plist保存和读取数据
原文网址:http://www.it165.net/pro/html/201309/7170.html
想保存成绩、记录得分、保存账号密码等等?数据持久性可以做到这一点!这篇文章通过简单的程序,来分享一下如何使用plist来保存和读取数据,以供大家参考学习。
一、程序的主要功能
1. xib文件如图1所示。
图 1
2. 通过“保存”按钮将4个textField(ID、Name、Age、Class后面的输入框)的内容保存到plist文件中。
3.通过“读取”按钮将plist中的内容分别读取到4个textField中。
二、实现步骤
1.先创建一个Single ViewController的视图,命名为“使用plist保存和读取数据”。然后对xib文件进行操作,分别放置上4个Label、4个textField和2个Button,如图1所示。
2.对4个textField分别设置IBOutlet属性,对2个Button分别设置IBAction方法,并将其与xib文件相对应的控件关联。
3.在“ViewController.h”文件中,添加一个UITextFieldDelegate,以调用该协议中的“- (BOOL)textFieldShouldReturn:(UITextField *)textField”方法通过点击键盘的返回键来隐藏键盘(注:因为这个程序比较简单,该步骤不是必须的,可根据需要添加。因为在程序中,还会通过一个“- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event”的方法,使得点击屏幕时隐藏键盘)。做完2、3步骤以后的程序应该与下面的程序代码类似:
01.
#import <UIKit/UIKit.h>
02.
@interface ViewController : UIViewController<UITextFieldDelegate>
03.
//输入学生ID
04.
@property (retain, nonatomic) IBOutlet UITextField *stuID;
05.
//输入学生Name
06.
@property (retain, nonatomic) IBOutlet UITextField *stuName;
07.
//输入学生Age
08.
@property (retain, nonatomic) IBOutlet UITextField *stuAge;
09.
//输入学生Class
10.
@property (retain, nonatomic) IBOutlet UITextField *stuClass;
11.
//点击“保存”按钮时触发的操作
12.
- (IBAction)saveData:(id)sender;
13.
//点击“读取”按钮时触发的操作
14.
- (IBAction)loadData:(id)sender;
15.
@end
4.因为有textField,所以一般接下来我是先在“ViewController.m”文件里面写隐藏键盘的方法,以免忘记而在测试程序时因为键盘未隐藏而耽误事。在这里有两个方法来隐藏键盘,上面已经叙述过。如果采用“- (BOOL)textFieldShouldReturn:(UITextField *)textField”的方法来隐藏键盘,需要先在“- (void)viewDidLoad”方法里面设置代理,程序代码如下:
01.
- (
void
)viewDidLoad
02.
{
03.
[super viewDidLoad];
04.
//对4个textField设置代理
05.
_stuID.delegate = self;
06.
_stuName.delegate = self;
07.
_stuAge.delegate = self;
08.
_stuClass.delegate = self;
09.
//对4个textField设置代理的工作完成
10.
}
接下来就可以完成“- (BOOL)textFieldShouldReturn:(UITextField *)textField”的方法来隐藏键盘,代码如下:
01.
- (
BOOL
) textFieldShouldReturn:(UITextField *)textField
02.
{
03.
//因为xib文件中的4个输入框均为textField,
04.
//所以只要使该方法的参数textField取消第一响应状态
05.
//即可满足该项目中的所有textField当点击回车按钮时都取消第一响应状态
06.
[textField resignFirstResponder];
07.
//取消textField的第一响应状态,键盘隐藏
08.
return
YES;
09.
}
另外一种隐藏键盘的方法是当触摸屏幕时(非textField区域和键盘区域)键盘隐藏,因此可以使用“- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event”方法,代码如下:
1.
//点击非textField和键盘的屏幕后隐藏键盘
2.
- (
void
)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
3.
{
4.
[_stuID resignFirstResponder];
5.
[_stuName resignFirstResponder];
6.
[_stuAge resignFirstResponder];
7.
[_stuClass resignFirstResponder];
8.
}
5.以上的工作做完后,那么接下来要干什么呢?既然是要永久的保存数据,那么是否应该有一个永久保存数据的位置呢?是的,接下来我们要做的工作就是创建一个.plist的文件,并得到保存该.plist的文件的位置,以供我们保存和读取数据时候找到该路径。为此,我们创建一个方法,该方法返回一个NSString类型的值(文件的路径是一串字符串,这个很好理解吧?),当我们点击“保存”或者“读取”按钮时,能够读到这个路径下的数据。我写的这个方法名叫“- (NSString*)dataFilePath”,详细代码如下所示:
01.
//获取文件的路径
02.
- (NSString*)dataFilePath
03.
{
04.
//1.获取文件路径数组,这个是因为考虑到为mac编写代码的原因
05.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
//注意,括号里面的第一个元素是NSDocumentDirectory,而不是NSDocumentationDirectory
06.
//2.获取文件路径数组的第一个元素,因为我们只需要这一个
07.
NSString *documentPath = [paths objectAtIndex:0];
08.
//3.获取第2步得到的元素的字符串,并创建一个名为data.plist的.plist文件用于保存数据
09.
NSString *fileName = [documentPath stringByAppendingPathComponent:@
"data.plist"
];
10.
return
fileName;
11.
}
6.接下来,就是对数据的保存了。为此,需要在点击“保存”按钮的方法里面填写一些内容。该方法我命名为“- (IBAction)saveData:(id)sender”。首先,我们先尝试打开一下我们创建的plist文件,看看里面都有什么内容,也好与保存完数据后的做比较。为此,我们需要先在“- (IBAction)saveData:(id)sender”的方法里面获得一下保存文件的路径,并测试文件是否存在。如果文件存在,则输出文件的路径地址,以便我们查找.plist文件。详细代码如下:
01.
//点击保存按钮时触发的操作
02.
- (IBAction)saveData:(id)sender
03.
{
04.
//1.首先获取文件的存取路径
05.
NSString *pathStr = [self dataFilePath];
06.
//如果路径没有找到,则弹出来一个警告对话框
07.
if
(pathStr == nil)
08.
{
09.
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@
"警告"
message:@
"当前路径没有找到"
delegate:nil cancelButtonTitle:@
"取消"
otherButtonTitles: nil];
10.
[alert show];
11.
[alert release];
//因为我写这个程序没有采用ARC,所以必须要释放alert
12.
}
13.
else
//如果路径不为空
14.
{
15.
NSLog(@
"pathStr: %@"
, pathStr);
//输出路径的地址
16.
}
17.
//2.获得路径后,定义一个可变数组用来保存数据
18.
//用数组是因为.plist文件的root下的值的tepy只能是数组或者字典
19.
NSMutableArray *data = [[NSMutableArray alloc]init];
20.
//3.将4个textField里面写入的值放到data里面
21.
[data addObject:self.stuID.text];
22.
[data addObject:self.stuName.text];
23.
[data addObject:self.stuAge.text];
24.
[data addObject:self.stuClass.text];
25.
//4.将可变数组里面的数据按照路径写入文件
26.
[data writeToFile:pathStr atomically:YES];
27.
[data release];
//因为我写这个程序没有采用ARC,所以必须要释放data
28.
}
写好后,运行程序,当模拟器将程序加载完成后,不要填写任何textField里面的内容,直接点击“保存”按钮,此时我的程序得到的NSLog的值为:“2013-09-15 22:21:47.430 使用plist保存和读取数据[1293:c07] pathStr: /Users/apple/Library/Application Support/iPhone Simulator/6.1/Applications/656AB286-6184-4400-AB72-A1437DC52328/Documents/data.plist”。复制这句话里面的“/Users/apple/Library/Application Support/iPhone Simulator/6.1/Applications/656AB286-6184-4400-AB72-A1437DC52328/Documents/data.plist”,在电脑显示桌面的情况下,选择上面标签中的“前往——前往文件夹”,然后把刚才复制的那句话粘贴到里面,即可找到我们创建的“data.plist”文件,打开它,应该和图2所示的内容很像:
图 2
看到第2行的第二列的值了么?那是一个Array,你点击一下它,可以看到它只有两个值:Array和Dictionary。root下有4个属性,那是因为我们创建了一个保存4个textField的值的数组。此时Value一列中还没有值,因为我们还没有对textField做任何操作。接下来,就是完成这一步的工作了。
7.重新运行程序,当iOS模拟器加载程序成功后,如图3所示的内容分别填写4个textField,完成后点击“保存”按钮(我在xib里面把4个textField的字体都设置为居中了,这个不影响最终的结果的,可根据个人喜好等自定):
图 3
此时,再按照第6步所示的方法,找到保存完数据后的data.plist文件,打开它,此时它应该与图4所示的内容类似:
图 4
8.数据已经保存了,那么是否可以读取呢?为此,我们先编写完成“读取”按钮的方法。我在程序里面给它命名为“- (IBAction)loadData:(id)sender”。首先,还是需要先把保存数据的路径给找出来,然后把该路径里面的内容分别赋值给4个textField。详细代码如下所示:
01.
//点击读取按钮时触发的操作
02.
- (IBAction)loadData:(id)sender
03.
{
04.
//1.首先获取文件的存取路径
05.
NSString *pathStr = [self dataFilePath];
06.
07.
//2.判断文件是否存在,如果存在用一个数组取出文件中数据
08.
//并分别赋值给4个textField
09.
if
([[NSFileManager defaultManager]fileExistsAtPath:pathStr])
10.
{
11.
//获取文件存取路径下的文件
12.
NSArray *data = [[NSArray alloc]initWithContentsOfFile:pathStr];
13.
14.
//将获取到的文件分别赋值给4个textField
15.
self.stuID.text = [data objectAtIndex:0];
16.
self.stuName.text = [data objectAtIndex:1];
17.
self.stuAge.text = [data objectAtIndex:2];
18.
self.stuClass.text = [data objectAtIndex:3];
19.
20.
[data release];
//因为我写这个程序没有采用ARC,所以必须要释放data
21.
}
22.
}
然后,通过Xcode重新运行代码,当iOS模拟器加载程序成功后,直接点击“读取”按钮,此时,你会发现,得到的内容和图3显示的一模一样(请忽略模拟器上的时间吧)——刚刚存的数据被成功加载回来了!是的,完成了简单的基本数据持久化。
9.至此,我们的程序就算是完成了。如果你没有采用ARC来写这个程序,那么,请记得在“- (void)dealloc”方法里面释放你创建的内存——如果你采用的是直接从xib拖动控件到ViewController.h文件里面生成相应的属性和方法,那么Xcode已经为你写好了“- (void)dealloc”方法了,你无须理会。
10.如果你想彻底清除data.plist里面保存的数据,直接将iOS模拟器“还原内容和设置”即可。
三、小测验
在上述保存了图3所示的内容以后并且没有将iOS模拟器“还原内容和设置”的情况下,再设置一组信息如图5所示,点击“保存”按钮后,按照第二大条第6步骤的方法,看看data.plist里面保存的是什么值?
图 5
请想想这是为什么吧?以及如何可以改进呢?也许,你并不想只保存一组数据,是吧?
如果你有好的想法,欢迎告知与大家,与大家一起探讨。
P.S.我已将完整的代码放到附件了(再次强调一下,我没有使用ARC),如果有需要的朋友,欢迎下载参考。如对我的代码有改进,还请告知与我,我好更新本博客供其他人参考,感谢!
【转】基本数据持久性(一) 使用plist保存和读取数据的更多相关文章
- [MISS静IOS开发原创文摘]-AppDelegate存储全局变量和 NSUserDefaults standardUserDefaults 通过模型保存和读取数据,存储自定义的对象
由于app开发的需求,需要从api接口获得json格式数据并保存临时的 app的主题颜色 和 相关url 方案有很多种: 1, 通过AppDelegate保存为全局变量,再获取 2,使用NSUSerD ...
- 如何保存或读取数据(到android的data目录)利用context获取常见目录可优化代码
读取用户信息 当然这里可以有多种返回值 非硬性
- iOS 保存、读取与应用状态
固化 对于大多数iOS应用,可以将其功能总结为:提供一套界面,帮助用户管理特定的数据.在这一过程中,不同类型的对象要各司其职:模型对象负责保存数据,视图对象负责显示数据,控制器对象负责在模型对象与视图 ...
- tensorflow:保存与读取网络结构,参数
训练一个神经网络的目的是啥?不就是有朝一日让它有用武之地吗?可是,在别处使用训练好的网络,得先把网络的参数(就是那些variables)保存下来,怎么保存呢?其实,tensorflow已经给我们提供了 ...
- iOS中plist的创建,数据写入与读取
iOS中plist的创建,数据写入与读取 Documents:应用将数据存储在Documents中,但基于NSuserDefaults的首选项设置除外Library:基于NSUserDefaults的 ...
- iOS——plist的创建,数据写入与读取
iOS中plist的创建,数据写入与读取 Documents:应用将数据存储在Documents中,但基于NSuserDefaults的首选项设置除外Library:基于NSUserDefaults的 ...
- IOS学习笔记之获取Plist文件读取数据
@property(nonatomic,strong) NSArray *pic; //创建数组属性 @property(nonatomic,assign) int index; //创建索引属性 @ ...
- Protobuf for Python测试保存和读取文件
安装pip, setuptools, and wheel 如果已经从python.org,安装啦Python 2 >=2.7.9 or Python 3 >=3.4 ,那么就已经有啦pip ...
- Apache Spark源码走读之20 -- ShuffleMapTask计算结果的保存与读取
欢迎转载,转载请注明出处,徽沪一郎. 概要 ShuffleMapTask的计算结果保存在哪,随后Stage中的task又是如何知道从哪里去读取的呢,这个过程一直让我困惑不已. 用比较通俗一点的说法来解 ...
随机推荐
- 浅谈mysql中不同事务隔离级别下数据的显示效果
事务的概念 事 务是一组原子性的SQL查询语句,也可以被看做一个工作单元.如果数据库引擎能够成功地对数据库应用所有的查询语句,它就会执行所有查询,如果任何一条查 询语句因为崩溃或其他原因而无法执行,那 ...
- C++学习 (转)
1.把C++当成一门新的语言学习: 2.看<Thinking In C++>: 3.看<The C++ Programming Language>和<Inside The ...
- 解决在管理wordpress时权限不足的问题
我的wordpress网站的运行环境是自己手动搭建的lamp环境,在管理wordpress时经常遇到因没有足够的权限而无法执行某些操作.在linux上的权限不足的问题无外乎有两个原因,一个是wordp ...
- google map android api v2
我在这主要列举几个需要注意的问题: 1.需要注意使用的api版本的问题,例如google map android api v1就和v2差别很大,包括申请key方面,所以在搜索资料的时候一定注意版本问题 ...
- 配置 Struts2 Hello World
http://javaweb.group.iteye.com/group/wiki/1505-struts2-under-helloworld---how-to-make-the-first-of-t ...
- 折腾了一早上的C# WPF ListView+Grid 实现图片+文字 自动换行排列 类似Windows资源管理器效果
<ListBox Name="lstFileManager" Background ="Transparent" ItemsSource="{B ...
- Java学习-数组
1.数组的是Object的直接子类,它属于“第一类对象”,但是它又与普通的java对象存在很大的不同,类名为:[I 一维数组:[I 二维数组:[[I 三维数组:[[[I 2.[代表了数组的维度,一个[ ...
- Java学习--Equals与“==”
在Java规范中,它对equals()方法的使用必须要遵循如下几个规则: equals 方法在非空对象引用上实现相等关系: 1.自反性:对于任何非空引用值 x,x.equals(x) 都应返回 tru ...
- 拖尾渲染器 Trail Renderer
拖尾渲染器(Trail Renderer)用于制作跟在场景中的物体后面的拖尾效果来代表它们在到处移动. 必须给Materials一个材质渲染器设置的Colors才有效. 展示自己的一个demo...
- CoreText实现图文混排之点击事件-b
CoreText实现图文混排之点击事件 主要思路 我们知道,CoreText是基于UIView去绘制的,那么既然有UIView,就有 -(void)touchesBegan:(NSSet<UIT ...