Three20研究院之结合第三方FMDB框架操作数据库详解(四)

开始本章之间,首先了解一下FMDB,它是一个老外写的第三方操作数据库的框架。因为IOS官方提供操作数据库的方法似乎不是那么近人而意,使用起来有点麻烦,所以这个老外哥们就将官方提供的方法又包了一层,它封装的方法非常浅,并没有多莫高深,只是更方便开发使用,我看了一下大概核心的代码500多行吧。下面开始学习它,首先需要将源码下载至本地,这哥们将代码上传至GitHub当中,(我现在越来越喜欢GitHub了,在这里总能找到老外写的好玩的东西)。
下载地址:https://github.com/ccgus/fmdb  

无需注册,在页面左上角标题下方点击“ZIP”按钮,即可将源码下载至本地,接着解压文件,然后将源码中src文件夹中的所有代码拷贝至工程当中。由于Xcode4.3.1有一个BUG比较恶心,不支持文件夹的拖拽添加至工程当中,所以需要手动添加文件夹。如下图所示,在下拉列表中点击“Add Files to Some Project”按钮,然后在我的电脑中 选择刚刚解压后的src文件夹,将FMDB中所有源码添加至当前工程。
FMDB的源码添加完毕后,然后删除fmdb.m 这是作者提供工程的入口类,有兴趣的朋友可以自行研究,我们只学习如何使用这个框架。 目前程序是无法编译通过的,因为缺少类库文件,如下图所示,请将libsqlite3.0dylib添加至工程。
类库文件添加完毕后,到这一步工程就应该可以正常编译了。如果到这一步你的工程还有错误,那就恭喜你自己在好好检查检查工程的结构啦。接下来将步入正题,老规矩还是以一个实例的形式向大家介绍如何使用FMDB,如下图所以,又是我们熟悉的界面。
本示例中,程序中共用到了3个控制类,它们是:
StartViewController:上图中绘制的启动视图。
SQLViewController:增、删、改、查后在屏幕中显示的列表视图。
MessageInfoController:选择数据库中某一项数据后将所有信息展示在这个视图中。

首先是程序的启动类,这里说明一下,有关以前提到的知识本节我就不在赘述,如果不理解的朋友请阅读本系列教程之前的文章。

AppDelegate.m
01 #import "AppDelegate.h"
02 #import "StartViewController.h"
03 #import "SQLViewController.h"
04 #import "MessageInfoController.h"
05 @implementation AppDelegate
06  
07 @synthesize window = _window;
08  
09 - (void)dealloc
10 {
11     [_window release];
12     [super dealloc];
13 }
14  
15 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
16 {
17     TTNavigator* navigator = [TTNavigator navigator];
18     navigator.persistenceMode = TTNavigatorPersistenceModeAll;
19     navigator.window = [[[UIWindow alloc] initWithFrame:TTScreenBounds()] autorelease];
20     TTURLMap* map = navigator.URLMap;
21     [map from:@"*" toViewController:[TTWebController class]];
22     [map from:@"tt://StartView" toSharedViewController:[StartViewControllerclass]];
23     [map from:@"tt://SQLView/(initInfo:)" toViewController:[SQLViewController class]];
24     [map from:@"tt://MessageView/(initInfo:)" toViewController:[MessageInfoController class]];
25  
26     if (![navigator restoreViewControllers])
27     {
28         [navigator openURLAction:[TTURLAction actionWithURLPath:@"tt://StartView"]];
29     }
30     return YES;
31 }
32  
33 @end

StartViewController.m 启动画面

01 #import "StartViewController.h"
02  
03 @implementation StartViewController
04  
05 - (void)viewDidLoad
06 {
07     [super viewDidLoad];
08     //标题栏名称
09     self.title = @"雨松MOMO";
10     //设置视图背景颜色
11     self.view.backgroundColor = [UIColor blackColor];
12     //创建图片视图
13     TTImageView *imageview = [[[TTImageView alloc] initWithFrame:
14                                CGRectMake(100, 50, 120, 120)] autorelease]; 
15  
16     //设置图片视图显示的图片资源
17     imageview.defaultImage = TTIMAGE(@"bundle://0.jpg");
18     //将图片视图加入整个视图当中
19     [self.view addSubview:imageview];
20  
21     //创建label视图
22     UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, 30)];
23     //设置显示内容
24     label.text = @"Three20软件开发之FMDB数据库";
25     //设置背景颜色
26     label.backgroundColor = [UIColor blueColor];
27     //设置文字颜色
28     label.textColor = [UIColor whiteColor];
29     //设置显示位置居中
30     label.textAlignment = UITextAlignmentCenter;
31     //设置字体大小
32     label.font = [UIFont fontWithName:[[UIFont familyNames] objectAtIndex:10] size:20]; 
33  
34     [self.view addSubview: label];
35  
36     NSArray *titles = [[NSArray alloc] initWithObjects:
37                        @"插入数据库",
38                        @"更新数据库",
39                        @"删除数据库",
40                        @"查询数据库",
41                        nil];
42  
43     for (int i =0; i < [titles count]; i++)
44     {
45  
46         //创建普通按钮
47         UIButton *button = [UIButton buttonWithType:1];
48         //设置按钮位置
49         button.frame = CGRectMake(0, 200 + i * 40, 320, 30);
50         //设置按钮现实文字
51         [button setTitle:[titles objectAtIndex:i] forState:UIControlStateNormal];
52         //设置按钮标记
53         button.tag = i;
54         //设置按钮点击后 绑定响应方法
55         [button addTarget:self action:@selector(ButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
56         //将按钮添加入视图中
57         [self.view addSubview: button];
58     }
59  
60 }
61  
62 //按钮点击后将进入这个方法
63 -(void)ButtonPressed:(id)buttonID
64 {
65     //得到导航对象
66     TTNavigator* navigator = [TTNavigator navigator];
67     //获取点击的按钮
68     UIButton *button = (UIButton *)buttonID;
69     //注解1
70     switch (button.tag) {
71         case 0:
72             [navigator openURLAction:[[TTURLAction actionWithURLPath:@"tt://SQLView/0"] applyAnimated:YES]];
73             break;
74         case 1:
75             [navigator openURLAction:[[TTURLAction actionWithURLPath:@"tt://SQLView/1"] applyAnimated:YES]];
76             break;
77         case 2:
78             [navigator openURLAction:[[TTURLAction actionWithURLPath:@"tt://SQLView/2"] applyAnimated:YES]];
79             break;
80         case 3:
81             [navigator openURLAction:[[TTURLAction actionWithURLPath:@"tt://SQLView/3"] applyAnimated:YES]];
82             break;
83         default:
84             break;
85     }
86 }
87 @end

 

注解1:在启动视图中,点击按钮后程序将进入@”tt://SQLView”页面,该页面对应的控制类是SQLViewController。
SQLViewController.h 
01 #import <Three20/Three20.h>
02 #import "SingleDate.h"
03  
04 @interface SQLViewController : TTTableViewController
05 {
06     //记录上一页点击的按钮
07     int pageID;
08     //获取单例模型的实例
09     SingleDate *instance;
10     //数据库对象
11     FMDatabase *db;
12 }
13 @end

 

SQLViewController.m

所有使用FMDB操作数据库的方法都写在这个类中,增加、删除、修改、查询都在里面。请大家先阅读一下,后面我会有详细的注解。
001 #import "SQLViewController.h"
002 #import "FMDatabase.h"
003 #import "FMDatabaseAdditions.h"
004  
005 #define DATABASE_NAME @"Temp.db"
006  
007 @implementation SQLViewController
008  
009 -(id)initInfo:(int)page
010 {
011     if (self = [super init]) {
012         //注解1
013         pageID = page;
014  
015     }
016     return self;
017  
018 }
019  
020 - (void)viewDidLoad
021 {
022  
023     [super viewDidLoad];
024  
025     //注解2
026  
027     //图片的地址
028     NSMutableArray *iconurls = [[[NSMutableArray alloc] initWithObjects:
029                                 @"bundle://0.jpg",
030                                 @"bundle://1.jpg",
031                                 @"bundle://2.jpg",
032                                 @"bundle://3.jpg",
033                                 nil] autorelease];
034     //姓名
035     NSMutableArray *names = [[[NSMutableArray alloc] initWithObjects:
036                              @"雨松MOMO",
037                              @"RORO娃娃",
038                              @"小老虎",
039                              @"哇咔咔",
040                              nil] autorelease];
041     //性别
042     NSMutableArray *sexs = [[NSMutableArray alloc] initWithObjects:
043                              @"男",
044                              @"女",
045                              @"男",
046                              @"女",
047                              nil];
048     //地址
049     NSMutableArray *address = [[[NSMutableArray alloc] initWithObjects:
050                             @"北京市朝阳区",
051                             @"北京市西城区",
052                             @"北京市海淀区",
053                             @"北京市东城区",
054                             nil] autorelease];
055  
056     //年龄
057     NSMutableArray *ages = [[[NSMutableArray alloc] initWithObjects:
058                                  [NSNumber numberWithInt:28],
059                                  [NSNumber numberWithInt:27],
060                                  [NSNumber numberWithInt:26],
061                                  [NSNumber numberWithInt:25],
062                                  nil] autorelease];
063  
064     //获取单例对象实例
065     instance = [SingleDate getInstance];
066     //读取数据库
067     db = [instance loadDB:DATABASE_NAME];
068     //结果集
069     FMResultSet *rs = nil;
070     //判断当前页面的ID
071     switch (pageID)
072     {
073         case 0:
074             //注解3
075             if(![db tableExists:@"Message"])
076             {
077                 //创建数据库
078                 if ([db executeUpdate:@"CREATE TABLE Message (_id INTEGER PRIMARY KEY AUTOINCREMENT,IconUrl text, Name text, Sex text,Address text,Age integer)"])
079                 {
080                     NSLog(@"创建表成功");
081  
082                     for(int i=0 ;i<[iconurls count]; i++)
083                     {
084                         //遍历测试数据数组,然后将测试数据写入数据库当中
085                         if([db executeUpdate:@"INSERT INTO Message (IconUrl,Name,Sex,Address,Age) VALUES (?,?,?,?,?)", [iconurls objectAtIndex:i],[names objectAtIndex:i], [sexs objectAtIndex:i],[address objectAtIndex:i],[ages objectAtIndex:i]])
086                         {
087                             NSLog(@"插入数据成功");
088  
089                         }
090                     }
091                 }
092             }
093             //返回一个结果集
094             rs=[db executeQuery:@"SELECT * FROM Message"];
095             break;
096         case 1:
097             //判断当数据库中含有Message表时
098             if([db tableExists:@"Message"])
099             {
100                 //注释4
101                 if([db executeUpdate:@"UPDATE Message SET Name = ? WHERE _id = ? ", @"雨松MOMO(已修改)",[NSNumber numberWithInt:1]])
102                 {
103                     NSLog(@"更新一个数据成功");
104  
105                 }
106  
107                 if([db executeUpdate:@"UPDATE Message SET Name = ? , Sex = ? ,  Address = ? WHERE _id = ? ", @"雨松MOMO(已修改)",@"男(已修改)",@"北京市朝阳区(已修改)",[NSNumber numberWithInt:1]])
108                 {
109                     NSLog(@"更新多条数据成功");
110  
111                 }
112             }
113               //返回一个结果集
114             rs=[db executeQuery:@"SELECT * FROM Message"];
115             break;
116         case 2:
117              //判断当数据库中含有Message表时
118              if([db tableExists:@"Message"])
119              {
120                  //删除数据
121                  if([db executeUpdate:@"DELETE FROM Message WHERE _id = ?",[NSNumber numberWithInt:2]])
122                  {
123                      NSLog(@"删除数据成功");
124                  }
125  
126              }
127               //返回一个结果集
128             rs=[db executeQuery:@"SELECT * FROM Message"];
129             break;
130         case 3:
131               //返回一个结果集
132              rs=[db executeQuery:@"SELECT * FROM Message WHERE _id = ? ",[NSNumber numberWithInt:3]];
133             break;
134  
135         default:
136             break;
137     }
138  
139     NSMutableArray * array = [[[NSMutableArray alloc]init] autorelease];
140     //注释5
141     while ([rs next])
142     {
143         [array addObject:[TTTableImageItem itemWithText:[rs stringForColumn:@"Name"]
144                                                imageURL:[rs stringForColumn:@"IconUrl"]
145                                                     URL:[NSString stringWithFormat: @"%@%@", @"tt://MessageView/", [rs stringForColumn:@"_id"]]]];
146     }
147     //用完以后一定要关闭
148     [rs close];
149  
150     //设置列表自适应高度
151     self.variableHeightRows = YES;
152     //设置列表现实的数据
153     self.dataSource = [TTSectionedDataSource dataSourceWithArrays:@"当前数据库信息",array,nil];
154 }
155  
156 @end

 

注解1:(int)page表示上一个页面进入本页面中传递的参数,在本页面中通过它来判断不同的数据库操作。
注解2:这4个数组包含的信息有,图片地址、姓名、性别、地址、年龄,这些数据仅仅起到测试数据的作用,后面我们需要将它们全部写入数据库当中。然后强调一下数据库与表的区别,一个库中可以添加多个表,本节中使用的数据库名称为Temp.db 数据表为Message,请大家注意一下即可。
注解3:tableExists方法用来判断数据库中是否包含某一个表,当数据库中没有该表时,创建该表并且写入数据。如果数据库中有该表则不做任何操作。 为了区分数据库,所以在插入数据时设置第一个参数为 _id INTEGER PRIMARY KEY AUTOINCREMENT它表示在数据库中添加_id字段,并且该字段为自动添值,它是一个向上递增的序列用来区分每条数据。
注解4:用于更新数据,这些都是标准的SQL语句,这里主要强调一下当更新多条数据时 数据之间使用逗号隔开。
注释5:这里主要学习FMResultSet类,它是一个查询的结果集。使用数据库语句找到的数据将全部写入FMResultSet对象当中,然后使用循环判断该对象即可。[rs next]方法表示拨动结果集的指针,返回true表示当前指针对应的结果集当中有值。最后将数据库中拿到的数据已列表的形式显示在视图中,如下图所示,列表中已经写入数据。

在获取数据库对象时,这使用到了单例模式,单例模式在程序语言设计中占据重要地位,而在IOS程序开发中也会频繁使用单例模式。举个简单的例子 从viewA 进入  viewB , 但是viewB需要viewA中计算过的一些数据,有些朋友会想那直接在页面切换时将参数传递给viewB不就行了。这样是可以,但是如果程序中频繁的使用这样的操作肯定会出问题,因为它们属于View层,MVC设计模式告诉我们一定不要让数据放在View层。 在这里单例模型就好比控制器层,在viewA中将数据计算完毕后,写入单例对象中的变量中,进入viewB后,在继续从单例中获取刚刚viewA传递进去的数值。这样的思路会清晰很多,避免后期很多麻烦。


SingleDate.h

01 #import <Three20/Three20.h>
02 #import "FMDatabase.h"
03  
04 @interface SingleDate : NSObject
05 {
06  
07 }
08 //获取单例对象
09 +(SingleDate *)getInstance;
10 //读取数据库
11 -(FMDatabase *)loadDB:(NSString *)dbName;
12 @end

SingleDate.m

01 #import "SingleDate.h"
02  
03 @implementation SingleDate
04  
05 static SingleDate *instance = nil;
06  
07 //获取单例
08 +(SingleDate *)getInstance
09 {
10     @synchronized(self)
11     {
12         if (instance == nil)
13         {
14             instance = [[self alloc] init];
15         }
16     }
17     return instance;
18 }
19  
20 //读取数据库
21 -(FMDatabase* )loadDB:(NSString *)dbName
22 {
23     //获取当前程序路径
24     NSURL *appUrl = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
25     NSString *dbPath = [[appUrl path] stringByAppendingPathComponent:dbName];
26     //注释1
27     FMDatabase *db= [FMDatabase databaseWithPath:dbPath] ; 
28  
29     if (![db open]) {
30         [db release];
31         NSLog(@"数据库未能创建/打开");
32         return nil;
33     }   
34  
35     return db;
36 }
37 @end

 


注释1:如果没有该数据库则创建并且返回数据库对象,如果有该数据库直接返回对象。接着调用[db open]方法判断数据库对象是否创建与打开成功。

        接下来我们看看创建的数据库文件保存在了那里,如果你是用真机调试,那么请在Xcode主界面中点击右上角Organizer按钮,接着选择机器的名称,在机器对应的下拉列表中选择Applications,最后点击右侧页面下方Download按钮将应用程序中的数据下载至本地,解开这个包即可看到创建的数据库。如果你使用模拟器调试,该文件保存的路径为Library(资源库)->Application Support ->iPhone Simulator -> 5.1->Applciations->你的项目->Documents->Temp.db ,这个路径是我的模拟器路径,不同的模拟器版本路径会稍有差异,不过都差不多。如果实在找不到,请输出上方代码的 dbPath,它就是当前你数据库文件的路径。
下面我推荐大家使用在Mac下查看数据库的软件,名称是Navicat Premium。那么本节中也使用这个软件打开上述代码创建的数据库。打开Uavicat Premium 然间后,在左上角出点击Connection下拉列表选择SQLite,然后弹出创建数据库查看页面,接着在Connection Name :输入一个名称(随便即可)Database File:选择刚刚创建的数据库文件的路径, 最后点击右下角OK按钮即可。如下图所示,已经将数据库打开,并且相应的数值已经写入Message数据库当中,这些数据从左到右的含义是:升序ID、图片的地址、名称、性别、地址、年龄,这些应该能看懂吧。怎么样这个软件还不错吧。
        接着是最后的展示页面,该页面将每一条数据库中的所有数据展示在屏幕当中。将选择列表的ID传入该页面,然后通过ID 去数据库中查询数值,从而将所有的信息展示在该页面中,代码在下面,仔细阅读以下就会明白。
MessageInfoController.h
01 #import <Three20/Three20.h>
02 #import "SingleDate.h"
03 #import "FMDatabase.h"
04 @interface MessageInfoController
05 : TTViewController
06 {
07     //数据库ID
08     int sqlID;
09     //单例对象
10     SingleDate *instance;
11     //数据库对象
12     FMDatabase *db;
13 }
14 @end

MessageInfoController.m

 

01 #import "MessageInfoController.h"
02  
03 #define DATABASE_NAME @"Temp.db"
04  
05 @implementation MessageInfoController
06  
07 -(id)initInfo:(int)page
08 {
09     if (self = [super init]) {
10  
11         sqlID = page;
12  
13     }
14     return self;
15  
16 }
17  
18 - (void)viewDidLoad
19 {
20  
21     [super viewDidLoad];
22     instance = [SingleDate getInstance];
23     db = [instance loadDB:DATABASE_NAME];
24     //查询数据库的结果集
25     FMResultSet *rs=[db executeQuery:@"SELECT * FROM Message WHERE _id = ? ",[NSNumber numberWithInt:sqlID]];
26     if(rs != nil)
27     {
28         [rs next];
29         //获取名称
30         NSString * name = [rs stringForColumn:@"Name"];
31         //获取图片
32         UIImage *  image = TTIMAGE([rs stringForColumn:@"IconUrl"]);
33         //获取性别
34         NSString *  sex = [rs stringForColumn:@"Sex"];
35         //获取地址
36         NSString *  address = [rs stringForColumn:@"Address"];
37         //获取年龄
38         int age = [rs intForColumn:@"Age"];
39  
40         [rs close];
41  
42         //标题栏名称
43         self.title = name;
44         //设置视图背景颜色
45         self.view.backgroundColor = [UIColor blackColor];
46         //创建图片视图
47         TTImageView *imageview = [[[TTImageView alloc] initWithFrame:
48                                    CGRectMake(100, 200, 120, 120)] autorelease]; 
49  
50         //设置图片视图显示的图片资源
51         imageview.defaultImage = image;
52         //将图片视图加入整个视图当中
53         [self.view addSubview:imageview];
54  
55         //将所有文字信息写入视图当中
56         CGRect frame = CGRectMake(10, 60, 300, 100);
57         TTStyledTextLabel* label = [[[TTStyledTextLabel alloc] initWithFrame:frame] autorelease];
58         NSString* labelText = [NSString stringWithFormat: @"姓名:%@ 性别:%@ 地址:%@ 年龄%d" , name, sex,address,age];
59  
60         label.text = [TTStyledText textFromXHTML:labelText];
61         label.font = [UIFont systemFontOfSize:22];
62         [self.view addSubview:label];
63  
64     }
65  
66 }
67 @end

 

最后欢迎各位盆友可以和MOMO一起讨论Three20软件开发,如果你觉得看得不清楚,MOMO附带上本章的源码下载,希望大家可以一起学习 哈哈~。哇咔咔~ MOMO愿和 大家好好学习,大家一起进步哈~!!!



(下载后必需搭建three20环境成功后才能运行~ 因为three20为引用加载,所以程序路径都是我本机的请见谅!或者你可可以将你的Three20路径修改的和我一样就可以直接运行啦,我的路径是:User (用户) -> Share(共享)->Three20)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值