ios编程笔记之

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

主要参考

一个小时内学习 SQLite 数据库

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

iOS 中sqlite 事务提交代码

在iOS开发中使用FMDB

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

网络编程(占坑待补)

关于HTTP


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

sqlite数据库

简介

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


iOS sqlite数据库操作

新建或打开数据库,

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



一、使用原生的api

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

#import   
#import   
  
  
@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   
#import   
  
  
@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.h
FMDatabase.m
FMDatabaseAdditions.h
FMDatabaseAdditions.m
FMDatabasePool.h
FMDatabasePool.m
FMDatabaseQueue.h
FMDatabaseQueue.m
FMResultSet.h
FMResultSet.m
2、建立数据库
建立数据库只需要如下一行即可,当该文件不存在时,fmdb会自己创建一个。如果你传入的参数是空串:@”” ,则fmdb会在临时文件目录下创建这个数据库,如果你传入的参数是 NULL,则它会建立一个在内存中的数据库。
FMDatabase *db = [FMDatabase databaseWithPath:@"/tmp/tmp.db"];
3、打开数据库
使用如下语句,如果打开失败,可能是权限不足或者资源不足。通常打开完操作操作后,需要调用close方法来关闭数据库。

if (![db open]) {
    // error 
    return;
}
// some operation
// ...
[db close];
4、执行更新操作
除了Select操作之外,其它的都是更新操作。更新操作使用如下方法,如果有错误,可以用error参数中获得。
-[FMDatabase executeUpdate:error:withArgumentsInArray:orVAList:]
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

你可能感兴趣的:(ios开发)