首页 > 移动平台 > 详细

iOS 面向模型的 SQL存储

时间:2017-01-08 22:23:18      阅读:327      评论:0      收藏:0      [点我收藏+]

本地化存储也是app开发当中比较常见的功能需求。比如一些列表界面(tableview)相关的数据存储。

本文就以tableview界面数据的存储为例。

为简单起见,demo中使用了MJExtension及MJRefresh框架,采用常用的MVC代码结构,我们将在此基础上扩展其本地化存储功能。列表界面的核心代码如下(灰色背景的部分表示将要实现和扩展的方法):

- (void)setupRefresh {

    self.tableView.mj_header = [XMGRefreshHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewTopics)];

    [self.tableView.mj_header beginRefreshing];

        self.tableView.mj_footer = [XMGRefreshFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreTopics)];

}

#pragma mark - 数据加载

- (void)loadNewTopics {

    // 取消所有请求

    [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];

    // 参数

    NSMutableDictionary *params = [NSMutableDictionary dictionary];

    params[@"a"] = self.aParam;

    params[@"type"] = @(self.type);

    __weak typeof(self) weakSelf = self;

    // 发送请求

    [self.manager GET:XMGCommonURL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {

        // 存储maxtime(方便用来加载下一页数据)

        weakSelf.maxtime = responseObject[@"info"][@"maxtime"];

           // 字典数组 -> 模型数组

        weakSelf.topics = [XMGTopic mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];

            // 2. 在本地sql做缓存  todo

       [weakSelf saveToSql: weakSelf.topics ] ;  

              // 刷新表格

        [weakSelf.tableView reloadData];

              // 让[刷新控件]结束刷新

        [weakSelf.tableView.mj_header endRefreshing];

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        // 让[刷新控件]结束刷新

        [weakSelf.tableView.mj_header endRefreshing];

        // 加载缓存、本地数据库 todo

            [weakSelf getFromeSql];

          // 刷新表格

        [weakSelf.tableView reloadData];

        }];

}

 

- (void)loadMoreTopics

{

    // 取消所有的请求

    [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)];

     // 参数

    NSMutableDictionary *params = [NSMutableDictionary dictionary];

    params[@"a"] = self.aParam;

    params[@"maxtime"] = self.maxtime;

    params[@"type"] = @(self.type);

 

    __weak typeof(self) weakSelf = self;

    // 发送请求

    [self.manager GET:XMGCommonURL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id  _Nonnull responseObject) {

        // 存储这页对应的maxtime

        weakSelf.maxtime = responseObject[@"info"][@"maxtime"];

        

        // 字典数组 -> 模型数组

        NSArray<XMGTopic *> *moreTopics = [XMGTopic mj_objectArrayWithKeyValuesArray:responseObject[@"list"]];

        [weakSelf.topics addObjectsFromArray:moreTopics];

        

        // 插入新增的数据至数据库

        [[SQLiteManager shareSQLiteManager] saveTopics:moreTopics];

        // 刷新表格

        [weakSelf.tableView reloadData];

        

        // 让[刷新控件]结束刷新

        [weakSelf.tableView.mj_footer endRefreshing];

    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {

        XMGLog(@"请求失败 - %@", error);

        

        // 让[刷新控件]结束刷新

        [weakSelf.tableView.mj_footer endRefreshing];

 }];

}

     

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.topics.count;

}

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    XMGTopicCell *cell = [tableView dequeueReusableCellWithIdentifier:XMGTopicCellId];

    cell.topic = self.topics[indexPath.row];

     return cell;

}

#pragma mark - 代理方法

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

{

//    return self.topics[indexPath.row].cellHeight;

    return 600;

}

这是面向模型的开发模式,模型类相关属性如下:

 @interface XMGTopic : NSObject

/** 用户的名字 */

@property (nonatomic, copy) NSString *name;

/** 用户的头像 */

@property (nonatomic, copy) NSString *profile_image;

/** 帖子的文字内容 */

@property (nonatomic, copy) NSString *text;

/***** 额外增加的属性 - 方便开发 *****/

/** cell的高度 */

@property (nonatomic, assign) CGFloat cellHeight;

/** 中间内容的frame */

@property (nonatomic, assign) CGRect contentF;

@end

其实如果单纯的实现存储的功能,简单粗暴的方法就是直接将模型、或者原始的字典或数组整体进行存储。但是这样的话就不方便相关的统计、搜索,后期需要扩展这些功能的话笨重而不灵活。

所以这里就将模型属性一一对应进行sql的数据存储。设计一个工具类SQLiteManager,核心代码如下(本次旨在实现功能,代码还可以优化重构,或采用运行时机制减少侵入性):

#import "SQLiteManager.h"

#import <sqlite3.h>

#import "XMGTopic.h"

 @interface SQLiteManager ()

{    sqlite3 *db;}

@end

 @implementation SQLiteManager

 + (instancetype)shareSQLiteManager {

    static SQLiteManager *instance = nil;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        instance = [[SQLiteManager alloc] init];

    });

    return  instance;

}

 

- (instancetype)init

{

    if (self = [super init]) {

        NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;

        NSString *filePath = [path stringByAppendingPathComponent:@"demo.sqlite"];

        NSLog(@"%@", filePath);

        

        if (sqlite3_open([filePath UTF8String], &db) == SQLITE_OK)

        {    NSLog(@"打开成功");

            [self createTable];

        }

    }

    return  self;

}

 

- (BOOL)createTable {

    NSString *sql = @"CREATE TABLE IF NOT EXISTS t_topic(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, profile_image TEXT, text TEXT, cellHeight FLOAT);";

    return [self execSQL:sql];

}

 

- (BOOL)dropTable {

    NSString *sql  = @"drop table if exists t_stu;";

    return [self execSQL:sql];

}

  

- (BOOL)execSQL:(NSString *)sql {

    return  sqlite3_exec(db, [sql UTF8String], NULL, NULL, NULL) == SQLITE_OK;

}

 

- (void)saveTopics:(NSArray *)topics {    

    for(XMGTopic* topic in topics) {

        NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_topic(name, profile_image, text, cellHeight) VALUES(‘%@‘, ‘%@‘, ‘%@‘, %f);", topic.name, topic.profile_image, topic.text, topic.cellHeight];

         sqlite3_stmt *stmt = nil;

        if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, nil) != SQLITE_OK)    return;

        if (sqlite3_step(stmt) == SQLITE_DONE){            

            NSLog(@"插入一条记录成功!");

       }

           sqlite3_finalize(stmt);

 }

}

 

  // 返回模型数组

- (NSArray *)getTopics  {

      NSString *sql = @"select * from t_topic;";

     // 准备语句

    sqlite3_stmt *stmt = nil;

    if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, nil) != SQLITE_OK)    {       

        NSLog(@"准备语句创建失败!");

        return nil;

    }    

    NSMutableArray *arrM = [NSMutableArray array];

    while (sqlite3_step(stmt) == SQLITE_ROW) {

        int count = sqlite3_column_count(stmt);

   id value;

   for (int i = 0; i < count; ++i) {        

        const char *cName = sqlite3_column_name(stmt, i);

        NSString *columnNameStr = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];

        NSLog(@"ddddddd%@",columnNameStr);

        int type = sqlite3_column_type(stmt, i);

        switch (type) {

            case SQLITE_INTEGER:

            {   int value = sqlite3_column_int(stmt, i);

            }

                break;

             case SQLITE_FLOAT:

            {   double value = sqlite3_column_double(stmt, i);

           }

                break;

            case SQLITE3_TEXT:

            {

                const char *textValue = sqlite3_column_text(stmt, i);

                value = [NSString stringWithCString:textValue encoding:NSUTF8StringEncoding];

            }

                break;

            case SQLITE_NULL:

                break;

              default:

                break;

        }

        XMGTopic *topicItem = [[XMGTopic alloc]init];

        if ([columnNameStr isEqualToString: @"name"]) {

            topicItem.name = (NSString *)value;

        }

        if ([columnNameStr isEqualToString: @"profile_image"]) {

            topicItem.profile_image = (NSString *)value;

        }

        if ([columnNameStr isEqualToString: @"text"]) {

            topicItem.text = (NSString *)value;

         }

        if ([columnNameStr isEqualToString: @"cellHeight"]) {

         topicItem.cellHeight = [value  doubleValue];

          }

        [arrM addObject:topicItem];

     }

    }

return  [arrM copy];

}

@end

 现在就可以实现存储的这两个方法了。

- (NSArray *)getFromeSql  {

if (topics != nil) return ;

return [[SQLiteManager shareSQLiteManager] getTopics];

}

- (void)saveToSql:(NSArray *)topics {

        [[SQLiteManager shareSQLiteManager] dropTable];

       //删除表后需要重新创建表单,此时单例是没有表的。注意理解单例

        [[SQLiteManager alloc] init] ;

        [[SQLiteManager shareSQLiteManager] saveTopics:weakSelf.topics];

}

 

iOS 面向模型的 SQL存储

原文:http://www.cnblogs.com/imsz/p/6262857.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!