ios 代码更新时ios本地数据库库也要进行变化么

4472人阅读
iPhone中支持通过sqlite3来访问iPhone本地的数据库。
具体使用方法如下
1:添加开发包libsqlite3.0.dylib
首先是设置项目文件,在项目中添加iPhone版的sqlite3的数据库的开发包,在项目下的Frameworks点击右键,然后选择libsqlite3.0.dylib文件。
libsqlite3.0.dylib文件地址:&
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/usr/lib/libsqlite3.0.dylib
2,代码中的操作:
那么接下来是代码了。
1 首先获取iPhone上sqlite3的数据库文件的地址
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@&database_name&];
2&打开iPhone上的sqlite3的数据库文件
sqlite3_open([path UTF8String], &database);
3 准备sql文---sql语句
sqlite3_stmt *
const char *sql = &SELECT
* FROM table_name WHERE pk=? and name=?&;
sqlite3_prepare_v2(database,&sql,
-1, &stmt, NULL);
4&邦定参数
// 邦定第一个int参数
sqlite3_bind_int(stmt, 1, 1);
// 邦定第二个字符串参数
sqlite3_bind_text(stmt, 2, [title UTF8String], -1, SQLITE_TRANSIENT);
5&执行sql文
sqlite3_step(stmt);
6&释放sql文资源
sqlite3_finalize(stmt);
7&关闭iPhone上的sqlite3的数据库
sqlite3_close(database);
/clickto/blog/item/0c25720eec87.html
以下演示一下使用sqlite的步骤,先创建一个数据库,然后查询其中的内容。2个重要结构体和5个主要函数:sqlite3
*pdb, 数据库句柄,跟文件句柄FILE很类似sqlite3_stmt
*stmt, 这个相当于ODBC的Command对象,用于保存编译好的SQL语句sqlite3_open(),
打开数据库sqlite3_exec(),
执行非查询的sql语句sqlite3_prepare(), 准备sql语句,执行select语句或者要使用parameter bind时,用这个函数(封装了sqlite3_exec).Sqlite3_step(), 在调用sqlite3_prepare后,使用这个函数在记录集中移动。Sqlite3_close(), 关闭数据库文件还有一系列的函数,用于从记录集字段中获取数据,如sqlite3_column_text(), 取text类型的数据。sqlite3_column_blob(),取blob类型的数据sqlite3_column_int(), 取int类型的数据PreparedStatement方式处理SQL请求的过程特点:可以绑定参数,生成过程。执行的时候像是ADO一样,每次返回一行结果。1. 首先建立statement对象:int sqlite3_prepare(
sqlite3 *db,
/* Database handle */
const char *zSql,
/* SQL statement, UTF-8 encoded */
int nBytes,
/* Length of zSql in bytes. */
sqlite3_stmt **ppStmt,
/* OUT: Statement handle */
const char **pzTail
/* OUT: Pointer to unused portion of zSql */);2. 绑定过程中的参数(如果有没有确定的参数)
int sqlite3_bind_xxxx(sqlite3_stmt*, int, ...);第二个int类型参数-表示参数的在SQL中的序号(从1开始)。第三个参数为要绑定参数的值。
对于blob和text数值的额外参数:第四参数是字符串(Unicode 8or16)的长度,不包括结束'\0'。第五个参数,类型为void(*)(void*),表示SQLite处理结束后用于清理参数字符串的函数。没有进行绑定的未知参数将被认为是NULL。3. 执行过程
int sqlite3_step(sqlite3_stmt*);可能的返回值: *SQLITE_BUSY:
数据库被锁定,需要等待再次尝试直到成功。 *SQLITE_DONE:
成功执行过程(需要再次执行一遍以恢复数据库状态) *SQLITE_ROW:
返回一行结果(使用sqlite3_column_xxx(sqlite3_stmt*,, int iCol)得到每一列的结果。
再次调用将返回下一行的结果。 *SQLITE_ERROR:
运行错误,过程无法再次调用(错误内容参考sqlite3_errmsg函数返回值) *SQLITE_MISUSE: 错误的使用了本函数(一般是过程没有正确的初始化)4. 结束的时候清理statement对象
int sqlite3_finalize(sqlite3_stmt *pStmt);应该在关闭数据库之前清理过程中占用的资源。5. 重置过程的执行
int sqlite3_reset(sqlite3_stmt *pStmt);过程将回到没有执行之前的状态,绑定的参数不会变化。其他工具函数1. 得到结果总共的行数
int sqlite3_column_count(sqlite3_stmt *pStmt);如果过程没有返回值,如update,将返回02. 得到当前行中包含的数据个数
int sqlite3_data_count(sqlite3_stmt *pStmt);如果sqlite3_step返回SQLITE_ROW,可以得到列数,否则为零。3. 得到数据行中某个列的数据
sqlite3_column_xxx(sqlite3_stmt*, int iCol);在sqlite3_step返回SQLITE_ROW后,使用它得到第iCol列的数据。其中的xxx代表:blob:指向保存数据内存的指针bytes, bytes16: 得到该blob类型数据的大小,或者text转换为UTF8/UTF16的字符串长度。double, int, int64: 数值text,text16:字符串指针type:该列的数据类型(SQLITE_INTEGER,SQLITE_FLOAT,SQLITE_TEXT,SQLITE_BLOB,SQLITE_NULL)注意:如果对该列使用了不同与该列本身类型适合的数据读取方法,得到的数值将是转换过的结果。4. 得到数据行中某个列的数据的类型
int sqlite3_column_type(sqlite3_stmt*, int iCol);返回值:SQLITE_INTEGER,SQLITE_FLOAT,SQLITE_TEXT,SQLITE_BLOB,SQLITE_NULL使用的方法和sqlite3_column_xxx()函数类似。//////////////////////////////////////
Sqlite 資料庫檔案的產生
MAC 上有許多應用程式都可以用來產生它,有 UI 界面很方便。但如果不想另外安裝軟體,MAC 系統也內建 sqlite3 的元件,可由 console 來建立。首先我們先開啟任何一款文書編輯軟體,以 sql 語法來手動建立,並存成 data.sql。
BEGINTRANSACTION;
CREATETABLE
(_id INTEGERPRIMARY
KEY,'Name'TEXT,
'Tel'TEXT,
'Address'TEXT);
INSERTINTO
VALUES(1,'Richie','1234567','台中市');
INSERTINTO
VALUES(2,'Eric','7654321','台北市');
INSERTINTO
VALUES(3,'Andy','1234321','高雄市');
然後在 console 下達以下指令 來產生 data.rdb 這個 sqlite file
data.rdb & data.sql
iOS 專案使用 Sqlite 資料庫
先將剛才產生的資料庫加入專案中,然後在專案中加入 libsqlite3.0.dylib。
接下來開始撰寫程式碼了,xxxAppDelegate.h 必須 import sqlite3.h,並宣告一個 sqlite3 結構。
&sqlite3.h&
@interfacexxxAppDelegate
: NSObject&UIApplicationDelegate&
&&&&sqlite3*
在 xxxAppDelegate.m 的 didFinishLaunchingWithOptions 函式 開始加入相關程式碼
(BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
&&&&NSString*path
= [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES)
lastObject];
&&&&NSString*file
= [path stringByAppendingPathComponent:@&data.rdb&];
&&&&if([[NSFileManagerdefaultManager]
fileExistsAtPath:file] == FALSE)
&&&&&&&&NSString*fromFile
= [[NSBundlemainBundle]
pathForResource:@&data.rdb&ofType:nil];
&&&&&&&&[[NSFileManagerdefaultManager]
copyItemAtPath:fromFile toPath:file error:nil];
&&&&if(sqlite3_open([file
UTF8String], &database) != SQLITE_OK)
&&&&&&&&NSAssert1(0,
to open database with message '%s'.&,
sqlite3_errmsg(database));
&&&&self.window.rootViewController
= self.viewC
&&&&[self.window
makeKeyAndVisible];
&&&&returnYES;
(void)dealloc
&&&&sqlite3_close(database);
&&&&[superdealloc];
簡 單說明一下,將 data.rdb 加入專案中後,該資料庫會出現在 app 套件內,但每個 app 就只有專屬 Documents 目錄可以讀寫。所以必須判斷 Documents 目錄下該檔案是否存在,如果不存在則 copy 過去該目錄後再 open 資料庫。至於為什麼做判斷?為什麼不每次都 copy 過去即可?因為如果不希望該資料庫在每次 app 版本更新後,都會被覆蓋掉,就得做檔案存在與否的判斷。
讀取資料庫
有成功 open 資料庫之後,就可以開始進行讀寫了。讀取資料庫的方法,其實也是很簡單,只要熟悉 SQL 語法,應該就沒什麼問題了。
NSString*sql
= [NSStringstringWithFormat:@&SELECT
* FROM Event &];
sqlite3_stmt
if(sqlite3_prepare_v2(database,
1, -1, &statement, NULL)
== SQLITE_OK)
(sqlite3_step(statement) == SQLITE_ROW)
&&&&&&&&NSString*strValue
= [NSStringstringWithUTF8String:(char*)sqlite3_column_text(statement,
&&&&&&&&intintValue
= sqlite3_column_int(statement, 1);
sqlite3_finalize(statement);
其中必須注意的是 sqlite3_column_text, sqlite3_column_int 負責取得資料,必須指定是哪個 column index。
執行 SQL 命令
上述是 SELECT 的用法,但是如果需要做 INSERT, DELETE, UPDATE 等動作時,則更是簡單,只需以下指令即可。
NSString*sql
= [NSStringstringWithFormat:@&CREATE
TABLE 'Info' (_id INTEGER PRIMARY KEY, 'Name' TEXT, 'Tel' TEXT, 'Address' TEXT)&];
sqlite3_exec(database,
1, nil,nil,
iPhone中支持通过sqlite3来访问iPhone本地的数据库。
具体使用方法如下
1:添加开发包libsqlite3.0.dylib
首先是设置项目文件,在项目中添加iPhone版的sqlite3的数据库的开发包,在项目下的Frameworks点击右键,然后选择libsqlite3.0.dylib文件。
libsqlite3.0.dylib文件地址:&
/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS2.2.sdk/usr/lib/libsqlite3.0.dylib
2,代码中的操作:
那么接下来是代码了。
1&首先获取iPhone上sqlite3的数据库文件的地址
NSArray&*paths&=&NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,&NSUserDomainMask,&YES);
NSString&*documentsDirectory&=&[paths&objectAtIndex:0];
NSString&*path&=&[documentsDirectory&stringByAppendingPathComponent:@&database_name&];
2&打开iPhone上的sqlite3的数据库文件
sqlite3_open([path&UTF8String],&&database);
3&准备sql文---sql语句
sqlite3_stmt&*
const&char&*sql&=&&SELECT&*&FROM&table_name&WHERE&pk=?&and&name=?&;
sqlite3_prepare_v2(database,&sql,&-1,&&stmt,&NULL);
4&邦定参数
//&邦定第一个int参数
sqlite3_bind_int(stmt,&1,&1);
//&邦定第二个字符串参数
sqlite3_bind_text(stmt,&2,&[title&UTF8String],&-1,&SQLITE_TRANSIENT);
5&执行sql文
sqlite3_step(stmt);
6&释放sql文资源
sqlite3_finalize(stmt);
7&关闭iPhone上的sqlite3的数据库
sqlite3_close(database);
/clickto/blog/item/0c25720eec87.html
以下演示一下使用sqlite的步骤,先创建一个数据库,然后查询其中的内容。2个重要结构体和5个主要函数:
sqlite3&&&&&&&&&&&&&&&*pdb,&数据库句柄,跟文件句柄FILE很类似
sqlite3_stmt&&&&&&*stmt,&这个相当于ODBC的Command对象,用于保存编译好的SQL语句
sqlite3_open(),&&&打开数据库
sqlite3_exec(),&&&执行非查询的sql语句
sqlite3_prepare(),&准备sql语句,执行select语句或者要使用parameter&bind时,用这个函数(封装了sqlite3_exec).
Sqlite3_step(),&在调用sqlite3_prepare后,使用这个函数在记录集中移动。
Sqlite3_close(),&关闭数据库文件
还有一系列的函数,用于从记录集字段中获取数据,如
sqlite3_column_text(),&取text类型的数据。
sqlite3_column_blob(),取blob类型的数据
sqlite3_column_int(),&取int类型的数据
PreparedStatement方式处理SQL请求的过程
特点:可以绑定参数,生成过程。执行的时候像是ADO一样,每次返回一行结果。
1.&首先建立statement对象:
int&sqlite3_prepare(
sqlite3&*db,&&&&&&&&&&&&/*&Database&handle&*/
const&char&*zSql,&&&&&&&/*&SQL&statement,&UTF-8&encoded&*/
int&nBytes,&&&&&&&&&&&&&/*&Length&of&zSql&in&bytes.&*/
sqlite3_stmt&**ppStmt,&&/*&OUT:&Statement&handle&*/
const&char&**pzTail&&&&&/*&OUT:&Pointer&to&unused&portion&of&zSql&*/
2.&绑定过程中的参数(如果有没有确定的参数)
int&sqlite3_bind_xxxx(sqlite3_stmt*,&int,&...);
第二个int类型参数-表示参数的在SQL中的序号(从1开始)。
第三个参数为要绑定参数的值。
对于blob和text数值的额外参数:
第四参数是字符串(Unicode&8or16)的长度,不包括结束'\0'。
第五个参数,类型为void(*)(void*),表示SQLite处理结束后用于清理参数字符串的函数。
没有进行绑定的未知参数将被认为是NULL。
3.&执行过程
int&sqlite3_step(sqlite3_stmt*);
可能的返回值:
*SQLITE_BUSY:&&&数据库被锁定,需要等待再次尝试直到成功。
*SQLITE_DONE:&&&成功执行过程(需要再次执行一遍以恢复数据库状态)
*SQLITE_ROW:&&&&返回一行结果(使用sqlite3_column_xxx(sqlite3_stmt*,,&int&iCol)得到每一列的结果。
再次调用将返回下一行的结果。
*SQLITE_ERROR:&&运行错误,过程无法再次调用(错误内容参考sqlite3_errmsg函数返回值)
*SQLITE_MISUSE:&错误的使用了本函数(一般是过程没有正确的初始化)
4.&结束的时候清理statement对象
int&sqlite3_finalize(sqlite3_stmt&*pStmt);
应该在关闭数据库之前清理过程中占用的资源。
5.&重置过程的执行&
int&sqlite3_reset(sqlite3_stmt&*pStmt);
过程将回到没有执行之前的状态,绑定的参数不会变化。
其他工具函数
1.&得到结果总共的行数
int&sqlite3_column_count(sqlite3_stmt&*pStmt);
如果过程没有返回值,如update,将返回0
2.&得到当前行中包含的数据个数
int&sqlite3_data_count(sqlite3_stmt&*pStmt);
如果sqlite3_step返回SQLITE_ROW,可以得到列数,否则为零。
3.&得到数据行中某个列的数据
sqlite3_column_xxx(sqlite3_stmt*,&int&iCol);
在sqlite3_step返回SQLITE_ROW后,使用它得到第iCol列的数据。
其中的xxx代表:
blob:指向保存数据内存的指针
bytes,&bytes16:&得到该blob类型数据的大小,或者text转换为UTF8/UTF16的字符串长度。
double,&int,&int64:&数值
text,text16:字符串指针
type:该列的数据类型(SQLITE_INTEGER,SQLITE_FLOAT,SQLITE_TEXT,SQLITE_BLOB,SQLITE_NULL)
注意:如果对该列使用了不同与该列本身类型适合的数据读取方法,得到的数值将是转换过的结果。
4.&得到数据行中某个列的数据的类型
int&sqlite3_column_type(sqlite3_stmt*,&int&iCol);
返回值:SQLITE_INTEGER,SQLITE_FLOAT,SQLITE_TEXT,SQLITE_BLOB,SQLITE_NULL
使用的方法和sqlite3_column_xxx()函数类似。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:386297次
积分:3512
积分:3512
排名:第3747名
原创:15篇
转载:101篇
评论:43条
(2)(4)(3)(7)(3)(6)(6)(2)(1)(2)(5)(3)(2)(5)(4)(2)(15)(4)(8)(22)(10)Android 和 iOS 孰优孰劣:真实应用开发过程告诉你答案
  随便搜索一下&Android&vs.&iOS&,都会出现很多关于哪个平台更好的争论,大多数的争论点都是关于市场占有率、易用性和设备分化等问题。当然也有一些&以开发者的角度&去比较这两个平台的文章,但是很少有从技术上做深入的比较,通常也只是用一个简单的示例应用介绍一些基本的特性。缺少这种深入的比较其实是有原因的:一个公司要做一个足够复杂的移动应用,通常需要一个人或团队做Android,另外一个人或团队做iOS。这两个平台使用不同的编程语言(Java和Objective-C),提供不同的SDK,使用不同的开发工具,所以人力资源分配上各做各的平台也就不奇怪了。
  GQueues是一个在线任务管理器,之前只有一个HTML5版本。最近我完成了GQueues&for&Android 和GQueues&for&iPhone&&&iPad 的开发。虽然这两个应用的复杂程度不能和第一人称射击游戏相提并论,但也绝不简单&&&为用户存储和管理数以千计的任务信息、支持多账户、提供到WEB端的后台同步、复杂的过滤、排序和分组功能。通过这次的实践,我希望透过独特的视角,分析和比较为这两个平台开发GQueues应用的过程。
 统计概况
Android&App
Sept&21,&2012
Mar&2,&2013
第一个可测的Beta版本
Dec&22,&2012
June&10,&2013
应用发布日期
Jan&31,&2013
July&18,&2013
项目总耗时
4.25&months
4.5&months
Ramp&Up&Time
870&hours&(approx)
960&hours&(approx)
Beta测试&Bugfix
Beta测试人员人数
26,981&lines
23,872&lines
 学习曲线
  我已经写了12年的代码,但这是我写的第一个Android应用,也是我写的第一个偏向数据处理的iOS应用(2010年我做过两个iOS&3上的游戏,但那两个游戏主要只涉及一些动画和蓝牙连接)。&我最后一次用Java是在研究生阶段,而我的Objective-C也仅限于那两个游戏。所以对于这两个平台,我基本上可以算是从零开始。
  简单讲,只需要花一半学习iOS的时间来学习Android,我就能开始Android开发。对于Android,我花了一周时间用来看书、跟着一些教程做一些测试应用,这些测试应用包含了GQueues将会用到的一些核心功能。做完这些,我基本上算是打好了为GQueues设计架构的基础,同时也可以开始为这个项目写代码了。在接下来的一周我可以很轻松自如地基于Android做开发,而不再需要依赖某个资源去实现新特性了。
  对于iOS,我同样按照上面的流程,但我花了两周时间做各种测试/实验,才让自己觉得可以开始为这个项目写一些基础代码了。其中大部分的时间都花在研究CoreData各种复杂的API上面。搞清楚怎么设置、怎么在线程安全的前提下,为每个用户集中管理和也花了些功夫,最重要的是要支持多账户(这个话题可能需要另一篇博客来单独讲讲)。为开发一个可扩展的架构花了更多时间,用于支持可被用户查看以及操作的任务表单、队列和分类。最后又过了两周(总共花了一个月)自己才能比较轻松自如地基于iOS写代码。
  总的来说,Android的文档(官方文档、第三方教程、图书、代码示例、StackOverflow)质量都非常高。我从一些著名的开源Android应用中学到了很多架构上的最佳实践,如Google开放给开发者的2012&Google&I/O&app。此外,Android本身就是开源的,必要时我可以自己查看Android的平台代码,弄清楚一些疑难问题。虽然iOS也有很多文档,但由于iOS5和iOS6相比之前的版本改动非常大,大部分文档都已经过时,其中包括ARC入门一文()。因此,大部分的示例代码(包括Apple官方示例)和一些问题的解决方法都是不正确的,需要使用新的方法取而代之。搞清楚这些肯定也需要花更多的时间。
  从上面的统计表中也可以看出,开发GQueues&for&Android要比开发 iOS 版的快十分之一的时间,尽管在开发Android版的期间我重新实现了之前用于支持GQueues&HTML5版的整个后端服务器同步代码。而开发一个不采用原始iOS6风格UI的应用也需要多花些时间,单单比较这个数据,Android开发就是比iOS开发快。
  用到的资源
Android App
  上面列出来的书其实用处很有限,因为跟大部分的技术类书籍一样,书的内容都有点过时了,而且大部分书只停留在入门级别的概念介绍。不过,在一开始的前几天看一下这些书,能够比较快地理解平台上的一些核心功能。就目前来讲,对于这两个平台,在线资源仍然是最有价值的。
  接下来我只简单说一下这两个平台的开发工具,因为关于这个话题已经有很多的讨论。我不是Eclipse或者XCode的脑残粉,它们有各自的强项和弱点(其实我最喜欢的还是Vim)。Eclipse的搜索暴慢而且很繁琐。XCode&Organizer的文档搜索也卡爆了。Eclipse中使用log&tags(通过Android插件的logcat集成)过滤日志超级实用。两个IDE的代码补全都很不错,XCode的Interface&Builder一点用处都没有(后面细讲)。不过XCode&Instruments就非常有用了,可以用它做优化分析、调试等等。我开始做GQueues&for&Android的时候,Google还没发布Android&Studio,不过在GQueues的后续更新版本中我会拿它来试试。
  如果你一边写代码一边测试,用Android的模拟器简直就是浪费时间(真不敢相信它能慢成这个鸟样)。在开发过程中,我都是直接部署到真机上测试的,用真机快很多。iOS的模拟器则很不同,跟Android相比简直就是火箭跟蜗牛赛跑,这也让整个开发过程更加高效。每写一小段代码我都会在模拟器上跑一下,等到整个功能完成了我就会部署到真机上玩玩。
  对于Android,我有各个版本的测试机器(除了Gingerbread,即Android&2.3),除此之外,就要倚靠beta测试过程中各种设备的覆盖了。对于iOS来讲就要简单很多了,我只需要拿GQueues需要支持的最旧的和最新的机器来测试就够了。
  测试设备
Android App
Samsung Infuse (Froyo 2.2)
Nexus S (ICS 4.0.3)
Galaxy Nexus (Jelly Bean 4.2)
Samsung Galaxy Tab 10.1 (Honeycomb 3.2)
Nexus 7 (Jelly Bean 4.2)
iPhone 4 (iOS 6)
iPhone 5 (iOS 6)
iPad 2 (iOS 6)
iPad 4th generation (iOS 6)
  GQueues的其中一个需求就是必须同时支持任意尺寸的手机和平板,并且针对不同的表单元素进行优化布局。由于各种各样的设备都运行着Android系统,Android也理所当然地有着成熟的UI组件帮助开发者支持各种尺寸。例如从Android第一个版本开始,RelativeLayout提供了View之间相对布局的支持,可用于创建灵活、响应迅速的布局。另外,在Android中所有的布局都由XML定义,这设计界面的方式非常简洁、简单并且高效,试过iOS中创建布局之后这种体会就更加深刻了。
  相对于Android的RelativeLayout,iOS有Auto&Layout,这种布局方式比较新(iOS&6新引入的),集成到了Interface&Builder(IB)中,但是太难用了。我花了好多天学习IB中怎么用Auto&Layout,跟任何iOS&6开发者一样,仅靠IB为视图(View)设定各种精确的约束,完全改变了我自己的标准,这是因为IB所谓的&智能&系统时刻维持(纠正)着视图布局相对位置。我学了很多技巧,想着弥补IB的短板,但是没啥作用。最后我只能放弃IB,转而用冗长的代码实现所有布局。如果你放弃IB和富有极客范的ASCII&art&style来写布局,使用Auto&Layout来实现还是很强大、很直接的。希望苹果在iOS&7中已经改善这些,不过我还木有试过。
  如果一个应用需要同时针对小屏设备和大屏设备进行优化,最关键的就是基于屏幕的真实尺寸进行动态组合视图,这种方式被称作&适配性布局(Adaptive&Layout)&,平板电脑可以在一屏中显示两个或三个视图,而手机上一屏则只显示一个视图。Android通过Fragments支持这种设计,Fragment是一个独立的、自包含的的模块,能够在需要的时候直接丢到Activity中去用。通过使用Fragments,只需要调整几行XML代码就可以让GQueues的布局适配不同分辨率的屏幕。对于我来讲,Fragments是一种非常自然的解决方案,因为它是基于面向对象里面两个众所周知的准则设计的&-&高内聚和低耦合。
  通过Custom&Container&View&Controller(你也可以用Master-Detail模板,当然这种方式宽度是固定的,也不支持个性化定制),iOS支持一屏使用多个ViewController。对于这个不成熟的特性,我觉得Apple的文档显得很复杂和不完整,最好的资源还要数Ray&s&iOS5&tutorials和WWDC视频。我花了比预计要多的时间,终于搞好了在iPad上同时显示多个View、在iPhone上显示单个View的布局架构。
  设备翻转
  简单说,在Android上支持设备翻转需要做很多工作,这些工作也是最终导致很多bug的源头,而在iOS上,支持屏幕翻转只需要做一点点工作,剩下就是系统帮我们搞定了。在Android上,屏幕翻转会直接销毁现有整个视图栈(Activity栈),屏幕翻转完成后再重建每个视图。所以在GQueues中支持屏幕翻转,我需要无时无刻保存好所有当前状态,随时保证翻转后能正常恢复状态。而在iOS上,系统会帮你管理所有屏幕翻转相关的细节,唯一需要我关心的就是翻转之后,我需要调整那些没有被Auto&Layout处理好的视图的位置。
  &复杂&布局
  网页开发上有一些常见的布局在GQueues上实现起来非常困难,不管是Android还是iOS。其中一个例子是在任务详细界面显示标签。每个标签都是变长的,在必要时标签需要自动换行。在网页上实现这个只需要设置CSS的float值就可以了。但不管是Android还是iOS对这种&流式布局&(Flow&Layout)都没有原生的支持,这也意味着我需要写很多代码自己去计算和摆放这些标签,以达到&流式布局&的效果。最后Android的代码是基于的演讲内容和的flow&layout实现的。在iOS上也采用了类似的方法,基于容器的总宽度,计算每个标签的宽度,最后设置auto&layout的参数。对于这个布局的实现在两个平台上都耗了很大的工作量。
  旧设备支持
  关于Android的生态系统常被人吐槽的就是严重的系统分化。运营商推送更新的步伐总是很慢,所以现在仍有大量运行着旧系统的设备,这也就意味着如果要保证应用足够大的设备覆盖率,开发者就不能使用新版系统带来的新特性。不过好在现在针对这个问题,Android社区做了很大的努力,提供了一些用于在旧系统上支持新特性的库。通过使用Android官方的&和Jake&Wharton的&Library,我几乎可以在Android&2.2上使用Jelly&Bean(4.2)中所有的新特性。
  对于iOS来说,支持旧系统一说几乎不存在,或者说根本就不是关键。在准备阶段我花了一些时间考虑从哪个iOS版本开始支持,而当时的统计数据显示使用iOS&6系统的设备已经达到,而当时对于放弃支持iPad一代我也有一些疑虑,因为我老爸老妈老姐用的就是iPad一代,他们将是GQueues的铁杆支持者。最后我决定还是只支持iOS&6+,这样我可以放开手使用Auto&Layout,而不需要浪费大量时间实现任何过时的布局技术。当然,我解决了iPad一代的问题(至少对我家里人说来说已经解决),就是换掉他们的iPad一代,给他们每人买一个iPad四代(作者有钱银)。
  数据存储和管理
  对于GQueues来说,数据是核心&-&把数据保存到设备上然后同步到WEB端。Android和iOS有着完全不同的数据管理系统。Android提供了ContentProvider,它是SQLite数据库上层的一个可被继承的应用接口,作为一个结构化框架被用于所有应用的数据处理。ContentProvider学习起来比较难,搞定一个GQueues可用的实现,前期需要花很多工作。一旦搞定了第一步后面的扩展和个性化定制都变得简单多了。
  一些背景信息,GQueues的web&service是基于的,这是一个高扩展性的分布式NoSQL存储系统,而SQLite则是一个标准的关系型数据库,扩展性明显也比较差,但这完全不需要考虑,因为这个应用只存储一个用户的数据。(顺便说一下,架构上我采用了&一个用户对应一个数据库&的设计,这对于快速简单地实现多用户切换有重要意义,不过实现细节可能得再开一博来聊了)。不管怎么说,Android的一个很大的优点就是可以创建来支持。为了支持,搞清楚各种复杂的表关联查询和子查询也花了写功夫,但是这也让Smart&Queues的加载更加高效和快速,因为过滤不是在代码里面实现的(在SQL里面)。
  在iOS上,我用的是,它是iOS上的&schema驱动数据图形管理和持久化框架&,基本上它可以被看做是一个NoSQL存储,不过有趣的是,Core&Data背后实际上是SQLite数据库(呃&实际上SQLite也是几个可选项中最合理的选择)。iOS也允许用户直接创建SQLite数据库,但只支持通过纯C代码来操作,对于其他iOS组件没有原生集成。Core&Data的学习起来也比较困难,但最后我还是选择Core&Data而不用SQLite,因为这样我可以轻松实现很多功能,包括缓存、数据模型迁移支持,还有通过&NSFetchedResultsController,可以非常简单地为界面中的table(列表)提供数据。
  管理数据集的关键就是使用事务,尤其重要是做数据同步的时候&-&ACID,即:atomic(原子性)、consistent(一致性)、isolated(隔离性)、durable(持久性)。Android上实现事务似很直观,跟大部分关系型数据库管理系统的实现方式是一样的,因此,保证数据完整性并不困难。另外,用好SQLite中的UNIQUE&&REPLACE语句,在数据同步的过程中建表、对记录进行原子更新的时候几乎不需要做任何额外工作。
  严格来讲,Core&Data并不完全支持事务。通过使用单独的子ManagedObjectContexts做后台线程处理,再加上@synchronized,能够处理好数据更新和同步,同时避免不正确的写操作覆盖(overwrite)。关于,iOS给的建议帮助很小,总的来说,CoreData给我的赶脚很笨重,并没有它声称的那么好用。另外,在Android上,SQLite可以轻松实现快速加载Smart&Queues,而在iOS上,所有的过滤都必须在代码中实现,就算用了大量的缓存,速度仍然很慢。
  在GQueues&for&Android上增加强大的全文搜索功能很简单,我模仿Google&I/O应用里面的搜索实现,使用了SQLite的特性。首先创建一个虚拟表,然后在一个存储了用户任务的表上设置几个触发器,由这些触发器填充数据到虚拟表。做完了这些,剩下的就是设计一个搜索界面和为搜索历史添加存储。
  iOS的Core&Data对于全文搜索并没有原生支持,所以我通过在谓词(Predicate)中使用LIKE语句,实现基本的任务描述和日记的搜索功能。这个实现当然没有全文搜索那么强大,但我认为它已经能够覆盖现实生活中大部分的使用场景了。
  特性API
  用于比较,我只会列举在GQueues中使用到的几个API。
  快速添加(Quick&Add)
  正则表达式在实现GQueues中解析的时候扮演着一个非常重要的角色,幸运的是,Android和iOS对于正则表达式都有着原生的支持。Android中的Pattern和Matcher从第一个版本起就开始支持,同时也包含了很多正则语法,其中包括前向断言(look-ahead&assertion)和后向断言(look-behind&assertion)。iOS则从iOS&4开始引入类,令人高兴的是,我可以把我在Android上辛辛苦苦写好的正则表达式几乎原封不动地搬到了iOS上。
  在设计界面的时候,我希望用户在查看任务详细的时候左右滑动切换。在Android上我用了&和新的类,FragmentStatePagerAdapter还处于试验阶段,并且只能通过支持库(Support&Library)来使用。我花了几天的时间实现了一个绑定好数据的初级版本,同时解决了几个关于重复菜单项的bug和在数据发生变化后的处理。这些比我预想的要困难很多,要不是因为左右滑动切换任务的用户体验那么好的话,我真不想实现这个功能。iOS上的就简单很多了,虽然也有一些奇怪问题要解决,并且需要自己再加上缓存支持使滑动复杂视图的时候达到可用状态。
  语音输入
  Android提供了了一个先进但很容易使用的speech-to-text&API,只用20行代码,我就把集成到GQueues,提供了一个。但很遗憾,iOS并没有提供支撑SIRI背后技术的API,开发者只能使用第三方库,依赖键盘上的麦克风提供语音输入的支持。我找了各种第三方库,包括&-&SIRI语音识别的提供商,但发现没有免费版本,收费版本价格不菲。所以最后GQueues只能靠用户自己使用键盘上内置的麦克风选项来进行语音输入,其实这也已经足够了,只要用户还记得有这么个功能。
  分享/插件(小部件)
  通过使用Intent,在Android上可以很容易就可以把我的应用集成到安装在用户手机上的其他应用。同样地,只需要很少的代码,通过支持&intent,我就能够让用户在其他应用中创建GQueues任务。Android同时也提供了一个小部件平台,于是我也做了几个小部件,以后还会增加一些。iOS对于跨应用集成和桌面小部件的支持度为零,完全不支持这两个功能。
 测试和发布
  beta测试
  在上面的统计概况表中已经指出,beta版面向真实用户测试了一个多月。两组测试人员都非常棒,帮我找到了数十计的bug,提出了增加一些特性的建议,对一些UI上不合理的地方提出了反馈。我通过私有的Google&Group组织beta测试,这样的beta测试保证了最后发布的应用对人们是真正有用的。在每次beta测试的最后,通过调查问卷我收集到了很多有建设性的反馈,也帮助进一步判断我的应用是否达到了可发布的状态。
  让测试者开始测试只需要发个APK的链接,让他们下载到他们机器上(呃..他们还需要在设置界面中开启&允许安装Google&Play以外的应用&的选项)。Google很方便地支持用真实用户来进行alpha和beta测试,可在中进行设置。在未来的版本更新中我想用用这两个功能。
iOS中的beta测试困难得多,就算用了服务,虽然TestFlight很大程度地简化了流程。为了满足Apple的控制欲,每部测试设备的UUID都要加到用于签名beta版应用的证书当中。因此,每次要添加beta测试者的时候,不论是添加一个人还是一群人,我都需要重新build一遍我的app。除此之外,Apple还限制了你一年最多只能注册100个测试设备。所以我要小心利用好这100个坑,这也是为什么GQueues的iOS测试者只有Android的一半。
  当然,不谈谈发布流程,Android和iOS的比较都不算完,在Google&Play上发布GQueues是一件很好玩的事情,只要我认为已经准备好了,我随时可以发布我的应用。点下按钮之后,30分钟内,我的应用就能在Google&Play上被全世界的用户找到并安装到他们的设备上。而在App&Store上发布一款应用,相信每个iOS开发者都有同样的感受,那是一个令人感到郁闷的经历。经过了数月紧张严密的编码,我只能把我的创作提交给Apple,然后等7天,7天之后审核人员花2分钟看看我的应用,最后拒绝了我的提交。我只能按要求做了修改之后再次提交,我又得等8天才在最后通过了审核。当然还有很多关于提交应用到App&Store的恐怖故事,跟他们比起来,我就像是公园里逛了一圈。尽管如此,在自己的商业控制上要对这样一个&情绪化的第三方平台&做出那么多的让步,仍然让我觉得很不爽。
 获胜的平台
  从上面的分析来看,做GQueues的过程中,并没有出现平台A完胜平台B的情况。Android和iOS在某些领域各有千秋,也都有需要改进的地方。从这两个平台的历史来看,貌似目前Android势头更猛一些,不止体现在市场占有率上,而是看到了Android近两年在UI上的改进和开发平台的稳步提升。而Apple则是封闭的王者,我也坚信他们在很努力地做着他们认为是下一代移动计算革命的事情。不管怎么说,当我想想这6年间所兴起的app生态圈,我为自己在这个移动技术快速更新的时代,能在这两个平台上做开发感到荣幸。
  原文链接: &&&翻译: - neevek
顶一下(0) 踩一下(0)
热门标签:}

我要回帖

更多关于 ios数据库编程 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信