webSocket 和LKDBHelper的使用

socketket与lkdbhelper来处理数据

客户需求:

当我们有需要从自己的后台推送消息给我们的用户时,用户需要实时的接收到来自我们的推送消息。前提是没有使用第三方的推送框架,那么这个使用websocket来接收消息,app端把接收到的消息存储在本地的数据库,让我们直接从数据库去读取数据。

SocketRocket是facebook基于socket进行的二次封装。下面是它的下载地址:

facebook/SocketRocket

LKDBHelper-SQLite-ORM这个第三方库,全自动的插入,查询,更新,删除。 是对sqlite的封装,使开发者不必关心sqlite复杂的语句。这个是github的下载地址:

li6185377/LKDBHelper-SQLite-ORM

从上面的需求中可以分析出做的事情,有2件事需要做。

一、Socket连接获取到后台推送的数据

SocketRocket提供的官方接口:

@interface SRWebSocket : NSObject

// 初始化方法,这只是一种还有很多种,具体请自己看
- (instancetype)initWithURLRequest:(NSURLRequest *)request;

// 代理方法
@property (nonatomic, weak) id <SRWebSocketDelegate> delegate;

// 打开socket
- (void)open;

// 关闭socket
- (void)close;

// 发送数据NSData
- (void)sendData:(nullable NSData *)data error:(NSError **)error;

// Send a UTF8 String 发送字符串数据
- (void)sendString:(NSString *)string error:(NSError **)error;

@end

Socket连接流程:

建议对这个第三方的库进行再一次封装,以便以后需要改换成其它的第三方库,只需要修改此处,而不必去整个工程的修改。

1.发送socket建立连接请求
代码:

/**
 *  Socket建立连接
 */
- (void)connectSocket
{
    //此地址不代表真实地址
    NSString *url = @"xsp://push.lala.com:8888";
    //初始化
    self.socket = [[SRWebSocket alloc] initWithURL:[NSURL URLWithString:url]];
    //设置代理
    self.socket.delegate = self;
    //打开socket连接
    [self.socket open];
}

2.从代理方法中收到连接情况,比如心跳报文等。在这个代理方法里面处理接收到的数据保存到本地数据库中

#pragma mark -- SocketDelegate
/**
 *  收到服务器的消息
 *
 *  @param webSocket socket
 *  @param message  收到服务器的消息,有可能是字符串,或是NSData数据
 */
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message
{
    NSError *error = nil;
    NSString *receiveMessage = (NSString *)message;
    
    //如果数据不能解析,很有可能是后台传的时候有tab键或是空格,找后台排查,或者就用字符替换掉这些多余的字符
    NSData *data = [receiveMessage dataUsingEncoding:NSUTF8StringEncoding];
    
    //NSJSONReadingAllowFragments不管外层的类型是什么
    NSDictionary *responseObj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
    
     NSString *type = responseObj[@"type"];
    //这里的代码不准确,主要是根据后台的返回类型来处理
    NSUInteger index = [NSString stringWithFormat:@"%@",type];

    switch (index) {
        case 0:
        {
            //心跳报文
        }
            break;
            
        case 1:
        {
            //推送的消息1,处理数据,保存到数据库
        }
            break;
            

        case 2:
        {
            //推送的消息2,处理数据,保存到数据库
        }
            break;
            

        default:
            break;
    }
    
}

3.断开连接

/**
 *  Socket断开连接
 *  分为服务器断开和客户端断开
 *  此处为客户端断开
 */
- (void)discononectSocket
{
    //关闭socket连接
    [self.socket close];
    self.socket = nil;
    self.socket.delegate = nil;
}

SocketRocket 提供的代理方法:

@protocol SRWebSocketDelegate <NSObject>
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;

@optional

//socket连接成功
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
//
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithString:(NSString *)string;

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithData:(NSData *)data;

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(nullable NSString *)reason wasClean:(BOOL)wasClean;

@end

服务器中断连接, Socket关闭连接

/**
 *  Socket关闭连接
 *
 *  @param webSocket <#webSocket description#>
 *  @param code      描述
 *  @param reason    原因
 *  @param wasClean  <#wasClean description#>
 */
- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean
{
    self.socket.delegate = nil;
    self.socket = nil;
    
    NSLog(@"socket close原因: %@,",reason);
}

Socket连接失败,客户端断网会调用


/**
 *  Socket连接失败,客户端断网会调用
 *
 *  @param webSocket <#webSocket description#>
 *  @param error     失败原因
 */
- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error
{
    NSLog(@"客户端网络异常:%@",error);
}

暂未使用到

//暂未使用到
- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(NSData *)pongPayload
{
    
}

到这里基本就把Socket的连接和可以接收到服务器的数据了,现在就需要把收到的数据存到本地数据库了。

二、把接受到的信息存储到本地的数据库中

在准备数据库之前需要了解怎么做呢?

1.首先是数据模型

2.把数据转换成模型存储数据库

1.创建一个继承自NSObject的类,如:SQliteModel

#import <Foundation/Foundation.h>

import <YYModel.h>

@interface SQliteModel : NSObject <YYModel>

@end

<u>
注: 此处添加YYModel是为了方便好数据转模型,虽然lkdbhelper里面有映射的方法,个人不是很习惯。
</u>

2.给模型添加字段 SQliteModel.h

#import <Foundation/Foundation.h>
#import <YYModel.h>
#import <LKDBHelper.h>

@interface ptInfo : NSObject <YYModel>

/**发送者名字*/
@property (nonatomic, copy) NSString *sendName;
/**发送头像*/
@property (nonatomic, copy) NSString *headUrl;

@end

@interface SQliteModel : NSObject <YYModel>
/**用户ID*/
@property (nonatomic, copy) NSString *userID;
/**当前时间*/
@property (nonatomic, copy) NSString *ptime;
/**用户名字*/
@property (nonatomic, copy) NSString *userName;
/**联系方法*/
@property (nonatomic, copy) NSString *userPhone;

@property (nonatomic, strong) ptInfo *info;

@end

3.实现方法 SQliteModel.m

#import "SQliteModel.h"

@implementation ptInfo


@end

@implementation SQliteModel

+ (NSDictionary<NSString *,id> *)modelCustomPropertyMapper
{
    return @{@"userID":@"id",@"ptInfo":@"info"};
}

+ (NSDictionary<NSString *,id> *)modelContainerPropertyGenericClass
{
    return @{@"info":[ptInfo class]};
}

/**
 *
 *  @return 是否将父实体类的属性也映射到SQLITE库中
 */
+ (BOOL)isContainParent
{
    return YES;
}

/**
 * 设置数据库的表名,在查询的时候可以根据表名来查询
 * 我在使用的时候不知道为什么不成功。总是提示sqlite语法错误
 */
+ (NSString *)getTableName
{
    return @"SQLiteModel";
}

/**
 * 设置表的单个主键
 */
+ (NSString *)getPrimaryKey
{
    return @"userID";
}


@end

4.Model模型已经准备好了,接下来就是准备开始创建数据库、保存、查询、删除等。

在需要使用的地方包含模型#import "SQliteModel.h"就可以使用了。

4.1 创建并保存到数据库

 case 1:
        {
            //推送的消息1,处理数据,保存到数据库
            
            //获取到的数据为字典
            NSDictionary *dict = responseObj[@"data"];
            //数据转为模型
            SQliteModel *firstModel = [SQliteModel yy_modelWithDictionary:dict];
            
            //保存模型
           BOOL isSaved = [firstModel saveToDB];
            
        }
            break;

保存的时候返回一个BOOL值来判断是否保存数据库成功

多种查询语句的公式如下:

★注意:

单条件:  
@"rowid = 1"  或者  @{@"rowid":@1}

多条件:
@“rowid = 1 and sex = 0"  或者    @{@"rowid":@1,@"sex":@0}
如果是or类型的条件,则只能用字符串的形式:@"rowid = 1 or sex = 0"

in条件:
@"rowid in (1,2,3)"   或者     @{@"rowid":@[@1,@2,@3]}
多条件带in:@"rowid in (1,2,3) and sex=0 "   或者    @{@"rowid":@[@1,@2,@3],@"sex":@0}

时间也只能用字符串:
@"date >= '2013-04-01 00:00:00'"

like也只能用字符串:

@"userName like '%%JY%%'"

因为这个只是写一个流程和思路,所有请按照实际的需求来写代码,不要完全按照我的这个顺序,因为我是全都写在一个- (void)viewDidLoad方法里面,如果完全这样写是不行滴哟!!!!

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSString *userID = @"12345";
    
    LKDBHelper *allHelper = [SQliteModel getUsingLKDBHelper];
    SQliteModel *model = [[SQliteModel alloc] init];
    //1.查询
    //1.1 删除所有的表
    [allHelper dropAllTable];
    
    //1.2 插入数据
    model.userID = @"1129";
    model.userName = @"我是锤锤";
    model.userPhone = @"18786642655";
    model.ptime = @"2016-11-15";
    
    [model saveToDB];
    //1.3 另一种插入方式
    model.userPhone = @"1399998888";
    [allHelper insertToDB:model];
    
    //1.4查询的方式
    /**
     * 第一个参数是查询的条件
     * orderBy:第二个参数是排序是以时间为降序
     * offset:0代表从第0个位置开始,比如在加载更多的时候会用到
     * count:0代表所有的,非0代表一共查询多少行数据
     */
    NSMutableArray *array = @[].mutableCopy;
    array = [SQliteModel searchWithWhere:[NSString stringWithFormat:@"userID=%@",userID] orderBy:@"ptime desc" offset:0 count:0];
    
    if (array.count>0) {
        //将查询到的数据保存到本地的数组中
        //这样看起来有没有很熟悉的感觉?是不是简单多了
        //多说一句,因为我这里并没有写的很详细。请在哪里需要用到的进行自己选择,千万不要看都不看就直接按照我的顺序来炒,那样是不行滴哟。
        //各种组合的查询我后面会给出参考的地址,有需要的请参考。
        self.dataSource = array;
    }
    //查询符合条件的条数
    NSInteger rowCount=[SQliteModel rowCountWithWhere:@"userID=2250"];
    NSLog(@"rowCount %ld",rowCount);
    
    //2.更新,带条件更新
    //根据userID来进行更新
    [SQliteModel updateToDB:model where:@{@"userID":model.userID}];

    
    //3.删除
    
   NSString * user=[allHelper searchSingle:[SQliteModel class] where:@{@"userPhone":@"12345678911"} orderBy:nil];
    BOOL ishas=[allHelper isExistsModel:user];
    if (ishas) {
        [allHelper deleteToDB:user];
    }
    
    //删除多条
    BOOL isDeleteMore=[allHelper deleteWithClass:[SQliteModel class] where:@"userName=1239"];
    if (isDeleteMore) {
        NSLog(@"符合条件的都被删除");
    }
    
}

参考资料:http://www.cnblogs.com/wujy/p/4522493.html

代码下载地址

如果有什么问题请在下方留言,也可以直接Email。
Email:marlonxlj@163.com

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容