webSocket 和LKDBHelper的使用

作者: marlonxlj | 来源:发表于2016-11-16 00:16 被阅读381次

    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

    相关文章

      网友评论

        本文标题:webSocket 和LKDBHelper的使用

        本文链接:https://www.haomeiwen.com/subject/qcwlpttx.html