phone开发基础教程

前端之家收集整理的这篇文章主要介绍了phone开发基础教程前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Iphone开发基础教程》第九章 导航控制器和表视图(2009-08-11 12:06:17)





这一章比较庞大,里面的例子也比较多,我看书和实践一共花了我一周的时间,然后自己又摸索构建一个View实现了一点功能,到今天才写这一章的东西,呵呵,晚了点了!


UINavigationController是用于构建分层应用程序的主要工具,它在管理以及换入和换出多个内容视图方面与UITabBarController较为相似,但是主要不同之处在于前者是作为栈来实现的,这让它非常实用处理分层数据。

创建Window-Based Application,我创建的项目名称是IP_09Nav。创建一个新类,UIViewController subclass命名为RootViewController,该类将包含导航控制器的根视图的控制器类。

设置导航控制器。打开IP_09NavAppDelegate.h添加一个输出口。

IBOutlet UINavigationController *navController;//声明一个Navigation输出

在IP_09NavAppDelegate.m中添加子视图:

[window addSubview:navController.view];//添加Navigation导航模板到window

接下来打开MainWindow.xib,向里面拖入一个Navigation Controller,要拖入nib窗口而不是view窗口。按下control键,并从IP_09Nav App Delegate图标拖入到新的Navigation Controller图标选中navController输出口。下面要将窗口工具栏中间的View Model按钮将nib主窗口改为列表模式。点Navigation Controller前面的小箭头,找到View Controller,然后Apple+4将基类修改为RootViewControoler。

接下来我们要创建一个类让其继承UITableViewController,这样我们做的目的是我们在继承的子类中添加一个UIImage的属性,并且让所有的Nav继承此类,这样所有的Nav也就有了UIImage这样一个属性了。

创建一个新类SecondLViewController。让其继承UITableViewController,给一个UIImage属性。这样把该项目下自己创建的类都让其继承该类。

在RootViewController.m中添加代码

#import "SecondLevelViewController.h"//导入该类是为了使用rowImage属性
#import "IP_09NavAppDelegate.h"//导入该类是为了使用应用程序委托

-(void)viewDidLoad
{
 self.title = @"Root L";//设置该控制器的标题
 NSMutableArray *array = [[NSMutableArray alloc]init];//创建一个可变数组,用来保存每一个二级视图 
 self.controllers = array;
 [array release];
 [super viewDidLoad];
}
#pragma mark Table Date source methods
//返回数组的计数,也就是在根视图下面一共有多少二级视图
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
 return [self.controllers count];
}


//返回单元格
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 static NSString *RootViewControllerCell = @"RootViewControllerCell";
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:RootViewControllerCell];
 if(cell == nil)
 {
 cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:RootViewControllerCell]autorelease];
 }
 NSUInteger row = [indexPath row];
 SecondLevelViewController *controller = [controllers objectAtIndex:row];
 cell.text = controller.title;
 cell.image = controller.rowImage;
 return cell;
}

#pragma mark table View Delegate Methods
//用来显示二级视图后面的箭头
-(UITableViewCellAccessoryType)tableView:(UITableView *)tableView
 accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath
{
 return UITableViewCellAccessoryDisclosureIndicator;
}

-(void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
//用户单击每行时调用方法
{
 NSUInteger row = [indexPath row];//获取单击时的行
 SecondLevelViewController *nextController = [self.controllers objectAtIndex:row];//从对应的行的数组中获取正确的控制器
 IP_09NavAppDelegate *delegate = [[UIApplication sharedApplication] delegate];//用应用程序委托来维护导航控制器,使用共享的UIApplication实例获取到该委托的引用
 [delegate.navController pushViewController:nextController animated:YES];//使用委托的navController输出口将下一个控制器放到导航控制器中
}
这样弄好以后build and go就可以显示一个空的试图了。

下面添加第一个自控制器:展示按钮试图

创建两个类DisclosureButtonController和DisclosureDetailController前一个类是为了显示二级试图里面的项,后一个主要是和xib文件关联显示详细信息。

打开DisclosureDetailController.h添加两个变量:

IBOutlet UILabel *label;//用户显示的label
 NSString *message;
在DisclosureDetailController.m中添加viewWillAppear方法

//此处用viewillAppear方法,而不用viewDidLoad方法是因为viewDidLoad方法只在第一次加载其视图的时候调用。用该方法在每次单击按钮的时候都会被调用
-(void)viewWillAppear:(BOOL)animated
{
 label.text = message;
 [super viewWillAppear:animated];
}

然后创建一个xib文件名称为DisclosureDetail.xib然后拖入一个UILabel,调整好大小,让其和DisclosureDetailController类相关联,并且连接好输出口。

下面修改DisclosureButtonController.h。

#import <UIKit/UIKit.h>
#import "SecondLevelViewController.h"
@class DisclosureDetailController;

@interface DisclosureButtonController : SecondLevelViewController
<UITableViewDelegate,UITableViewDataSource>
{
 NSArray *list;
 DisclosureDetailController *childCntroller;
}
@property (nonatomic,retain) NSArray *list;
@property (nonatomic,retain) DisclosureDetailController *childCntroller;
@end

接下来修改DisclosureButtonController.m

#import "IP_09NavAppDelegate.h"
#import "DisclosureDetailController.h"

//初始化一个数据源
-(void)viewDidLoad
{
 NSArray *array = [[NSArray alloc]initWithObjects:@"0",@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",nil];
 self.list = array;
 [array release];
 [super viewDidLoad];
}

#pragma mark Table dataSource methods
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
 return [list count];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
 static NSString *s = @"DisclosureButtonCellIdentifier";
 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:s];
 if(cell == nil)
 {
 cell = [[[UITableViewCell alloc]initWithFrame:CGRectZero reuseIdentifier:s]autorelease];
 }
 NSInteger row = [indexPath row];
 NSString *rowString = [list objectAtIndex:row];
 cell.text = rowString;
 [rowString release];
 return cell;
}

#pragma mark Table Delegate methods 委托方法
//返回带展示按钮的行
-(UITableViewCellAccessoryType)tableView:(UITableView *)tableView accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath
{
 return UITableViewCellAccessoryDetailDisclosureButton;
}

//选中行时调用,给出提示,而不是选中按钮给出提示
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 NSInteger row = [indexPath row];
 NSString *message = [self.list objectAtIndex:row];
 UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"Show" message:message delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
 [alert show];
 [alert release];
 [message release];
}

//点击后面的按钮展示下一级菜单
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
 if(childCntroller == nil)
 {
 childCntroller = [[DisclosureDetailController alloc]initWithNibName:@"DisclosureDetail" bundle:nil];
 } 
 childCntroller.title = @"你好!";
 NSUInteger row = [indexPath row];//得到上级的行
 
 NSString *selectedMovid = [list objectAtIndex:row];//得到上级的值
 NSString *detailMessage = [[NSString alloc] initWithFormat:@"you pressed the disclosure button for %@",selectedMovid];
 childCntroller.message = detailMessage;
 childCntroller.title = selectedMovid;
 [detailMessage release];
 IP_09NavAppDelegate *delegate = [[UIApplication sharedApplication]delegate];
 [delegate.navController pushViewController:childCntroller animated:YES];
}
最后在RootViewController中把

#import "DisclosureButtonController.h"

DisclosureButtonController *dbutton = [[DisclosureButtonController alloc]initWithStyle:UITableViewStylePlain];
 dbutton.title = @"Disclosure button";
 dbutton.rowImage = [UIImage imageNamed:@"disclosureButtonControllerIcon.png"];
 [array addObject:dbutton];
 [dbutton release];

运行一下看看。



第二个子控制器:校验表(也就是允许用户从列表中选择一个项目)

创建一个新类CheckListController,继承自SecondLevelViewController。限于篇幅有限,代码我就不在这上面添加了,具体代码可以去我CSDN上面下载,代码中有注释。

代码填写好后在RootViewController里面添加一个二级试图,方法和第一个相似。

然后运行。

第三个控制器:表行上的控件

创建一个新类RowControllersController,继承SecondLevelViewController。具体代码下载看吧。

这几个控制器和第一个差不多,步骤都大同小异,想必自己摸索一下就好了。

第四个控制器:可移动的行

这个演示主要是让其行在编辑模式下面可以随心所欲的移动。也是代码操作,步骤入第一个。

第五个控制器:可删除的行(同第四个)

第六个控制器:可便捷的详细窗格

创建数据模型对象。创建一个新类President这个选择模板为NSObject subclass,然后添加代码。导入Presidents.plist文件

创建控制器。创建两个类PresidentsViewController和PresidentDetailController。具体代码可以去下载,太多了。

最后这个比较麻烦,一定要信息,上面的方法要一点一点搞明白。我最后就是把这个演示用xib实现了一下,用的plist文件也是自己创建的,也可以下载,但是还是有一点问题,有时候会推出,现在还在研究阶段。

最后上几个关于本章的几个图片




《Iphone开发基础教程》第十章 应用程序设置和用户默认设置

这一章主要介绍的是如何向Iphone的Settings应用程序中添加自己的应用设置,以及如何从应用程序内部访问这些设置。

用户默认设置是应用程序首选项的一部分,由NSUserDefaults类实现,用户保存和获取首选项。与NSDictonary获取数据一样,实用键值读取和保存首选项数据。不同之处是NSUserDefaults数据被持久化到文件系统中,而没有存储在内存中的对象实例中。

Settings应用程序的优势之一是无需为首选项设计用户界面。创建属性列表来定义应用程序的可用设置后,Settings应用程序会自动创建用户界面。但是使用Settings应用程序也有一些限制,当应用程序正在运行时,用户可能需要更改的任何首选项都不应该受到Settings应用程序的限制,因为用户可能被强制退出应用程序以更改这些值。互动式应用程序,通常应该提供首选项视图,使用户更改设置时无需退出应用程序。

下面开始这一章的练习。

创建新的项目,这次使用的是Utility Application模板。我创建的项目名称是:IP_10Seting

这个模板从来没有使用过,首先先来熟悉一下该模板。该模板创建出来的应用程序有一个主视图和一个辅助试图,点击主视图中的信息按钮会进入辅助试图,点击辅助试图中的Done按钮会返回主视图。

在这个项目中,你会发现没有Classes文件夹,因为事先这种类型的应用程序需要许多文件,该模板已经将这些文件组织到一些分组中,展开文件夹Main View、Flipside View和Application Controllers,然后将Resources也打开。然后就会看到在每一个文件夹下面会自动对应几个类文件。组成主视图的所有类,包括试图控制器和一个UIView子类,都包含在Main View文件夹中。事先flipside试图所需要的源代码文件都包含在Flipside View文件夹中,最后应用程序委托和控制器类都包含在Application Controllers文件夹中。

打开MainWindow.xib,将主视图更改为列表模式,点击Root View Controller,View,light info button并在此上apple+4,在type中选择info dark这样主视图中的信息按钮就会变成黑色,这样在白色背景下面就会有好的显示效果

更改info.plist文件添加图标。

在根目录上面(就是点IP_10Seting)创建新项目,选择Settings Bundle,创建一个新的Bundle(用默认的名字)。

创建属性列表时要用固定的模式,在创建的Bundle中已经存在了一个Root.plist文件,我们对这个文件进行修改就好了。

打开Root.plist文件,在最上面的Title里修改你Setting的名字。SettingsTable先不用管。在PreferenceSpecifiers项下,有许都的项目,删除2,3,4项。然后展开1,修改Title,这个Title会显示在Settings里面。然后在Item1下面在添加一项,默认是string类型,修改为Dictionary,然后向里面添加5项。Type/PSTextFieldSpecifier,Title/Username,Key/username,AutocapitalizetionType/None,AutocorrectionType/No。PSTextFieldSpecifier说明我们希望在该文本字段中编辑此设置。AutocapitalizetionType指的是该文本字段不要尝试自动大写用户输入的内容。AutocorrectionType这个是告诉Settings不需要自动更正输入到该文本中的值。

到此都可以运行一下看看结果了。

下面添加安全字段设置。

添加一新项,简单的方法就是直接复制item 2然后粘贴就好了,修改item 3中的项。

Type/PSTextFieldSpecifier,Title/Pasword,Key/pasword,AutocapitalizetionType/None,AutocorrectionType/No,IsSecure/Boolean类选中,这样输入的密码就要被点所代替。

添加多值字段。还利用上面的方法,复制一个。

Type/PSMultiValueSpecifier,Title/Protocol,Key/protocol,添加两个Array类型的值。Titles和Values,其中Titles是显示在Settings中的值,而values是显示的值对应的一个值。DefaultValue/1,这个是启动的时候默认的值。

添加开关设置。继续复制、粘贴、修改

Type/PSToggleSwitchSpecifier,Title/Warp Drive,Key/warp,Truue/Engaged,Falsue/Disabled,DefaultValue/Engaged。

添加滑块设置。在添加滑块设置前,让我们再创建一个分组。很简单就是复制item 1,然后粘贴就好了。(这个例子中的粘贴都是选中最后行然后粘贴,让粘贴的行成为最后的行)

修改键值。

Type/PSSliderSpecifier,Key/warpfactor,DefaultValue/5,MinimumValue/0,MaximumValue/10,MinimumValueImage/rabbit.png,MaximumValueImage/turtle.png,从前到后以此为类型,key值,默认值,最小值,最多值,slider左边显示的图标,slider右边显示的图标。

添加一个分组,然后添加子视图设置。

所谓的添加子视图,其实就是再添加一个plist文件罢了。在复制,粘贴一行,修改键值。



Type/PSChildPaneSpecifier,Title/More Settings,File/More这个就是新的plist文件

创建新的plist文件也有一个诀窍,我们可以复制一个Root.plist文件,粘贴然后修改名字,修改里面的项就Ok了。但是这里的复制和粘贴不能在Xcode里面完成,我们必须找到项目所在的文件夹,找到Setting.bundle然后点右键,让其显示文件夹里面的内容,在这里面进行复制粘贴操作才可。

到此该bundle创建完成,下面的就是我们怎么读出来了。

读取应用程序设置。

读取操作主要是应用NSUserDefaults类进行。

首先打开MainViewController.h。添加常量和变量。

//这里面定义的常量对应Setting.bundle里面Root.plist里面每一项的key值
#define kUsernameKey @"username"
#define kSwitch @"warp"
#define kSlider @"warpfactor"
#define kPasword @"pasword"
#define kProtocol @"protocol"

#define kSecondname @"secondname"
#define kUseraddress @"useraddress"
#define kUserBirth @"userbirth"
#define kUserPhone @"userphone"
#define kSecondProtocol @"secondprotocol"

IBOutlet UILabel *usernameLabel;
 IBOutlet UILabel *paswordLabel;
 IBOutlet UILabel *protocolLabel;
 IBOutlet UILabel *secondname;
 IBOutlet UILabel *useraddress;
 IBOutlet UILabel *userbirth;
 IBOutlet UILabel *userphone;
 IBOutlet UILabel *secondprotocol;
 IBOutlet UILabel *switchStats;
 IBOutlet UILabel *sliderValue;

然后打开MainViewController.m添加三个方法

//这个新的方法仅用于抓取标准用户默认设置,并使用我们输入到属性文件中的键值,将所有标签的文本属性设置为用户默认设置中的适当对象
-(void)refreshFields
{
 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
 usernameLabel.text = [defaults objectForKey:kUsernameKey];
 paswordLabel.text = [defaults objectForKey:kPasword];
 protocolLabel.text = [defaults objectForKey:kProtocol];
 
 secondname.text = [defaults objectForKey:kSecondname];
 useraddress.text = [defaults objectForKey:kUseraddress];
 userbirth.text = [defaults objectForKey:kUserBirth];
 userphone.text = [defaults objectForKey:kUserPhone];
 secondprotocol.text = [defaults objectForKey:kSecondProtocol];
 
 switchStats.text = [defaults objectForKey:kSwitch];
 sliderValue.text = [[defaults objectForKey:kSlider]stringValue];
}

//在viewDidLoad和viewDidAppear中调用refreshfields方法,使得在视图载入时显示的字段将设置为合适的首选项值,然后在视图更新
//首选项时,显示的字段将被刷新
-(void)viewDidAppear:(BOOL)animated
{
 [self refreshFields];
 [super viewDidAppear:animated];
}

- (void)viewDidLoad {
 [self refreshFields];
}

当然了,需要打开MainView.xib,向里面拖入适当的UILabel并且和刚才定义的变量进行关联。

这样主视图的读取已经结束。


现在添加辅助视图,在辅助试图我们添加一个switch和一个slider用来读取应用程序设置中的值。

打开FlipsideViewController.h,添加两个输出口。

IBOutlet UISwitch *switchshow;
IBOutlet UiSlider *slidershow;

打开FlipsideViewController.m,首先引入MainViewController。

#import "MainViewController.h"

添加两个方法

- (void)viewDidLoad
{
 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
 switchshow.on = ([[defaults objectForKey:kSwitch]isEqualToString:@"Engaged"])?YES:NO;
 slidershow.value = [defaults floatForKey:kSlider];
}

//重写viewWillDisappear方法,以便在主视图再次显示之前,将控件的值填充到用户默认设置中。
- (void)viewWillDisappear:(BOOL)animated
{
 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
 NSString *prefValue = (switchshow.on)? @"Engaged": @"Disabled";
 [defaults setObject:prefValue forKey:kSwitch];
 [defaults setFloat:slidershow.value forKey:kSlider];
 [super viewWillDisappear:animated];
}

好了,释放资源,build and go运行吧,看看结果。


到此结束,不是很难,这一章就半天就可以搞定。

代码在我的csdn上面有,需要的可以去下载,下载地址http://hanyegudeng.download.csdn.net/





《Iphone开发基础教程》第十一章 基本数据持久

以前我们也用到过读取数据,但是没有一个应用程序是将其数据永久性存储,也就是在应用重启,机器重启后数据不会丢失,和上一次最后的数据一致。这章一共定义了三种保持数据的方法,第一种:实用属性列表,第二种:对象归档,第三种:使用Iphone的嵌入式数据库sqlite3)

给予Iphone应用程序沙盒原理,我们保持的数据都是保存在相对应的应用程序的Document文件夹。既然我们把数据放在每一个应用的Document文件夹中,呢我我们怎么得到相应的路径呢,其实也不是很难。下面是检索文档目录路径的代码

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserdomainMask,YES);

NSString *documentDirectory = [paths objectAtIndex:0];常量NSDocumentDirectory表面我们正在查找的Document目录路径,常量NSUserDomainmask表明我们希望将搜索限制于我们应用程序的沙盒中。这样我们就可以得到该数组的第一值,也仅此一值,因为每一个应用程序只有一个Document文件夹。我们得到了Document的路径,然后和文件名相连接不就是一个完整的路径了吗,这用到了stringByAppendingPathComponent方法

NSString *filepath = [documentDirectory stringbyAppendingPathComponent:@"filename.xxx"];其中filename.xxx为要命名的文件

在每一个应用程序中还对应一个temp文件夹,我们怎么获取这个文件夹的路径呢,也比较简单:

NSString *tempPath = NSTemporaryDirectory();

NSString *filePath = [tempPath stringByAppendingPathComponent:@"filename.xxx"];

下面我们来创建该项目:

第一个实用属性列表文件,打开Xcode,创建新项目,选择View-Based Application即可,我创建项目名称是IP_11persistence。打开IP_11persistenceViewController.h,首先定义一个常量用来串联Document。

#define kFileName @"data.plist"

然后定义四个输出口,用来输入和显示数据。

IBOutlet UITextField *show1;
 IBOutlet UITextField *show2;
 IBOutlet UITextField *show3;
 IBOutlet UITextField *show4;

定义两个方法

-(NSString *)dataFilePath;//用来返回数据文件的完整路径名
-(void)applicationWillTerminate:(NSNotification *)notification;//应用程序在退出调用,将数据保存到数据列表

然后打开IP_11persistenceViewController.m

添加下面这三个方法

-(NSString *)dataFilePath//用来返回数据文件的完整路径名
{
 NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
 NSString *paths = [path objectAtIndex:0];
 return [paths stringByAppendingPathComponent:kFileName];


}

-(void)applicationWillTerminate:(NSNotification *)notification//应用程序在退出调用,将数据保存到数据列表
{
 NSMutableArray *array = [[NSMutableArray alloc]init];
 [array addObject:show1.text];
 [array addObject:show2.text];
 [array addObject:show3.text];
 [array addObject:show4.text];
 [array writeToFile:[self dataFilePath] atomically:YES];
 [array release];
}

-(void)viewDidLoad
{
 NSString *filePath = [self dataFilePath];//得到文件路径
 if([[NSFileManager defaultManager] fileExistsAtPath:filePath])//如果该文件存在就加载
 {
 NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
 show1.text = [array objectAtIndex:0];
 show2.text = [array objectAtIndex:1];
 show3.text = [array objectAtIndex:2];
 show4.text = [array objectAtIndex:3];
 [array release];
 }



 UIApplication *app = [UIApplication sharedApplication];
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:)
 name:UIApplicationWillTerminateNotification
 object:app];
 [super viewDidLoad];
}

代码已经搞定,下面点开Resources文件夹,打开IP_11persistenceViewController.xib,向里面拖入4个UITextField控件,勾掉每一个控件上的Clear When Editing Begin,这样就不是每次选中文本框的时候会自动消失里面的内容了。关联四个控件即可。(在实际的例子当中我添加两个方法,一个是在点击回车时,软键盘自动消失,一个是在点击背景是软键盘自动消失,这两个方法在第四章中有详细的讲解,可以去参考)。build and go运行,这是你输入内容关闭应用程序,然后在打开,你会发现你刚才输入的内容仍然存在,下面开始第二种方法,使用对象归档的方法

创建一个新的项目,我的项目名是:IP_11persistence2。创建好以后,在Classes文件夹上点右键创建一个新的类,选择NSObject subclass模板。名称为fourlines。打开fourlines.h,向里面添加四个常量和四个输出口:

#define kField1Key @"show1"
#define kField2Key @"show2"
#define kField3Key @"show3"
#define kField4Key @"show4"

NSString *show1;
NSString *show2;
NSString *show3;
NSString *show4;

打开fourlines.m文件修改代码

-(void)encodeWithCoder:(NSCoder *)encoder //对所有的属性进行编码
{
 [encoder encodeObject:show1 forKey:kField1Key];
 [encoder encodeObject:show2 forKey:kField2Key];
 [encoder encodeObject:show3 forKey:kField3Key];
 [encoder encodeObject:show4 forKey:kField4Key];
}

-(id)initWithCoder:(NSCoder *)decoder//使用相同的4格键值对这些属性进行解码
{
 if(self == [super init])
 {
 self.show1 = [decoder decodeObjectForKey:kField1Key];
 self.show2 = [decoder decodeObjectForKey:kField2Key];
 self.show3 = [decoder decodeObjectForKey:kField3Key];
 self.show4 = [decoder decodeObjectForKey:kField4Key];
 }
 return self;
}

-(id)copyWithZone:(NSZone *)zone//创建一个新的fourline对象,并将所有4格字符串复制到其中
{
 fourlines *copy = [[[self class] allocWithZone:zone] init];
 show1 = [self.show1 copy];
 show2 = [self.show2 copy];
 show3 = [self.show3 copy];
 show4 = [self.show4 copy];
 return copy;
}

然后打开IP_11persistence2ViewController.h,里面声明四个输出口,这和第一个例子一样,定义两个常量。

#define kFileName @"archive"
#define kDataKey @"Data"

打开IP_11persistence2ViewController.m导入fourlines类。

#import "fourlines.h"

修改代码

-(NSString *)dataFilePath//用来返回数据文件的完整路径名
{
 NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,YES);
 NSString *paths = [path objectAtIndex:0];
 return [paths stringByAppendingPathComponent:kFileName];
}

-(void)applicationWillTerminate:(NSNotification *)notification//应用程序在退出调用,将数据保存到数据列表
{
 fourlines *fourline = [[fourlines alloc] init];
 fourline.show1 = show1.text;
 fourline.show2 = show2.text;
 fourline.show3 = show3.text;
 fourline.show4 = show4.text;
 
 NSMutableData *data = [[NSMutableData alloc] init];
 NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
 [archiver encodeObject:fourline forKey:kDataKey];
 [archiver finishEncoding];
 [data writeToFile:[self dataFilePath] atomically:YES];
 [fourline release];
 [archiver release];
 [data release];
}

-(void)viewDidLoad
{
 NSString *filePath = [self dataFilePath];//得到文件路径
 if([[NSFileManager defaultManager] fileExistsAtPath:filePath])//如果该文件存在就加载
 {
 NSMutableData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
 NSKeyedUnarchiver *archiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
 fourlines *fourline = [archiver decodeObjectForKey:kDataKey];
 [archiver finishDecoding];
 
 show1.text = fourline.show1;
 show2.text = fourline.show2;
 show3.text = fourline.show3;
 show4.text = fourline.show4;
 
 [archiver release];
 [data release];
 }
 UIApplication *app = [UIApplication sharedApplication];
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:)
 name:UIApplicationWillTerminateNotification
 object:app];
 [super viewDidLoad];
}

对IP_11persistence2ViewController.xib的操作同第一个。

下面来创建最后一个使用sqlite来保存数据。我创建的项目名是IP_11sqlite。

首先导入libsqlite3.lib,这和导入FrameWork一样,在Framework文件夹上面右击,ADD-Existing Files然后选择文件,该文件在/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/usr/lib/libsqlite3.dylib下面。导入后开始修改代码

打开IP_11sqliteViewController.h

#import "/usr/include/sqlite3.h"
#define kFileName @"data.sqlite3"

增加一个变量:sqlite3 *database;

修改后为:

#import <UIKit/UIKit.h>
#import "/usr/include/sqlite3.h"
#define kFileName @"data.sqlite3"

@interface IP_11sqliteViewController : UIViewController {
 IBOutlet UITextField *show1;
 IBOutlet UITextField *show2;
 IBOutlet UITextField *show3;
 IBOutlet UITextField *show4;
 
 sqlite3 *database;
}
@property (nonatomic,retain) UITextField *show1;
@property (nonatomic,retain) UITextField *show2;
@property (nonatomic,retain) UITextField *show3;
@property (nonatomic,retain) UITextField *show4;
-(NSString *)dataFilePath;
-(void)applicationWillTerminate:(NSNotification *)notification;
@end

然后打开IP_11sqliteViewController.m修改代码如下:

-(NSString *)dataFilePath//用来返回数据文件的完整路径名
{
 NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,YES);
 NSString *paths = [path objectAtIndex:0];
 return [paths stringByAppendingPathComponent:kFileName];
}

-(void)applicationWillTerminate:(NSNotification *)notification//应用程序在退出调用,将数据保存到数据列表
{
 for(int i = 1; i<=4; i++)
 {
 NSString *fieldName = [[NSString alloc] initWithFormat:@"show%d",i];
 UITextField *field = [self valueForKey:fieldName];//根据每一i的值设定相应textfield
 [fieldName release];
 
 NSString *update = [[NSString alloc] initWithFormat:@"insert or replace into fields (row,field_data) values (%d,'%@');",i,field.text];//插入或更新表
 char *errorMsg;
 
 if(sqlite3_exec(database,[update UTF8String],NULL,&errorMsg) != sqlITE_OK)//执行插入或更新操作,如果插入或更新失败给出错误信息
 {
 NSAssert1(0,@"Error updating tables: %s",errorMsg);
 sqlite3_free(errorMsg);
 }
 }
 sqlite3_close(database);//关闭数据库连接
}

-(void)viewDidLoad
{
 if(sqlite3_open([[self dataFilePath] UTF8String],&database) != sqlITE_OK)//打开数据库,如果打开失败给出提示
 {
 sqlite3_close(database);
 NSAssert(0,@"Failed to open database");
 }
 
 char *errorMsg;
 NSString *createsql = @"create table if not exists fields (row integer primary key,field_data text);";//创建表
 if(sqlite3_exec(database,[createsql UTF8String],&errorMsg)!=sqlITE_OK)//是否创建成功
 {
 sqlite3_close(database);
 NSAssert1(0,@"Error creating table: %s",errorMsg);
 }
 
 NSString *query = @"select row,field_data from fields order by row";//查找表中的数据,行和每一行对应的值
 sqlite3_stmt *statement;
 if(sqlite3_prepare_v2(database,[query UTF8String],-1,&statement,nil) == sqlITE_OK)
 {
 while(sqlite3_step(statement) == sqlITE_ROW)
 {
 int row = sqlite3_column_int(statement,0);
 char *rowData = (char *)sqlite3_column_text(statement,1);
 
 NSString *fieldName = [[NSString alloc] initWithFormat:@"show%d",row];
 NSString *fieldValue = [[NSString alloc] initWithUTF8String:rowData];
 UITextField *field = [self valueForKey:fieldName];
 field.text = fieldValue;
 [fieldName release];
 [fieldValue release];
 }
 sqlite3_finalize(statement);
 }
 
 UIApplication *app = [UIApplication sharedApplication];
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillTerminate:)
 name:UIApplicationWillTerminateNotification
 object:app];
 [super viewDidLoad];
}
最后就是IP_11sqliteViewController.xib的修改了,和第一个一样的。

到此三种方法的操作结束了。

代码在我的csdn上面有,需要的可以去下载,下载地址http://hanyegudeng.download.csdn.net/。

原文链接:https://www.f2er.com/sqlite/202973.html

猜你在找的Sqlite相关文章