iOS開發中SQLite死鎖問題(OC版)

iOS開發中SQLite死鎖問題(OC版)

翻自己的博客發現自己以前寫過如何使用SQLite,然後當時好像沒提死鎖的事情。因爲SQLite只支持單線程的,所以如果碰到多個功能需要訪問SQLite的,很有可能引起死鎖問題。當然了,現在可能都用Swift不用OC了,但是爲了方案的完整性,我還是要記錄一下這件事情。

那麼比較常見的就是@synchronized關鍵字,這個Java的同學應該很熟悉,過多的解釋也沒什麼好說的,前人都已經栽樹成林了,我沒必要再多囉嗦了。

以下是兩年前的代碼了,也是爲了補之前那篇博客《iOS SQLite3 “增刪改查”(Objective-C)》的坑

代碼或者博客寫的不好,還請多多指教,感謝!

//
//  SQLite.h
//
//  Created by Zhan on 16/9/8.
//  Copyright © 2016年 Michael Zhan. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <sqlite3.h>

typedef void (^SelectBlock)(NSMutableArray * mutableArray);
typedef void (^DBFailureBlock)(void);
typedef void (^Success)(void);
typedef void (^Failed)(void);

@interface ContactDB : NSObject

+ (ContactDB *)sharedDataBaseHandle;
-(sqlite3 *)openDB;
-(void)createTable;
-(void)dropTable:(Success)successBlock failed:(Failed)failedBlock;

-(void)insert_name:(NSString *)name phone:(NSString *)phone headimg:(NSString *)path deptId:(NSString *)deptId deptName:(NSString *)deptName uppercase:(NSString *)uppercase userId:(NSString *)userId mail:(NSString *)mail;

-(void)loadContact:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock;

-(void)select_name:(NSString *)name success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock;
-(void)select_phone:(NSString *)phone success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock;
-(void)select_uppercase:(NSString *)uppercase success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock;

-(void)select_userId:(NSString *)userId success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock;

-(void)select_deptName:(NSString *)deptName success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock;

-(void)closeDB;

+ (void)destroyDealloc;

@end
//
//  SQLite.m
//
//  Created by Zhan on 16/9/8.
//  Copyright © 2016年 Michael Zhan. All rights reserved.
//

#import "ContactDB.h"

@implementation ContactDB

static ContactDB *manager = nil;
static sqlite3 * db = nil;  //設置句柄 通過句柄對數據庫進行操作
static bool isOperation;

+(ContactDB *)sharedDataBaseHandle{
    if (manager == nil) {
        manager = [[ContactDB alloc] init];
        isOperation = false;
    }
    return manager;
}

-(sqlite3 *)openDB{
    if (db != nil) {
        return db;
    }
    NSArray *test = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
    NSString * fileName = [[test lastObject]stringByAppendingPathComponent:@"Contact"];
    NSLog(@"%@",fileName);  //打印路徑
    sqlite3_open(fileName.UTF8String, &db);
    [self dropTable:^{
        [self createTable];
    } failed:^{
        
    }];
    return db;
}

-(void)createTable{
    NSString * sql = [[@"create table if not exists "stringByAppendingString:@"Contact"]stringByAppendingString:@" (id integer primary key autoincrement not null, name text not null, phone text not null, headimg text null, deptId text not null, deptName text not null, uppercase text null, userId text not null, mail text null);"];
    //    NSLog(@"sql : %@",sql);
    if(db == nil){
        return;
    }
    sqlite3_exec(db, sql.UTF8String, NULL, NULL, NULL);
//    NSLog(@"create contact error : %s",err);
}

-(void)loadContact:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock{
    sqlite3_stmt *statement = nil;
    NSString *sql = @"select * from Contact";
    //    NSLog(@"sql == %@",sql);
//    BOOL hasRow = false;
    if(db == nil && isOperation == true){
        return;
    }
    NSMutableArray * mutableArray = [[NSMutableArray alloc]init];
    isOperation = true;
    @synchronized(self){
        if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil) == SQLITE_OK) {
            while (sqlite3_step(statement) == SQLITE_ROW) {
    //            hasRow = true;
                NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc]init];
                
                char *name = (char *)sqlite3_column_text(statement, 1);
                NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
                [mutableDictionary setObject:nameStr forKey:@"name"];
                
                char *phone = (char *)sqlite3_column_text(statement, 2);
                NSString *phoneStr = [[NSString alloc]initWithUTF8String:phone];
                [mutableDictionary setObject:phoneStr forKey:@"phone"];
                
                char *headimg = (char *)sqlite3_column_text(statement, 3);
                NSString *headimgStr = [[NSString alloc]initWithUTF8String:headimg];
                [mutableDictionary setObject:headimgStr forKey:@"headimg"];
                
                char *deptId = (char *)sqlite3_column_text(statement, 4);
                NSString *deptIdStr = [[NSString alloc]initWithUTF8String:deptId];
                [mutableDictionary setObject:deptIdStr forKey:@"deptId"];
                
                char *deptName = (char *)sqlite3_column_text(statement, 5);
                NSString *deptNameStr = [[NSString alloc]initWithUTF8String:deptName];
                [mutableDictionary setObject:deptNameStr forKey:@"deptName"];
                
                char *uppercase = (char *)sqlite3_column_text(statement, 6);
                NSString *uppercasetStr = [[NSString alloc]initWithUTF8String:uppercase];
                [mutableDictionary setObject:uppercasetStr forKey:@"uppercase"];
                
                char *userId = (char *)sqlite3_column_text(statement, 7);
                NSString *userIdStr = [[NSString alloc]initWithUTF8String:userId];
                [mutableDictionary setObject:userIdStr forKey:@"userId"];
                
                char *mail = (char *)sqlite3_column_text(statement, 8);
                NSString *mailStr = [[NSString alloc]initWithUTF8String:mail];
                [mutableDictionary setObject:mailStr forKey:@"mail"];
                
                [mutableArray addObject:mutableDictionary];
            }
            isOperation = false;
            successBlock(mutableArray);
        }else{
            failureBlock();
        }
        sqlite3_finalize(statement);
    }
}

- (void)insert_name:(NSString *)name phone:(NSString *)phone headimg:(NSString *)path deptId:(NSString *)deptId deptName:(NSString *)deptName uppercase:(NSString *)uppercase userId:(NSString *)userId mail:(NSString *)mail{
        BOOL hasInfo = false;
        sqlite3_stmt *statement = nil;
        NSString *select = [[@"select * from Contact where userId = '"stringByAppendingString:userId]stringByAppendingString:@"'"];
        @synchronized (self) {
            if(db == nil && isOperation == true){
                return;
            }
            isOperation = true;
            if (sqlite3_prepare_v2(db, [select UTF8String], -1, &statement, nil) == SQLITE_OK) {
                while (sqlite3_step(statement) == SQLITE_ROW) {
                    hasInfo = true;
                    break;
                }
            }
            uppercase = [uppercase stringByReplacingOccurrencesOfString:@" " withString:@""];
            NSString * sql;
            if(hasInfo){
                sql = [NSString stringWithFormat:@"update Contact set name = '%@', phone = '%@', headimg = '%@', deptId = '%@', deptName = '%@', uppercase = '%@', mail = '%@' where userId = '%@'",name, phone, path, deptId, deptName, uppercase, mail, userId];
            }else{
                sql = [NSString stringWithFormat:@"insert into Contact (name, phone, headimg, deptId, deptName, uppercase, userId, mail) VALUES('%@', '%@', '%@', '%@', '%@', '%@', '%@', '%@')", name, phone, path, deptId, deptName, uppercase, userId, mail];
            }
            sqlite3_exec(db, sql.UTF8String, NULL, NULL, NULL);
            isOperation = false;
            sqlite3_finalize(statement);
        }
  
-(void)select_name:(NSString *)name success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock{
    sqlite3_stmt *statement = nil;
    NSString *sql = [[@"select * from Contact where name LIKE '%"stringByAppendingString:name]stringByAppendingString:@"%'"];
    NSMutableArray * mutableArray = [[NSMutableArray alloc]init];
    if(db == nil && isOperation == true){
        return;
    }
    isOperation = true;
    @synchronized (self) {
        if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil) == SQLITE_OK) {
            while (sqlite3_step(statement) == SQLITE_ROW) {
                NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc]init];
                
                char *name = (char *)sqlite3_column_text(statement, 1);
                NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
                [mutableDictionary setObject:nameStr forKey:@"name"];
                
                char *phone = (char *)sqlite3_column_text(statement, 2);
                NSString *phoneStr = [[NSString alloc]initWithUTF8String:phone];
                [mutableDictionary setObject:phoneStr forKey:@"phone"];
                
                char *headimg = (char *)sqlite3_column_text(statement, 3);
                NSString *headimgStr = [[NSString alloc]initWithUTF8String:headimg];
                [mutableDictionary setObject:headimgStr forKey:@"headimg"];
                
                char *deptId = (char *)sqlite3_column_text(statement, 4);
                NSString *deptIdStr = [[NSString alloc]initWithUTF8String:deptId];
                [mutableDictionary setObject:deptIdStr forKey:@"deptId"];
                
                char *deptName = (char *)sqlite3_column_text(statement, 5);
                NSString *deptNameStr = [[NSString alloc]initWithUTF8String:deptName];
                [mutableDictionary setObject:deptNameStr forKey:@"deptName"];
                
                char *uppercase = (char *)sqlite3_column_text(statement, 6);
                NSString *uppercasetStr = [[NSString alloc]initWithUTF8String:uppercase];
                [mutableDictionary setObject:uppercasetStr forKey:@"uppercase"];
                
                char *userId = (char *)sqlite3_column_text(statement, 7);
                NSString *userIdStr = [[NSString alloc]initWithUTF8String:userId];
                [mutableDictionary setObject:userIdStr forKey:@"userId"];
                
                char *mail = (char *)sqlite3_column_text(statement, 8);
                NSString *mailStr = [[NSString alloc]initWithUTF8String:mail];
                [mutableDictionary setObject:mailStr forKey:@"mail"];
                
                [mutableArray addObject:mutableDictionary];
            }
            isOperation = false;
            successBlock(mutableArray);
        }else{
            failureBlock();
        }
        sqlite3_finalize(statement);
    }
}

-(void)select_phone:(NSString *)phone success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock{
    sqlite3_stmt *statement = nil;
    NSString *sql = [[@"select * from Contact where phone LIKE '%"stringByAppendingString:phone]stringByAppendingString:@"%'"];
    //    NSLog(@"sql == %@",sql);
    NSMutableArray * mutableArray = [[NSMutableArray alloc]init];
    if(db == nil && isOperation == true){
        return;
    }
    isOperation = true;
    @synchronized (self) {
        if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil) == SQLITE_OK) {
            while (sqlite3_step(statement) == SQLITE_ROW) {
                NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc]init];
                
                char *name = (char *)sqlite3_column_text(statement, 1);
                NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
                [mutableDictionary setObject:nameStr forKey:@"name"];
                
                char *phone = (char *)sqlite3_column_text(statement, 2);
                NSString *phoneStr = [[NSString alloc]initWithUTF8String:phone];
                [mutableDictionary setObject:phoneStr forKey:@"phone"];
                
                char *headimg = (char *)sqlite3_column_text(statement, 3);
                NSString *headimgStr = [[NSString alloc]initWithUTF8String:headimg];
                [mutableDictionary setObject:headimgStr forKey:@"headimg"];
                
                char *deptId = (char *)sqlite3_column_text(statement, 4);
                NSString *deptIdStr = [[NSString alloc]initWithUTF8String:deptId];
                [mutableDictionary setObject:deptIdStr forKey:@"deptId"];
                
                char *deptName = (char *)sqlite3_column_text(statement, 5);
                NSString *deptNameStr = [[NSString alloc]initWithUTF8String:deptName];
                [mutableDictionary setObject:deptNameStr forKey:@"deptName"];
                
                char *uppercase = (char *)sqlite3_column_text(statement, 6);
                NSString *uppercasetStr = [[NSString alloc]initWithUTF8String:uppercase];
                [mutableDictionary setObject:uppercasetStr forKey:@"uppercase"];
                
                char *userId = (char *)sqlite3_column_text(statement, 7);
                NSString *userIdStr = [[NSString alloc]initWithUTF8String:userId];
                [mutableDictionary setObject:userIdStr forKey:@"userId"];
                
                char *mail = (char *)sqlite3_column_text(statement, 8);
                NSString *mailStr = [[NSString alloc]initWithUTF8String:mail];
                [mutableDictionary setObject:mailStr forKey:@"mail"];
                
                [mutableArray addObject:mutableDictionary];
            }
            isOperation = false;
            successBlock(mutableArray);
        }else{
            failureBlock();
        }
        sqlite3_finalize(statement);
    }
}

-(void)select_uppercase:(NSString *)uppercase success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock{
    uppercase = [uppercase uppercaseString];
    uppercase = [uppercase stringByReplacingOccurrencesOfString:@" " withString:@""];
    sqlite3_stmt *statement = nil;
    NSString *sql = [[@"select * from Contact where uppercase LIKE '%"stringByAppendingString:uppercase]stringByAppendingString:@"%'"];
    //    NSLog(@"sql == %@",sql);
    NSMutableArray * mutableArray = [[NSMutableArray alloc]init];
    if(db == nil && isOperation == true){
        return;
    }
    isOperation = true;
    @synchronized (self) {
        if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil) == SQLITE_OK) {
            while (sqlite3_step(statement) == SQLITE_ROW) {
                NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc]init];
                
                char *name = (char *)sqlite3_column_text(statement, 1);
                NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
                [mutableDictionary setObject:nameStr forKey:@"name"];
                
                char *phone = (char *)sqlite3_column_text(statement, 2);
                NSString *phoneStr = [[NSString alloc]initWithUTF8String:phone];
                [mutableDictionary setObject:phoneStr forKey:@"phone"];
                
                char *headimg = (char *)sqlite3_column_text(statement, 3);
                NSString *headimgStr = [[NSString alloc]initWithUTF8String:headimg];
                [mutableDictionary setObject:headimgStr forKey:@"headimg"];
                
                char *deptId = (char *)sqlite3_column_text(statement, 4);
                NSString *deptIdStr = [[NSString alloc]initWithUTF8String:deptId];
                [mutableDictionary setObject:deptIdStr forKey:@"deptId"];
                
                char *deptName = (char *)sqlite3_column_text(statement, 5);
                NSString *deptNameStr = [[NSString alloc]initWithUTF8String:deptName];
                [mutableDictionary setObject:deptNameStr forKey:@"deptName"];
                
                char *userId = (char *)sqlite3_column_text(statement, 7);
                NSString *userIdStr = [[NSString alloc]initWithUTF8String:userId];
                [mutableDictionary setObject:userIdStr forKey:@"userId"];
                
                char *uppercase = (char *)sqlite3_column_text(statement, 6);
                NSString *uppercasetStr = [[NSString alloc]initWithUTF8String:uppercase];
                [mutableDictionary setObject:uppercasetStr forKey:@"uppercase"];
                
                [mutableArray addObject:mutableDictionary];
            }
            isOperation = false;
            successBlock(mutableArray);
        }else{
            failureBlock();
        }
        sqlite3_finalize(statement);
    }
}

-(void)select_userId:(NSString *)userId success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock{
    sqlite3_stmt *statement = nil;
    NSString *sql = [[@"select * from Contact where userId = '"stringByAppendingString:userId]stringByAppendingString:@"'"];
    if(db == nil && isOperation == true){
        return;
    }
    NSMutableArray * mutableArray = [[NSMutableArray alloc]init];
    @synchronized (self) {
        if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil) == SQLITE_OK) {
            while (sqlite3_step(statement) == SQLITE_ROW) {
                NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc]init];
                
                char *name = (char *)sqlite3_column_text(statement, 1);
                NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
                [mutableDictionary setObject:nameStr forKey:@"name"];
                
                char *phone = (char *)sqlite3_column_text(statement, 2);
                NSString *phoneStr = [[NSString alloc]initWithUTF8String:phone];
                [mutableDictionary setObject:phoneStr forKey:@"phone"];
                
                char *headimg = (char *)sqlite3_column_text(statement, 3);
                NSString *headimgStr = [[NSString alloc]initWithUTF8String:headimg];
                [mutableDictionary setObject:headimgStr forKey:@"headimg"];
                
                char *deptId = (char *)sqlite3_column_text(statement, 4);
                NSString *deptIdStr = [[NSString alloc]initWithUTF8String:deptId];
                [mutableDictionary setObject:deptIdStr forKey:@"deptId"];
                
                char *deptName = (char *)sqlite3_column_text(statement, 5);
                NSString *deptNameStr = [[NSString alloc]initWithUTF8String:deptName];
                [mutableDictionary setObject:deptNameStr forKey:@"deptName"];
                
                char *uppercase = (char *)sqlite3_column_text(statement, 6);
                NSString *uppercasetStr = [[NSString alloc]initWithUTF8String:uppercase];
                [mutableDictionary setObject:uppercasetStr forKey:@"uppercase"];
                
                char *userId = (char *)sqlite3_column_text(statement, 7);
                NSString *userIdStr = [[NSString alloc]initWithUTF8String:userId];
                [mutableDictionary setObject:userIdStr forKey:@"userId"];
                
                char *mail = (char *)sqlite3_column_text(statement, 8);
                NSString *mailStr = [[NSString alloc]initWithUTF8String:mail];
                [mutableDictionary setObject:mailStr forKey:@"mail"];
                
                [mutableArray addObject:mutableDictionary];
            }
            isOperation = false;
            successBlock(mutableArray);
        }else{
            failureBlock();
        }
        sqlite3_finalize(statement);
    }
}

-(void)select_deptName:(NSString *)deptName success:(SelectBlock)successBlock failure:(DBFailureBlock)failureBlock{
    sqlite3_stmt *statement = nil;
    NSString *sql = [[@"select * from Contact where deptName = '"stringByAppendingString:deptName]stringByAppendingString:@"'"];
//    NSLog(@"sql == %@",sql);
    if(db == nil && isOperation == true){
        return;
    }
    NSMutableArray * mutableArray = [[NSMutableArray alloc]init];
    @synchronized (self) {
        if (sqlite3_prepare_v2(db, [sql UTF8String], -1, &statement, nil) == SQLITE_OK) {
            while (sqlite3_step(statement) == SQLITE_ROW) {
                NSMutableDictionary *mutableDictionary = [[NSMutableDictionary alloc]init];
                
                char *name = (char *)sqlite3_column_text(statement, 1);
                NSString *nameStr = [[NSString alloc] initWithUTF8String:name];
                [mutableDictionary setObject:nameStr forKey:@"name"];
                
                char *phone = (char *)sqlite3_column_text(statement, 2);
                NSString *phoneStr = [[NSString alloc]initWithUTF8String:phone];
                [mutableDictionary setObject:phoneStr forKey:@"phone"];
                
                char *headimg = (char *)sqlite3_column_text(statement, 3);
                NSString *headimgStr = [[NSString alloc]initWithUTF8String:headimg];
                [mutableDictionary setObject:headimgStr forKey:@"headimg"];
                
                char *deptId = (char *)sqlite3_column_text(statement, 4);
                NSString *deptIdStr = [[NSString alloc]initWithUTF8String:deptId];
                [mutableDictionary setObject:deptIdStr forKey:@"deptId"];
                
                char *deptName = (char *)sqlite3_column_text(statement, 5);
                NSString *deptNameStr = [[NSString alloc]initWithUTF8String:deptName];
                [mutableDictionary setObject:deptNameStr forKey:@"deptName"];
                
                char *uppercase = (char *)sqlite3_column_text(statement, 6);
                NSString *uppercasetStr = [[NSString alloc]initWithUTF8String:uppercase];
                [mutableDictionary setObject:uppercasetStr forKey:@"uppercase"];
                
                char *userId = (char *)sqlite3_column_text(statement, 7);
                NSString *userIdStr = [[NSString alloc]initWithUTF8String:userId];
                [mutableDictionary setObject:userIdStr forKey:@"userId"];
                
                char *mail = (char *)sqlite3_column_text(statement, 8);
                NSString *mailStr = [[NSString alloc]initWithUTF8String:mail];
                [mutableDictionary setObject:mailStr forKey:@"mail"];
                
                [mutableArray addObject:mutableDictionary];
            }
            isOperation = false;
            successBlock(mutableArray);
        }else{
            failureBlock();
        }
            sqlite3_finalize(statement);
    }
}

-(void)dropTable:(Success)successBlock failed:(Failed)failedBlock{
    NSString * sql = [@"drop table if exists "stringByAppendingString:@"Contact"];
    NSLog(@"sql : %@",sql);
    @synchronized (self) {
        @try {
           sqlite3_exec(db, sql.UTF8String, NULL, NULL, NULL);
           successBlock();
        } @catch (NSException *exception) {
           failedBlock();
        } @finally {
            
        }
    }
//    sqlite3_exec(db, sql.UTF8String, NULL, NULL, NULL);
}

-(void)closeDB{
    if (sqlite3_close(db) == SQLITE_OK){
        db = nil;
    }
}

+ (void)destroyDealloc{
    if (nil == manager){
        return;
    }
    manager = nil;
}

@end
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章