ios编程笔记之

来源:互联网 发布:经传软件跟风统计 编辑:程序博客网 时间:2024/05/29 12:20

这里总结整理有关网络编程、sqlite数据库、GCD多线程的使用。

主要参考

一个小时内学习 SQLite 数据库

iOS学习之sqlite的创建数据库,表,插入查看数据

iOS 中sqlite 事务提交代码

在iOS开发中使用FMDB

-------------------------------------------------------------

网络编程(占坑待补)

关于HTTP


-------------------------------------------------------------

sqlite数据库

简介

SQLite 是一个开源的嵌入式关系数据库,实现自包容、零配置、支持事务的SQL数据库引擎。 其特点是高度便携、使用方便、结构紧凑、高效、可靠。 与其他数据库管理系统不同,SQLite 的安装和运行非常简单,在大多数情况下 - 只要确保SQLite的二进制文件存在即可开始创建、连接和使用数据库。


iOS sqlite数据库操作

新建或打开数据库,

创建数据表,
插入数据,
查询数据并打印



一、使用原生的api

先加入sqlite开发库libsqlite3.dylib,相应类文件中导入头文件

#import <UIKit/UIKit.h>  #import <sqlite3.h>      @interface ViewController : UIViewController  {      sqlite3 *db;  }  @end  

sqlite 的方法:
sqlite3          *db ,数据库句柄,跟文件句柄FILE很类似
sqlite3_stmt      *stmt, 这个相当于ODBC的Command对象,用于保存编译好的SQL语句
sqlite3_open(),   打开数据库,没有数据库时创建。
sqlite3_exec(),   执行非查询的sql语句
Sqlite3_step(), 在调用sqlite3_prepare后,使用这个函数在记录集中移动。
Sqlite3_close(), 关闭数据库文件
还有一系列的函数,用于从记录集字段中获取数据,如
sqlite3_column_text(), 取text类型的数据。
sqlite3_column_blob(),取blob类型的数据

sqlite3_column_int(), 取int类型的数据


1、添加库文件

添加使用sqlite的库libsqlite3.dylib,确保在使用到sqlite数据库的类中导入头文件,添加成员变量db

#import <UIKit/UIKit.h>  #import <sqlite3.h>      @interface ViewController : UIViewController  {      sqlite3 *db;  }  @end  

2、打开数据库

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);   NSString *documents = [paths objectAtIndex:0];   NSString *database_path = [documents stringByAppendingPathComponent:DBNAME];      if (sqlite3_open([database_path UTF8String], &db) != SQLITE_OK) {       sqlite3_close(db);       NSLog(@"数据库打开失败");   }  

3、关闭数据库

sqlite3_close(db);  

4、更新数据

使用execu方法执行更新数值的sqlite语句,实现数据库的增、改、删。

-(void)execSql:(NSString *)sql{    char *err;    if (sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK) {        sqlite3_close(db);        NSLog(@"数据库操作数据失败!");    }}
5、查询语句
 NSString *sqlQuery = @"SELECT * FROM PERSONINFO";    sqlite3_stmt * statement;        if (sqlite3_prepare_v2(db, [sqlQuery UTF8String], -1, &statement, nil) == SQLITE_OK) {        while (sqlite3_step(statement) == SQLITE_ROW) {            char *name = (char*)sqlite3_column_text(statement, 1);            NSString *nsNameStr = [[NSString alloc]initWithUTF8String:name];                        int age = sqlite3_column_int(statement, 2);                        char *address = (char*)sqlite3_column_text(statement, 3);            NSString *nsAddressStr = [[NSString alloc]initWithUTF8String:address];                        NSLog(@"name:%@  age:%d  address:%@",nsNameStr,age, nsAddressStr);        }    }    sqlite3_close(db);

6、使用事务

简介:对大批量、有制约关系的数据库操作,可以提高效率,而且数据库更安全

//    @try {//        //        if(sqlite3_exec(iDateContainer.iSql, "BEGIN;", NULL, NULL, &dataErr) == SQLITE_OK)//        {//            NSLog(@"事务启动成功");//            sqlite3_free(dataErr);//            [cur_sm_group_inf Create_Sm_Group_Inf];//            [cur_sm_member_inf Create_Sm_Member_Inf];//            [cur_sm_item_inf Create_Sm_Item_Inf];//         //        sqlite3_exec(iDateContainer.iSql, "delete from sm_member_inf", 0, 0, &dataErr);//        sqlite3_exec(iDateContainer.iSql, "delete from sm_item_inf", 0, 0, &dataErr);//        sqlite3_exec(iDateContainer.iSql, "delete from sm_group_inf", 0, 0, &dataErr);//        //        //        [parser setDelegate:self];//        [parser setShouldProcessNamespaces:NO];//        [parser setShouldReportNamespacePrefixes:NO];//        [parser setShouldResolveExternalEntities:NO];//        //        [parser parse];////            if(sqlite3_exec(iDateContainer.iSql, "COMMIT", NULL, NULL, &dataErr) == SQLITE_OK)//            {//                NSLog(@"事务提交成功");//                //            }//            sqlite3_free(dataErr);//        }else{//            sqlite3_free(dataErr);//            NSLog(@"事务启动失败");//        }//        //        //    }//    @catch (NSException *exception) {//        NSLog(@"事务抛出异常 回滚");//        if (sqlite3_exec(iDateContainer.iSql, "ROLLBACK", NULL, NULL, &dataErr)== SQLITE_OK) {//            NSLog(@"回滚事务成功");//        }//        sqlite3_free(dataErr);//        NSLog(@"failed to sqlite%@",[exception description]);//    }//    @finally {//        NSLog(@"try 处理结束 ");//    }


二、使用第三方包FMDB

前言

http://blog.devtang.com/blog/2012/04/22/use-fmdb/

SQLite (http://www.sqlite.org/docs.html) 是一个轻量级的关系数据库。iOS SDK很早就支持了SQLite,在使用时,只需要加入 libsqlite3.dylib 依赖以及引入 sqlite3.h 头文件即可。但是,原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,开源社区中就出现了一系列将SQLite API进行封装的库,而FMDB (https://github.com/ccgus/fmdb) 则是开源社区中的优秀者。


FMDB在使用上相当方便。以下是一个简单的例子:

NSString* docsdir = [NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) lastObject];NSString* dbpath = [docsdir stringByAppendingPathComponent:@"user.sqlite"];FMDatabase* db = [FMDatabase databaseWithPath:dbpath];[db open];FMResultSet *rs = [db executeQuery:@"select * from people"];while ([rs next]) {    NSLog(@"%@ %@",        [rs stringForColumn:@"firstname"],        [rs stringForColumn:@"lastname"]);}[db close];

可以看到,使用FMDB后的数据库代码清晰明了,比原生的API优雅多了。另外,FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。
使用说明

该使用说明主要翻译自fmdb的github项目说明文档: https://github.com/ccgus/fmdb


1、引入相关文件
首先将FMDB从github上clone下来,然后将以下文件copy到你的工程中:

FMDatabase.hFMDatabase.mFMDatabaseAdditions.hFMDatabaseAdditions.mFMDatabasePool.hFMDatabasePool.mFMDatabaseQueue.hFMDatabaseQueue.mFMResultSet.hFMResultSet.m
2、建立数据库
建立数据库只需要如下一行即可,当该文件不存在时,fmdb会自己创建一个。如果你传入的参数是空串:@”” ,则fmdb会在临时文件目录下创建这个数据库,如果你传入的参数是 NULL,则它会建立一个在内存中的数据库。
<span style="font-size:14px;">FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];</span>
3、打开数据库
使用如下语句,如果打开失败,可能是权限不足或者资源不足。通常打开完操作操作后,需要调用close方法来关闭数据库。

if (![db open]) {    // error     return;}// some operation// ...
[db close];
4、执行更新操作
除了Select操作之外,其它的都是更新操作。更新操作使用如下方法,如果有错误,可以用error参数中获得。
<span style="font-size:14px;">-[FMDatabase executeUpdate:error:withArgumentsInArray:orVAList:]</span>
5、执行查询操作
查询操作示例如下。注意:即使操作结果只有一行,也需要先调用FMResultSet的next方法。

FMResultSet *s = [db executeQuery:@"SELECT * FROM myTable"];while ([s next]) {    //retrieve values for each record}FMResultSet *s = [db executeQuery:@"SELECT COUNT(*) FROM myTable"];if ([s next]) {    int totalCount = [s intForColumnIndex:0];}
6、FMDB提供如下多个方法来获取不同类型的数据:
intForColumn:longForColumn:longLongIntForColumn:boolForColumn:doubleForColumn:stringForColumn:dateForColumn:dataForColumn:dataNoCopyForColumn:UTF8StringForColumnIndex:objectForColumn:
通常情况下,你并不需要关闭FMResultSet,因为相关的数据库关闭时,FMResultSet也会被自动关闭。
7、数据参数
通常情况下,你可以按照标准的SQL语句,用?表示执行语句的参数,如:

INSERT INTO myTable VALUES (?, ?, ?)
然后,可以我们可以调用executeUpdate方法来将?所指代的具体参数传入,通常是用变长参数来传递进去的,如下:
NSString *sql = @"insert into User (name, password) values (?, ?)";[db executeUpdate:sql, user.name, user.password];
这里需要注意的是,参数必须是NSObject的子类,所以象int,double,bool这种基本类型,需要封装成对应的包装类才行,如下所示:
// 错误,42不能作为参数[db executeUpdate:@"INSERT INTO myTable VALUES (?)", 42];// 正确,将42封装成 NSNumber 类[db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:42]];
8、线程安全
如果我们的app需要多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。切记不能在多个线程中共同一个FMDatabase对象并且在多个线程中同时使用,这个类本身不是线程安全的,这样使用会造成数据混乱等问题。
使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。在闭包中操作数据库,而不直接参与FMDatabase的管理。

// 创建,最好放在一个单例的类中FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:aPath];// 使用[queue inDatabase:^(FMDatabase *db) {    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];    FMResultSet *rs = [db executeQuery:@"select * from foo"];    while ([rs next]) {        // …    }}];// 如果要支持事务[queue inTransaction:^(FMDatabase *db, BOOL *rollback) {    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:1]];    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:2]];    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:3]];    if (whoopsSomethingWrongHappened) {        *rollback = YES;        return;    }    // etc…    [db executeUpdate:@"INSERT INTO myTable VALUES (?)", [NSNumber numberWithInt:4]];}];


-------------------------------------------------------------

GCD多线程


什么是GCD
Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法。该方法在Mac OS X 10.6雪豹中首次推出,并随后被引入到了iOS4.0中。GCD是一个替代诸如NSThread, NSOperationQueue, NSInvocationOperation等技术的很高效和强大的技术,它看起来象就其它语言的闭包(Closure)一样,但苹果把它叫做blocks。


应用举例
让我们来看一个编程场景。我们要在iPhone上做一个下载网页的功能,该功能非常简单,就是在iPhone上放置一个按钮,点击该按钮时,显示一个转动的圆圈,表示正在进行下载,下载完成之后,将内容加载到界面上的一个文本控件中。


dispatch queue分成以下三种:
1)运行在主线程的Main queue,通过dispatch_get_main_queue获取。

/*!* @function dispatch_get_main_queue** @abstract* Returns the default queue that is bound to the main thread.** @discussion* In order to invoke blocks submitted to the main queue, the application must* call dispatch_main(), NSApplicationMain(), or use a CFRunLoop on the main* thread.** @result* Returns the main queue. This queue is created automatically on behalf of* the main thread before main() is called.*/__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_4_0)DISPATCH_EXPORT struct dispatch_queue_s _dispatch_main_q;#define dispatch_get_main_queue() \DISPATCH_GLOBAL_OBJECT(dispatch_queue_t, _dispatch_main_q)
可以看出,dispatch_get_main_queue也是一种dispatch_queue_t。
2)并行队列global dispatch queue,通过dispatch_get_global_queue获取,由系统创建三个不同优先级的dispatch queue。并行队列的执行顺序与其加入队列的顺序相同。
3)串行队列serial queues一般用于按顺序同步访问,可创建任意数量的串行队列,各个串行队列之间是并发的。
当想要任务按照某一个特定的顺序执行时,串行队列是很有用的。串行队列在同一个时间只执行一个任务。我们可以使用串行队列代替锁去保护共享的数据。和锁不同,一个串行队列可以保证任务在一个可预知的顺序下执行。
serial queues通过dispatch_queue_create创建,可以使用函数dispatch_retain和dispatch_release去增加或者减少引用计数。


GCD的用法

 //  后台执行: dispatch_async(dispatch_get_global_queue(0, 0), ^{      // something }); // 主线程执行: dispatch_async(dispatch_get_main_queue(), ^{      // something }); // 一次性执行: static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{     // code to be executed once }); // 延迟2秒执行: double delayInSeconds = 2.0; dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); dispatch_after(popTime, dispatch_get_main_queue(), ^(void){     // code to be executed on the main queue after delay }); // 自定义dispatch_queue_t dispatch_queue_t urls_queue = dispatch_queue_create("blog.devtang.com", NULL); dispatch_async(urls_queue, ^{     // your code  }); dispatch_release(urls_queue); // 合并汇总结果 dispatch_group_t group = dispatch_group_create(); dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{      // 并行执行的线程一 }); dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{      // 并行执行的线程二 }); dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{      // 汇总结果 });复制代码一个应用GCD的例子:复制代码    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{        NSURL * url = [NSURL URLWithString:@"http://www.baidu.com"];        NSError * error;        NSString * data = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];        if (data != nil) {            dispatch_async(dispatch_get_main_queue(), ^{                NSLog(@"call back, the data is: %@", data);            });        } else {            NSLog(@"error when download:%@", error);        }    });

GCD的另一个用处是可以让程序在后台较长久的运行
在没有使用GCD时,当app被按home键退出后,app仅有最多5秒钟的时候做一些保存或清理资源的工作。但是在使用GCD后,app最多有10分钟的时间在后台长久运行。这个时间可以用来做清理本地缓存,发送统计数据等工作。
让程序在后台长久运行的示例代码如下:
// AppDelegate.h文件@property (assign, nonatomic) UIBackgroundTaskIdentifier backgroundUpdateTask;// AppDelegate.m文件- (void)applicationDidEnterBackground:(UIApplication *)application{    [self beingBackgroundUpdateTask];    // 在这里加上你需要长久运行的代码    [self endBackgroundUpdateTask];}- (void)beingBackgroundUpdateTask{    self.backgroundUpdateTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{        [self endBackgroundUpdateTask];    }];}- (void)endBackgroundUpdateTask{    [[UIApplication sharedApplication] endBackgroundTask: self.backgroundUpdateTask];    self.backgroundUpdateTask = UIBackgroundTaskInvalid;}

详见博客:

iOS多线程GCD

使用GCD

详解IOS开发应用之并发Dispatch Queues 详解IOS开发应用之并发Dispatch Queues


学习资源:FMDB官方使用文档-GCD的使用-提高性能(翻译)


-------------------------------------------------------------

一、使用原生的api
0 0
原创粉丝点击