IOS 豆瓣--收藏 (数据库操作)

豆瓣项目中 收藏按钮
当用户点击收藏按钮 他会判断用户当前状态 这里状态分为 登陆 和 没有登陆状态

没登陆状态:他会调用登陆界面(这里必须是登陆界面已经设计好)让用户登陆 用户登陆后自动判断是否已经收藏

#pragma  mark 收藏按钮
- (void)addButtonItem
{
    //收藏按钮
    UIBarButtonItem * rightButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"收藏" style:(UIBarButtonItemStylePlain) target:self action:@selector(actionRightButton:)];

    self.navigationItem.rightBarButtonItem = rightButtonItem;
    [rightButtonItem release];
}

上面是添加收藏按钮 以及点击收藏按钮方法 : actionRightButton:

下面是实现 actionRightButton: 方法

- (void)actionRightButton:(UIBarButtonItem *)button
{
    //  判断是否登录  利用单例判断登陆状态  
    BOOL isLogin = [[FileManager shareFileManager] islogin];

    if (isLogin == YES) {
        //  如果登陆  直接操作数据库了  把数据插入到数据库  收藏
        // favorite 是操作数据库方法  下面会 出现
        [self favorite];
    } else {
    //  loginVC 是调用登陆界面  方法
        [self loginVC];
    }
}

当用户没有登陆时会调用 loginVC 登陆方法

//  登录界面
- (void)loginVC
{
//  LoginViewController 是登陆界面 
    LoginViewController *loVC = [[LoginViewController alloc] init];

    __block AcyivitySecondViewController *mySelf = self;

    loVC.block = ^void(){

        NSLog(@"OK");
        //  调用操作数据库方法 
        [mySelf favorite];

    };

    //  给登录界面添加导航条
    UINavigationController *nac = [[UINavigationController alloc] initWithRootViewController:loVC];
    [self presentViewController:nac animated:YES completion:nil];
}

当用户登陆后 也会自动把当前收藏的 数据模型(model) 和数据库中已经添加过的model进行对比 如果已经收藏 也会弹出已经收藏提示 如果还没有收藏 那就会调用数据库 把model 插入到数据库中 并且弹出 收藏成功提示。

下面是调用添加到数据中的方法

//  收藏  去数据库中查询
- (void)favorite
{
//  当已经登陆 也要去判断是否已经收藏 
    //  先判断 是否收藏 去查数据库
    BOOL isFavorite = [[SqLiteManager shareManager] isFavoriteActivityWithID:self.model.ID];
    if (isFavorite == YES) {
    UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"该活动已经被收藏过" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"确定", nil];
        [alertView show];
        [alertView release];
        return;

    } else {
        //  没收藏就收藏下
        //  更改model的收藏属性 再插入
        self.model.isFavorite = YES;
        // 把model插入到数据库
        [[SqLiteManager shareManager] insertWithModel:self.model];
        //显示alertView提示用户
        UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"收藏成功" delegate:nil cancelButtonTitle:nil otherButtonTitles:nil];
        [alertView show];
        [alertView release];
        //0.3秒后alertView消失
        [self performSelector:@selector(p_removeAlertView:) withObject:alertView afterDelay:0.3];
    }
}

下面是关于 数据库 单例

// 先把声明  数据库 需要用到的方法

+ (SqLiteManager *)shareManager;


//  打开数据库
- (sqlite3 *)openDB;

//  关闭数据库
- (void)closeDB;

//  创建表
- (void)createTable;

//  插入数据
- (void)insertWithModel:(ActivityModel *)model;

//  删除数据
- (void)deleteActivity:(ActivityModel *)activity;

//  查询 根据ID
- (ActivityModel *)queryID:(NSString *)ID;

//获取所有活动
- (NSArray *)selectAllActivity;


//判断活动是否被收藏
- (BOOL)isFavoriteActivityWithID:(NSString *)ID;

实现 单例 数据库 中声明的方法

+ (SqLiteManager *)shareManager
{
    static SqLiteManager *manager = nil;
    if (manager == nil) {
        manager = [[SqLiteManager alloc] init];
        //  创建表
        [manager createTable];
    }
    return manager;
}


//  定义一个静态区指针 连接数据库 让数据库再程序结束后自动释放
static sqlite3 *db = nil;
// 打开数据库
- (sqlite3 *)openDB
{
    if (db != nil) {
        return db;
    }

    NSString *dbPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"ActivityList.sqlite"];
    NSLog(@"--------------%@", dbPath);
    //  有这个库  就打开   没有就创建一个
    int result = sqlite3_open(dbPath.UTF8String, &db);

    if (result == SQLITE_OK) {
        NSLog(@"打开数据库成功");
    } else {
        NSLog(@"打开数据库失败");
    }

    return db;
}

//  关闭数据库
- (void)closeDB
{
    int result = sqlite3_close(db);
    if (result == SQLITE_OK) {
        // 切记  不要忘掉  在关闭数据库的时候  把db置为空  
         db = nil;

        NSLog(@"关闭数据库成功");

    } else {
        NSLog(@"关闭数据库失败");
    }
}

//  创建表
- (void)createTable
{
    db = [self openDB];

    //  创建一张表的时候  最重要的就是   这个唯一码 (主键)
    // 主键  ID
    // 属性: title  imageUrl
    // 数据模型归档后  data  因为数据库存放的数据类型有限  不能存放数据模型  必须把数据模型 归档成数据库  能接受的模型  这里把  数据模型转化为  NSData类型

    NSString *sql = @"CREATE TABLE IF NOT EXISTS ActivityList (ID TEXT PRIMARY KEY not NULL, title TEXT not NULL, imageUrl TEXT not NULL, data BLOB not NULL)";

    //  创建多张表
    //  @"CREATE TABLE IF NOT EXISTS ActivityList (ID TEXT PRIMARY KEY not NULL, title TEXT not NULL, imageUrl TEXT not NULL, data BLOB not NULL);CREATE TABLE IF NOT EXISTS MoveList (ID TEXT PRIMARY KEY not NULL, title TEXT not NULL, imageUrl TEXT not NULL, data BLOB not NULL)"
      //  第三个参数  是一个回调的函数
    //  第四个参数  是函数携带的参数
    // 最后一个是错误信息
    int result = sqlite3_exec(db, sql.UTF8String, NULL, NULL, NULL);

    if (result == SQLITE_OK) {
        NSLog(@"创建表成功");
    } else {
        NSLog(@"创建表失败");
    }

    [self closeDB];


}

//  插入数据  接收传过来的model  需要把model 归档 再放入数据库
- (void)insertWithModel:(ActivityModel *)model
{
    db = [self openDB];

    sqlite3_stmt * stmt = nil;

    NSString * sql = @"insert into ActivityList (ID,title,imageUrl,data) values (?,?,?,?)";

   //  如果程序中插入的数据中有data文件   使用sqlite3_exec  执行语句的话
    //  程序会把这个data文件  转化成字符串存进数据库  而不是 咱们要的数据


    int result = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL);

    if (result == SQLITE_OK) {

        //  绑定? 参数二 插入字段顺序 从1开始
        sqlite3_bind_text(stmt, 1, [model.ID UTF8String], -1, NULL);
        sqlite3_bind_text(stmt, 2, [model.title UTF8String], -1, NULL);
        sqlite3_bind_text(stmt, 3, [model.image UTF8String], -1, NULL);

        //  拼接归档时的key  保证唯一
         // 数据模型归档后  data  因为数据库存放的数据类型有限  不能存放数据模型  必须把数据模型 归档成数据库  能接受的模型  这里把  数据模型转化为  NSData类型
        NSString * archiverKey = [NSString stringWithFormat:@"%@%@",kActivityArchiverKey,model.ID];

        //  把model进行归档  得到插入数据库的data
        NSData * data = [[FileManager shareFileManager] dataOfArchiverObject:model forKey:archiverKey];

        // blob 表示 data类型在数据库中的类型
        //  参数3  data 的大小
        //  参数4 data 的长度  注意转换类型  需要int类型
        // 参数5  
        sqlite3_bind_blob(stmt, 4, [data bytes], (int)[data length], NULL);

        //  执行上面命令
        sqlite3_step(stmt);

    }

    sqlite3_finalize(stmt);


    [self closeDB];
}

//  删除数据
- (void)deleteActivity:(ActivityModel *)activity
{
    db = [self openDB];
    NSString *sql = [NSString stringWithFormat:@"delete from ActivityList where ID = '%@'",activity.ID];
    int result = sqlite3_exec(db, sql.UTF8String, NULL, NULL, NULL);
    if (result == SQLITE_OK) {
        NSLog(@"删除成功");
    } else {
        NSLog(@"删除失败");
    }

    [self closeDB];

}


#pragma mark 查询
- (ActivityModel *)queryID:(NSString *)ID
{
    NSString * archiverKey = [NSString stringWithFormat:@"%@%@",kActivityArchiverKey,ID];

    db = [self openDB];

    //  根据ID 查询对应的Data

    //  原来是 * 查询所有的字段  现在咱们就把对应的data取出来就行
    //  查询  这里也用到反归档
    // data是归档后  放入到数据库中的data     这里是根据  ID  查询出来 data
    NSString *sql = [NSString stringWithFormat:@"select data from ActivityList where ID = '%@'",ID];

    //  创建一个跟随指针
    sqlite3_stmt *stmt = nil;

    //  执行sql语句
    sqlite3_prepare_v2(db, sql.UTF8String, -1, &stmt, NULL);

    //  绑定 查询字段ID 根据ID查询  从1开始
    //
    sqlite3_bind_text(stmt, 1, ID.UTF8String, -1, NULL);

    //  定义一个model接收  从库中查出的数据
    ActivityModel *model = nil;

    while (sqlite3_step(stmt) == SQLITE_ROW) {

        //  第二个参数 列数  查询的列数 从零开始

        // * 的时候查询数据库中所有的   要按照顺序写第二个参数
        // 如果 只查询一个 这个参数 要按照你查询的列数来写
        //  把取出来的data和字节数转换成  oc的data
        NSData *data = [NSData dataWithBytes:sqlite3_column_blob(stmt, 0) length:sqlite3_column_bytes(stmt, 0)];

        //  把取出来的model 反归档 返回
        model = [[FileManager shareFileManager] unarchiverObject:data forKey:archiverKey];


    }

    sqlite3_finalize(stmt);

    [self closeDB];

    return model;

}


//判断活动是否被收藏
- (BOOL)isFavoriteActivityWithID:(NSString *)ID
{
    // 插入数据库之前  先查询数据库  如果返回的model有值  说明已经收藏了
    ActivityModel * model = [self queryID:ID];

    if (model == nil) {
        return NO;
    }
    return YES;
}



//获取所有活动
- (NSArray *)selectAllActivity
{

    [self openDB];

    sqlite3_stmt * stmt = nil;

    //  查询所有的 ID,data
    NSString * sql = @"select ID,data from ActivityList";

    int result = sqlite3_prepare_v2(db, [sql UTF8String], -1, &stmt, NULL);

    NSMutableArray * activityArray = [NSMutableArray array];

    if (result == SQLITE_OK) {

        while (sqlite3_step(stmt) == SQLITE_ROW) {

            NSString * ID = [NSString stringWithUTF8String:(const char *)sqlite3_column_text(stmt, 0)];

            NSData * data = [NSData dataWithBytes:sqlite3_column_blob(stmt, 1) length:sqlite3_column_bytes(stmt, 1)];

            NSString * archiverKey = [NSString stringWithFormat:@"%@%@",kActivityArchiverKey,ID];

            //  查询出来反归档  把model放在数组里面  返回去
            ActivityModel * model = [[FileManager shareFileManager] unarchiverObject:data forKey:archiverKey];
            [activityArray addObject:model];
        }

    }

    sqlite3_finalize(stmt);

    [self closeDB];

    return activityArray;
}

上面是数据库的操作 在数据库操作中 用到 对数据的归档
对数据的归档 就是 以一种存放数据的形式
下面介绍归档 与接档

#pragma mark 归档方法(存数据)  你要注意归档的  属性的类型  要与  调用的方法对应   这是把数据模型中的声明的属性  进行归档  与 接档 

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.ID forKey:@"ID"];
    [aCoder encodeObject:self.title forKey:@"title"];
    [aCoder encodeObject:self.begin_time forKey:@"begin_time"];
    [aCoder encodeObject:self.end_time forKey:@"end_time"];
    [aCoder encodeObject:self.address forKey:@"address"];
    [aCoder encodeObject:self.category_name forKey:@"category_name"];
    [aCoder encodeObject:self.image forKey:@"image"];
    [aCoder encodeObject:self.content forKey:@"content"];
    [aCoder encodeObject:self.wisher_count forKey:@"wisher_count"];
    [aCoder encodeObject:self.participant_count forKey:@"participant_count"];
    [aCoder encodeObject:self.imagePath forKey:@"imagePath"];
    [aCoder encodeBool:self.isDownloading forKey:@"isDownloading"];
    [aCoder encodeBool:self.isFavorite forKey:@"isFavorite"];

}


#pragma mark 反规当(取数据)  你要注意归档的  属性的类型  要与  调用的方法对应
- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self) {

        self.ID = [aDecoder decodeObjectForKey:@"ID"];
        self.title = [aDecoder decodeObjectForKey:@"title"];
        self.begin_time = [aDecoder decodeObjectForKey:@"begin_time"];
        self.end_time = [aDecoder decodeObjectForKey:@"end_time"];
        self.address = [aDecoder decodeObjectForKey:@"address"];
        self.category_name = [aDecoder decodeObjectForKey:@"category_name"];
        self.image = [aDecoder decodeObjectForKey:@"image"];
        self.content = [aDecoder decodeObjectForKey:@"content"];
        self.wisher_count = [aDecoder decodeObjectForKey:@"wisher_count"];
        self.participant_count = [aDecoder decodeObjectForKey:@"participant_count"];
        self.imagePath = [aDecoder decodeObjectForKey:@"imagePath"];
        self.isDownloading = [aDecoder decodeBoolForKey:@"isDownloading"];
        self.isFavorite = [aDecoder decodeBoolForKey:@"isFavorite"];
    }

    return self;
}

在单例中用到 也要归档和接档

#pragma mark -- 将对象归档 反归档

//将对象归档  数据操作调用到  dataOfArchiverObject 方法  传进来一个model 
//  把传进来的model 归档成数据库接受的类型  NSMutableData
- (NSData *)dataOfArchiverObject:(id)object forKey:(NSString *)key
{
    NSMutableData * data = [NSMutableData data];
    //  NSKeyedArchiver 归档方法
    NSKeyedArchiver * archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];

    [archiver encodeObject:object forKey:key];
    [archiver finishEncoding];

    [archiver release];
    //  返回归档后的  data
    return data;
}

//反归档(接档 / 反编码)
- (id)unarchiverObject:(NSData *)data forKey:(NSString *)key
{

    NSKeyedUnarchiver * unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];

    id object = [unarchiver decodeObjectForKey:key];

    [unarchiver finishDecoding];

    [unarchiver release];

    return object;

基本思路:当用户点击页面上 收藏按钮的时候 他会自动判断当前用户的状态
这里的状态分为 登陆状态 和 未登陆状态

登陆状态 :
在登陆状态下 他会去数据库中查找是否已经存在判断当前的 数据模型 是否已经收藏 如果已经收藏 他就会自动弹出 已经收藏

如果没有收藏 他会把数据模型插入到 数据库中 由于数据库存放的数据类型有限制 所以 不能直接把数据模型 插入到数据库中 这里就用到了 对数据模型的 归档和接档
归档 : 基本用在往数据库中插入数据的时候
接档:基本用在 从数据库中查询的时候

未有登录状态:
在用户点击收藏没有登陆状态下 会自动弹出登陆界面 让用户登陆 只有登陆后才能进行收藏
当用户登陆后 会自动调用数据库 把当前的数据模型和 数据库中已经添加过得数据模型 进行对比 是否存在 如果已经存在 就会弹出已经收藏 如果没有收藏 那就会往数据库中插入数据模型

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值