Initial commit
This commit is contained in:
Generated
+19
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2012 Jianghuai Li (https://github.com/li6185377)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// LKDBProperty+KeyMapping.h
|
||||
// LKDBHelper
|
||||
//
|
||||
// Created by LJH on 13-6-17.
|
||||
// Copyright (c) 2013年 ljh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LKDBUtils.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface NSObject (TableMapping)
|
||||
|
||||
/**
|
||||
* @brief Overwrite in your models if your property names don't match your Table Column names.
|
||||
also use for set create table columns.
|
||||
|
||||
@{ sql column name : ( model property name ) or LKDBInherit or LKDBUserCalculate}
|
||||
|
||||
*/
|
||||
+ (nullable NSDictionary *)getTableMapping;
|
||||
|
||||
/***
|
||||
simple set a column as "LKSQL_Mapping_UserCalculate"
|
||||
column name
|
||||
*/
|
||||
+ (void)setUserCalculateForCN:(NSString *)columnName;
|
||||
|
||||
///property type name
|
||||
+ (void)setUserCalculateForPTN:(NSString *)propertyTypeName;
|
||||
|
||||
///binding columnName to PropertyName
|
||||
+ (void)setTableColumnName:(NSString *)columnName bindingPropertyName:(NSString *)propertyName;
|
||||
|
||||
///remove unwanted binding property
|
||||
+ (void)removePropertyWithColumnName:(NSString *)columnName;
|
||||
+ (void)removePropertyWithColumnNameArray:(NSArray *)columnNameArray;
|
||||
|
||||
@end
|
||||
|
||||
@interface LKDBProperty : NSObject
|
||||
|
||||
///保存的方式
|
||||
@property (nonatomic, copy, readonly) NSString *type;
|
||||
|
||||
///保存到数据的 列名
|
||||
@property (nonatomic, copy, readonly) NSString *sqlColumnName;
|
||||
///保存到数据的类型
|
||||
@property (nonatomic, copy, readonly) NSString *sqlColumnType;
|
||||
|
||||
///属性名
|
||||
@property (nonatomic, copy, readonly) NSString *propertyName;
|
||||
///属性的类型
|
||||
@property (nonatomic, copy, readonly) NSString *propertyType;
|
||||
|
||||
///属性的Protocol
|
||||
//@property(readonly,copy,nonatomic)NSString *propertyProtocol;
|
||||
|
||||
///creating table's column
|
||||
@property (nonatomic, assign) BOOL isUnique;
|
||||
@property (nonatomic, assign) BOOL isNotNull;
|
||||
@property (nullable, nonatomic, copy) NSString *defaultValue;
|
||||
@property (nullable, nonatomic, copy) NSString *checkValue;
|
||||
@property (nonatomic, assign) NSInteger length;
|
||||
|
||||
- (BOOL)isUserCalculate;
|
||||
@end
|
||||
|
||||
@interface LKModelInfos : NSObject
|
||||
|
||||
- (id)initWithKeyMapping:(nullable NSDictionary *)keyMapping
|
||||
propertyNames:(NSArray *)propertyNames
|
||||
propertyType:(NSArray *)propertyType
|
||||
primaryKeys:(nullable NSArray *)primaryKeys;
|
||||
|
||||
@property (nonatomic, readonly) NSUInteger count;
|
||||
@property (nullable, nonatomic, readonly) NSArray *primaryKeys;
|
||||
|
||||
- (nullable LKDBProperty *)objectWithIndex:(NSInteger)index;
|
||||
- (nullable LKDBProperty *)objectWithPropertyName:(NSString *)propertyName;
|
||||
- (nullable LKDBProperty *)objectWithSqlColumnName:(NSString *)columnName;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+277
@@ -0,0 +1,277 @@
|
||||
//
|
||||
// LKDBProperty+KeyMapping.m
|
||||
// LKDBHelper
|
||||
//
|
||||
// Created by LJH on 13-6-17.
|
||||
// Copyright (c) 2013年 ljh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LKDB+Mapping.h"
|
||||
#import "NSObject+LKModel.h"
|
||||
|
||||
@interface LKModelInfos () {
|
||||
__strong NSMutableDictionary *_proNameDic;
|
||||
__strong NSMutableDictionary *_sqlNameDic;
|
||||
__strong NSArray *_primaryKeys;
|
||||
}
|
||||
- (void)removeWithColumnName:(NSString *)columnName;
|
||||
- (void)addDBPropertyWithType:(NSString *)type cname:(NSString *)column_name ctype:(NSString *)ctype pname:(NSString *)pname ptype:(NSString *)ptype;
|
||||
|
||||
- (void)updateProperty:(LKDBProperty *)property sqlColumnName:(NSString *)columnName;
|
||||
- (void)updateProperty:(LKDBProperty *)property propertyName:(NSString *)propertyName;
|
||||
@end
|
||||
|
||||
#pragma mark - 声明属性
|
||||
@interface LKDBProperty ()
|
||||
@property (nonatomic, copy) NSString *type;
|
||||
|
||||
@property (nonatomic, copy) NSString *sqlColumnName;
|
||||
@property (nonatomic, copy) NSString *sqlColumnType;
|
||||
|
||||
@property (nonatomic, copy) NSString *propertyName;
|
||||
@property (nonatomic, copy) NSString *propertyType;
|
||||
|
||||
- (id)initWithType:(NSString *)type cname:(NSString *)cname ctype:(NSString *)ctype pname:(NSString *)pname ptype:(NSString *)ptype;
|
||||
@end
|
||||
#pragma mark - LKDBProperty
|
||||
@implementation LKDBProperty
|
||||
|
||||
- (id)initWithType:(NSString *)type cname:(NSString *)cname ctype:(NSString *)ctype pname:(NSString *)pname ptype:(NSString *)ptype
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_type = [type copy];
|
||||
_sqlColumnName = [cname copy];
|
||||
_sqlColumnType = [ctype copy];
|
||||
_propertyName = [pname copy];
|
||||
_propertyType = [ptype copy];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (void)enableUserCalculate
|
||||
{
|
||||
_type = LKSQL_Mapping_UserCalculate;
|
||||
}
|
||||
- (BOOL)isUserCalculate
|
||||
{
|
||||
return ([_type isEqualToString:LKSQL_Mapping_UserCalculate] || _propertyName == nil || [_propertyName isEqualToString:LKSQL_Mapping_UserCalculate]);
|
||||
}
|
||||
@end
|
||||
#pragma mark - NSObject - TableMapping
|
||||
@implementation NSObject (TableMapping)
|
||||
+ (NSDictionary *)getTableMapping
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
+ (void)setUserCalculateForCN:(NSString *)columnName
|
||||
{
|
||||
if ([LKDBUtils checkStringIsEmpty:columnName]) {
|
||||
LKErrorLog(@"columnName is null");
|
||||
return;
|
||||
}
|
||||
|
||||
LKModelInfos *infos = [self getModelInfos];
|
||||
LKDBProperty *property = [infos objectWithSqlColumnName:columnName];
|
||||
if (property) {
|
||||
[property enableUserCalculate];
|
||||
} else {
|
||||
[infos addDBPropertyWithType:LKSQL_Mapping_UserCalculate cname:columnName ctype:LKSQL_Type_Text pname:columnName ptype:@"NSString"];
|
||||
}
|
||||
}
|
||||
+ (void)setUserCalculateForPTN:(NSString *)propertyTypeName
|
||||
{
|
||||
if ([LKDBUtils checkStringIsEmpty:propertyTypeName]) {
|
||||
LKErrorLog(@"propertyTypeName is null");
|
||||
return;
|
||||
}
|
||||
|
||||
Class clazz = NSClassFromString(propertyTypeName);
|
||||
LKModelInfos *infos = [self getModelInfos];
|
||||
for (NSInteger i = 0; i < infos.count; i++) {
|
||||
LKDBProperty *property = [infos objectWithIndex:i];
|
||||
|
||||
Class p_cls = NSClassFromString(property.propertyType);
|
||||
BOOL isSubClass = ((p_cls && clazz) && [p_cls isSubclassOfClass:clazz]);
|
||||
BOOL isNameEqual = [property.propertyType isEqualToString:propertyTypeName];
|
||||
if (isSubClass || isNameEqual) {
|
||||
[property enableUserCalculate];
|
||||
}
|
||||
}
|
||||
}
|
||||
+ (void)setTableColumnName:(NSString *)columnName bindingPropertyName:(NSString *)propertyName
|
||||
{
|
||||
if ([LKDBUtils checkStringIsEmpty:columnName] || [LKDBUtils checkStringIsEmpty:propertyName])
|
||||
return;
|
||||
|
||||
LKModelInfos *infos = [self getModelInfos];
|
||||
|
||||
LKDBProperty *property = [infos objectWithPropertyName:propertyName];
|
||||
if (property == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
LKDBProperty *column = [infos objectWithSqlColumnName:columnName];
|
||||
if (column) {
|
||||
[infos updateProperty:column propertyName:propertyName];
|
||||
column.propertyType = property.propertyType;
|
||||
} else if ([property.sqlColumnName isEqualToString:property.propertyName]) {
|
||||
[infos updateProperty:property sqlColumnName:columnName];
|
||||
} else {
|
||||
[infos addDBPropertyWithType:LKSQL_Mapping_Binding cname:columnName ctype:LKSQL_Type_Text pname:propertyName ptype:property.propertyType];
|
||||
}
|
||||
}
|
||||
+ (void)removePropertyWithColumnNameArray:(NSArray *)columnNameArray
|
||||
{
|
||||
LKModelInfos *infos = [self getModelInfos];
|
||||
for (NSString *columnName in columnNameArray) {
|
||||
[infos removeWithColumnName:columnName];
|
||||
}
|
||||
}
|
||||
+ (void)removePropertyWithColumnName:(NSString *)columnName
|
||||
{
|
||||
[[self getModelInfos] removeWithColumnName:columnName];
|
||||
}
|
||||
@end
|
||||
|
||||
#pragma mark - LKModelInfos
|
||||
|
||||
@implementation LKModelInfos
|
||||
- (id)initWithKeyMapping:(NSDictionary *)keyMapping propertyNames:(NSArray *)propertyNames propertyType:(NSArray *)propertyType primaryKeys:(NSArray *)primaryKeys
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
|
||||
_primaryKeys = [NSArray arrayWithArray:primaryKeys];
|
||||
|
||||
_proNameDic = [[NSMutableDictionary alloc] init];
|
||||
_sqlNameDic = [[NSMutableDictionary alloc] init];
|
||||
|
||||
NSString *type, *column_name, *column_type, *property_name, *property_type;
|
||||
if (keyMapping.count > 0) {
|
||||
NSArray *sql_names = keyMapping.allKeys;
|
||||
|
||||
for (NSInteger i = 0; i < sql_names.count; i++) {
|
||||
|
||||
type = column_name = column_type = property_name = property_type = nil;
|
||||
|
||||
column_name = [sql_names objectAtIndex:i];
|
||||
NSString *mappingValue = [keyMapping objectForKey:column_name];
|
||||
|
||||
//如果 设置的 属性名 是空白的 自动转成 使用ColumnName
|
||||
if ([LKDBUtils checkStringIsEmpty:mappingValue]) {
|
||||
NSLog(@"#ERROR sql column name %@ mapping value is empty,automatically converted LKDBInherit", column_name);
|
||||
mappingValue = LKSQL_Mapping_Inherit;
|
||||
}
|
||||
|
||||
if ([mappingValue isEqualToString:LKSQL_Mapping_UserCalculate]) {
|
||||
type = LKSQL_Mapping_UserCalculate;
|
||||
column_type = LKSQL_Type_Text;
|
||||
} else {
|
||||
|
||||
if ([mappingValue isEqualToString:LKSQL_Mapping_Inherit] || [mappingValue isEqualToString:LKSQL_Mapping_Binding]) {
|
||||
type = LKSQL_Mapping_Inherit;
|
||||
property_name = column_name;
|
||||
} else {
|
||||
type = LKSQL_Mapping_Binding;
|
||||
property_name = mappingValue;
|
||||
}
|
||||
|
||||
NSUInteger index = [propertyNames indexOfObject:property_name];
|
||||
|
||||
NSAssert(index != NSNotFound, @"#ERROR TableMapping SQL column name %@ not fount %@ property name", column_name, property_name);
|
||||
|
||||
property_type = [propertyType objectAtIndex:index];
|
||||
column_type = LKSQLTypeFromObjcType(property_type);
|
||||
}
|
||||
|
||||
[self addDBPropertyWithType:type cname:column_name ctype:column_type pname:property_name ptype:property_type];
|
||||
}
|
||||
} else {
|
||||
for (NSInteger i = 0; i < propertyNames.count; i++) {
|
||||
|
||||
type = LKSQL_Mapping_Inherit;
|
||||
|
||||
property_name = [propertyNames objectAtIndex:i];
|
||||
column_name = property_name;
|
||||
|
||||
property_type = [propertyType objectAtIndex:i];
|
||||
column_type = LKSQLTypeFromObjcType(property_type);
|
||||
|
||||
[self addDBPropertyWithType:type cname:column_name ctype:column_type pname:property_name ptype:property_type];
|
||||
}
|
||||
}
|
||||
|
||||
if (_primaryKeys.count == 0) {
|
||||
_primaryKeys = [NSArray arrayWithObject:@"rowid"];
|
||||
}
|
||||
|
||||
for (NSString *pkname in _primaryKeys) {
|
||||
if ([pkname.lowercaseString isEqualToString:@"rowid"]) {
|
||||
if ([self objectWithSqlColumnName:pkname] == nil) {
|
||||
[self addDBPropertyWithType:LKSQL_Mapping_Inherit cname:pkname ctype:LKSQL_Type_Int pname:pkname ptype:@"int"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (void)addDBPropertyWithType:(NSString *)type cname:(NSString *)column_name ctype:(NSString *)ctype pname:(NSString *)pname ptype:(NSString *)ptype
|
||||
{
|
||||
LKDBProperty *db_property = [[LKDBProperty alloc] initWithType:type cname:column_name ctype:ctype pname:pname ptype:ptype];
|
||||
|
||||
if (db_property.propertyName) {
|
||||
_proNameDic[db_property.propertyName] = db_property;
|
||||
}
|
||||
if (db_property.sqlColumnName) {
|
||||
_sqlNameDic[db_property.sqlColumnName] = db_property;
|
||||
}
|
||||
}
|
||||
- (NSArray *)primaryKeys
|
||||
{
|
||||
return _primaryKeys;
|
||||
}
|
||||
- (NSUInteger)count
|
||||
{
|
||||
return _sqlNameDic.count;
|
||||
}
|
||||
- (LKDBProperty *)objectWithIndex:(NSInteger)index
|
||||
{
|
||||
if (index < _sqlNameDic.count) {
|
||||
id key = [_sqlNameDic.allKeys objectAtIndex:index];
|
||||
return [_sqlNameDic objectForKey:key];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
- (LKDBProperty *)objectWithPropertyName:(NSString *)propertyName
|
||||
{
|
||||
return [_proNameDic objectForKey:propertyName];
|
||||
}
|
||||
- (LKDBProperty *)objectWithSqlColumnName:(NSString *)columnName
|
||||
{
|
||||
return [_sqlNameDic objectForKey:columnName];
|
||||
}
|
||||
|
||||
- (void)updateProperty:(LKDBProperty *)property propertyName:(NSString *)propertyName
|
||||
{
|
||||
[_proNameDic removeObjectForKey:property.propertyName];
|
||||
property.propertyName = propertyName;
|
||||
_proNameDic[propertyName] = property;
|
||||
}
|
||||
- (void)updateProperty:(LKDBProperty *)property sqlColumnName:(NSString *)columnName
|
||||
{
|
||||
[_sqlNameDic removeObjectForKey:property.sqlColumnName];
|
||||
property.sqlColumnName = columnName;
|
||||
_sqlNameDic[columnName] = property;
|
||||
}
|
||||
- (void)removeWithColumnName:(NSString *)columnName
|
||||
{
|
||||
if ([LKDBUtils checkStringIsEmpty:columnName])
|
||||
return;
|
||||
|
||||
LKDBProperty *property = [_sqlNameDic objectForKey:columnName];
|
||||
if (property.propertyName) {
|
||||
[_proNameDic removeObjectForKey:property.propertyName];
|
||||
}
|
||||
[_sqlNameDic removeObjectForKey:columnName];
|
||||
}
|
||||
@end
|
||||
+292
@@ -0,0 +1,292 @@
|
||||
//
|
||||
// LKDBHelper.h
|
||||
// LJH
|
||||
//
|
||||
// Created by LJH on 12-12-6.
|
||||
// Copyright (c) 2012年 LJH. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LKDB+Mapping.h"
|
||||
#import "LKDBUtils.h"
|
||||
#import "NSObject+LKDBHelper.h"
|
||||
#import "NSObject+LKModel.h"
|
||||
#import <FMDB/FMDB.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LKDBHelper : NSObject
|
||||
|
||||
/**
|
||||
* @brief Log error message, Default: NO
|
||||
*/
|
||||
+ (void)setLogError:(BOOL)logError;
|
||||
|
||||
/**
|
||||
* @brief null is '' , Default: NO
|
||||
*/
|
||||
+ (void)setNullToEmpty:(BOOL)empty;
|
||||
|
||||
/**
|
||||
* @brief filepath the use of : "documents/db/" + fileName + ".db"
|
||||
* add to global cache with instance created
|
||||
* refer: FMDatabase.h + (instancetype)databaseWithPath:(NSString *)inPath;
|
||||
*/
|
||||
- (instancetype)initWithDBName:(NSString *)dbname;
|
||||
- (void)setDBName:(NSString *)fileName;
|
||||
|
||||
/**
|
||||
* @brief path of database file
|
||||
* refer: FMDatabase.h + (instancetype)databaseWithPath:(NSString *)inPath;
|
||||
*/
|
||||
- (instancetype)initWithDBPath:(NSString *)filePath;
|
||||
- (void)setDBPath:(NSString *)filePath;
|
||||
|
||||
/**
|
||||
* @brief closing a database connection and remove instance for global cache
|
||||
*/
|
||||
- (void)closeDB;
|
||||
|
||||
/**
|
||||
* @brief 当数据库无操作 多少秒后 自动关闭数据库连接, 区间 [10 ~ int_max] 默认:20秒
|
||||
*/
|
||||
- (void)setAutoCloseDBTime:(NSInteger)time;
|
||||
|
||||
/**
|
||||
* @brief current encryption key.
|
||||
*/
|
||||
@property (nullable, nonatomic, copy, readonly) NSString *encryptionKey;
|
||||
|
||||
/**
|
||||
* @brief Set encryption key
|
||||
refer: FMDatabase.h - (BOOL)setKey:(NSString *)key;
|
||||
* invoking after the `LKDBHelper initialize` in YourModelClass.m `getUsingLKDBHelper` function
|
||||
*/
|
||||
- (BOOL)setKey:(NSString *)key;
|
||||
|
||||
/// Reset encryption key
|
||||
- (BOOL)rekey:(NSString *)key;
|
||||
|
||||
/**
|
||||
* @brief execute database operations synchronously,not afraid of recursive deadlock
|
||||
|
||||
同步执行数据库操作 可递归调用
|
||||
*/
|
||||
- (void)executeDB:(void (^)(FMDatabase *db))block;
|
||||
|
||||
- (BOOL)executeSQL:(NSString *)sql arguments:(nullable NSArray *)args;
|
||||
- (nullable NSString *)executeScalarWithSQL:(NSString *)sql arguments:(nullable NSArray *)args;
|
||||
|
||||
/**
|
||||
* @brief execute database operations synchronously in a transaction
|
||||
block return the YES commit transaction returns the NO rollback transaction
|
||||
|
||||
同步执行数据库操作 在事务内部
|
||||
block 返回 YES commit 事务 返回 NO rollback 事务
|
||||
*/
|
||||
- (void)executeForTransaction:(BOOL (^)(LKDBHelper *helper))block;
|
||||
|
||||
@end
|
||||
|
||||
@interface LKDBHelper (DatabaseManager)
|
||||
|
||||
///get table has created
|
||||
- (BOOL)getTableCreatedWithClass:(Class)model;
|
||||
- (BOOL)getTableCreatedWithTableName:(NSString *)tableName;
|
||||
|
||||
///drop all table
|
||||
- (void)dropAllTable;
|
||||
|
||||
///drop table with entity class
|
||||
- (BOOL)dropTableWithClass:(Class)modelClass;
|
||||
- (BOOL)dropTableWithTableName:(NSString *)tableName;
|
||||
|
||||
@end
|
||||
|
||||
@interface LKDBHelper (DatabaseExecute)
|
||||
/**
|
||||
* @brief The number of rows query table
|
||||
*
|
||||
* @param modelClass entity class
|
||||
* @param where can use NSString or NSDictionary or nil
|
||||
*
|
||||
* @return rows number
|
||||
*/
|
||||
- (NSInteger)rowCount:(Class)modelClass where:(nullable id)where;
|
||||
- (void)rowCount:(Class)modelClass where:(nullable id)where callback:(void (^)(NSInteger rowCount))callback;
|
||||
- (NSInteger)rowCountWithTableName:(NSString *)tableName where:(nullable id)where;
|
||||
|
||||
/**
|
||||
* @brief query table
|
||||
*
|
||||
* @param params query condition
|
||||
*/
|
||||
- (nullable NSMutableArray *)searchWithParams:(LKDBQueryParams *)params;
|
||||
|
||||
/**
|
||||
* @brief query table
|
||||
*
|
||||
* @param modelClass entity class
|
||||
* @param where can use NSString or NSDictionary or nil
|
||||
|
||||
* @param orderBy The Sort: Ascending "name asc",Descending "name desc"
|
||||
For example: @"rowid desc"x or @"rowid asc"
|
||||
|
||||
* @param offset Skip how many rows
|
||||
* @param count Limit the number
|
||||
*
|
||||
* @return query finished result is an array(model instance collection)
|
||||
*/
|
||||
- (nullable NSMutableArray *)search:(Class)modelClass
|
||||
where:(nullable id)where
|
||||
orderBy:(nullable NSString *)orderBy
|
||||
offset:(NSInteger)offset
|
||||
count:(NSInteger)count;
|
||||
|
||||
/**
|
||||
* query sql, query finished result is an array(model instance collection)
|
||||
* you can use the "@t" replace Model TableName
|
||||
* query sql use lowercase string
|
||||
* 查询的sql语句 请使用小写 ,否则会不能自动获取 rowid
|
||||
* example:
|
||||
NSMutableArray *array = [[LKDBHelper getUsingLKDBHelper] searchWithSQL:@"select * from @t where blah blah.." toClass:[ModelClass class]];
|
||||
*
|
||||
*/
|
||||
- (nullable NSMutableArray *)searchWithSQL:(NSString *)sql toClass:(nullable Class)modelClass;
|
||||
|
||||
/**
|
||||
* @brief don't do any operations of the sql
|
||||
*/
|
||||
- (nullable NSMutableArray *)searchWithRAWSQL:(NSString *)sql toClass:(nullable Class)modelClass;
|
||||
|
||||
/**
|
||||
* query sql, query finished result is an array(model instance collection)
|
||||
* you can use the "@t" replace Model TableName and replace all ? placeholders with the va_list
|
||||
* example:
|
||||
NSMutableArray *array = [[LKDBHelper getUsingLKDBHelper] searc:[ModelClass class] withSQL:@"select rowid from name_table where name = ?", @"Swift"];
|
||||
*
|
||||
*/
|
||||
- (nullable NSMutableArray *)search:(Class)modelClass withSQL:(NSString *)sql, ...;
|
||||
|
||||
/**
|
||||
columns may NSArray or NSString if query column count == 1 return single column string array
|
||||
other return models entity array
|
||||
*/
|
||||
- (nullable NSMutableArray *)search:(Class)modelClass
|
||||
column:(nullable id)columns
|
||||
where:(nullable id)where
|
||||
orderBy:(nullable NSString *)orderBy
|
||||
offset:(NSInteger)offset
|
||||
count:(NSInteger)count;
|
||||
|
||||
/**
|
||||
* @brief async search
|
||||
*/
|
||||
- (void)search:(Class)modelClass
|
||||
where:(nullable id)where
|
||||
orderBy:(nullable NSString *)orderBy
|
||||
offset:(NSInteger)offset
|
||||
count:(NSInteger)count
|
||||
callback:(void (^)(NSMutableArray *_Nullable array))block;
|
||||
|
||||
///return first model or nil
|
||||
- (nullable id)searchSingle:(Class)modelClass where:(nullable id)where orderBy:(nullable NSString *)orderBy;
|
||||
|
||||
/**
|
||||
* @brief insert table
|
||||
*
|
||||
* @param model you want to insert the entity
|
||||
*
|
||||
* @return the inserted was successful
|
||||
*/
|
||||
- (BOOL)insertToDB:(NSObject *)model;
|
||||
- (void)insertToDB:(NSObject *)model callback:(void (^)(BOOL result))block;
|
||||
|
||||
/**
|
||||
* @brief insert when the entity primary key does not exist
|
||||
*
|
||||
* @param model you want to insert the entity
|
||||
*
|
||||
* @return the inserted was successful
|
||||
*/
|
||||
- (BOOL)insertWhenNotExists:(NSObject *)model;
|
||||
- (void)insertWhenNotExists:(NSObject *)model callback:(void (^)(BOOL result))block;
|
||||
|
||||
/**
|
||||
* @brief update table
|
||||
*
|
||||
* @param model you want to update the entity
|
||||
* @param where can use NSString or NSDictionary or nil
|
||||
when "where" is nil : update the value based on rowid column or primary key column
|
||||
*
|
||||
* @return the updated was successful
|
||||
*/
|
||||
- (BOOL)updateToDB:(NSObject *)model where:(nullable id)where;
|
||||
- (void)updateToDB:(NSObject *)model where:(nullable id)where callback:(void (^)(BOOL result))block;
|
||||
- (BOOL)updateToDB:(Class)modelClass set:(NSString *)sets where:(nullable id)where;
|
||||
- (BOOL)updateToDBWithTableName:(NSString *)tableName set:(NSString *)sets where:(nullable id)where;
|
||||
|
||||
/**
|
||||
* @brief delete table
|
||||
*
|
||||
* @param model you want to delete entity
|
||||
when entity property "rowid" == 0 based on the primary key to delete
|
||||
*
|
||||
* @return the deleted was successful
|
||||
*/
|
||||
- (BOOL)deleteToDB:(NSObject *)model;
|
||||
- (void)deleteToDB:(NSObject *)model callback:(void (^)(BOOL result))block;
|
||||
|
||||
/**
|
||||
* @brief delete table with "where" constraint
|
||||
*
|
||||
* @param modelClass entity class
|
||||
* @param where can use NSString or NSDictionary, can not is nil
|
||||
*
|
||||
* @return the deleted was successful
|
||||
*/
|
||||
- (BOOL)deleteWithClass:(Class)modelClass where:(nullable id)where;
|
||||
- (void)deleteWithClass:(Class)modelClass where:(nullable id)where callback:(void (^)(BOOL result))block;
|
||||
- (BOOL)deleteWithTableName:(NSString *)tableName where:(nullable id)where;
|
||||
|
||||
/**
|
||||
* @brief entity exists?
|
||||
* for primary key column
|
||||
(if rowid > 0 would certainly exist so we do not rowid judgment)
|
||||
* @param model entity
|
||||
*
|
||||
* @return YES: entity presence , NO: entity not exist
|
||||
*/
|
||||
- (BOOL)isExistsModel:(NSObject *)model;
|
||||
- (BOOL)isExistsClass:(Class)modelClass where:(nullable id)where;
|
||||
- (BOOL)isExistsWithTableName:(NSString *)tableName where:(nullable id)where;
|
||||
|
||||
/**
|
||||
* @brief Clear data based on the entity class
|
||||
*
|
||||
* @param modelClass entity class
|
||||
*/
|
||||
+ (void)clearTableData:(Class)modelClass;
|
||||
|
||||
/**
|
||||
* @brief Clear Unused Data File
|
||||
if you property has UIImage or NSData, will save their data in the (documents dir)
|
||||
*
|
||||
* @param modelClass entity class
|
||||
* @param columns UIImage or NSData Column Name
|
||||
*/
|
||||
+ (void)clearNoneImage:(Class)modelClass columns:(NSArray<NSString *> *)columns;
|
||||
+ (void)clearNoneData:(Class)modelClass columns:(NSArray<NSString *> *)columns;
|
||||
|
||||
@end
|
||||
|
||||
@interface LKDBHelper (Deprecated_Nonfunctional)
|
||||
/// you can use [LKDBHelper getUsingLKDBHelper]
|
||||
#pragma mark - deprecated
|
||||
+ (LKDBHelper *)sharedDBHelper __deprecated_msg("Method deprecated. Use `[Model getUsingLKDBHelper]`");
|
||||
- (BOOL)createTableWithModelClass:(Class)modelClass __deprecated_msg("Now you can not call it. Will automatically determine whether you need to create");
|
||||
- (void)setEncryptionKey:(NSString *)encryptionKey __deprecated_msg("Method deprecated. Use `setKey: OR resetKey:` invoking after the `LKDBHelper initialize` in YourModelClass.m `getUsingLKDBHelper` function");
|
||||
#pragma mark -
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+1721
File diff suppressed because it is too large
Load Diff
+117
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// NSObject+LKUtils.h
|
||||
// LKDBHelper
|
||||
//
|
||||
// Created by LJH on 13-4-15.
|
||||
// Copyright (c) 2013年 ljh. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LKDBUtils : NSObject
|
||||
|
||||
// 创建文件路径所需要的文件夹
|
||||
+ (BOOL)createDirectoryWithFilePath:(NSString *)filePath;
|
||||
|
||||
///返回根目录路径 "document"
|
||||
+ (NSString *)getDocumentPath;
|
||||
///返回 "document/dir/" 文件夹路径
|
||||
+ (NSString *)getDirectoryForDocuments:(NSString *)dir;
|
||||
///返回 "document/filename" 路径
|
||||
+ (NSString *)getPathForDocuments:(NSString *)filename;
|
||||
///返回 "document/dir/filename" 路径
|
||||
+ (NSString *)getPathForDocuments:(NSString *)filename inDir:(NSString *)dir;
|
||||
///文件是否存在
|
||||
+ (BOOL)isFileExists:(NSString *)filepath;
|
||||
///删除文件
|
||||
+ (BOOL)deleteWithFilepath:(NSString *)filepath;
|
||||
///返回该文件目录下 所有文件名
|
||||
+ (nullable NSArray *)getFilenamesWithDir:(NSString *)dir;
|
||||
|
||||
///检测字符串是否为空
|
||||
+ (BOOL)checkStringIsEmpty:(NSString *)string;
|
||||
+ (nullable NSString *)getTrimStringWithString:(nullable NSString *)string;
|
||||
|
||||
///把Date 转换成String
|
||||
+ (NSString *)stringWithDate:(NSDate *)date;
|
||||
///把String 转换成Date
|
||||
+ (NSDate *)dateWithString:(NSString *)str;
|
||||
///单例formatter
|
||||
+ (NSNumberFormatter *)numberFormatter;
|
||||
|
||||
@end
|
||||
|
||||
#ifdef DEBUG
|
||||
#ifdef NSLog
|
||||
#define LKErrorLog(fmt, ...) NSLog(@"#LKDBHelper ERROR:\n" fmt, ##__VA_ARGS__);
|
||||
#else
|
||||
#define LKErrorLog(fmt, ...) NSLog(@"\n#LKDBHelper ERROR: %s [Line %d] \n" fmt, __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
|
||||
#endif
|
||||
#else
|
||||
#define LKErrorLog(...)
|
||||
#endif
|
||||
|
||||
static NSString *const LKSQL_Type_Text = @"text";
|
||||
static NSString *const LKSQL_Type_Int = @"integer";
|
||||
static NSString *const LKSQL_Type_Double = @"double";
|
||||
static NSString *const LKSQL_Type_Blob = @"blob";
|
||||
|
||||
static NSString *const LKSQL_Attribute_NotNull = @"NOT NULL";
|
||||
static NSString *const LKSQL_Attribute_PrimaryKey = @"PRIMARY KEY";
|
||||
static NSString *const LKSQL_Attribute_Default = @"DEFAULT";
|
||||
static NSString *const LKSQL_Attribute_Unique = @"UNIQUE";
|
||||
static NSString *const LKSQL_Attribute_Check = @"CHECK";
|
||||
static NSString *const LKSQL_Attribute_ForeignKey = @"FOREIGN KEY";
|
||||
|
||||
static NSString *const LKSQL_Convert_FloatType = @"float_double_decimal";
|
||||
static NSString *const LKSQL_Convert_IntType = @"int_char_short_long";
|
||||
static NSString *const LKSQL_Convert_BlobType = @"";
|
||||
|
||||
static NSString *const LKSQL_Mapping_Inherit = @"LKDBInherit";
|
||||
static NSString *const LKSQL_Mapping_Binding = @"LKDBBinding";
|
||||
static NSString *const LKSQL_Mapping_UserCalculate = @"LKDBUserCalculate";
|
||||
|
||||
static NSString *const LKDB_TypeKey = @"DB_Type";
|
||||
|
||||
static NSString *const LKDB_TypeKey_Model = @"DB_Type_Model";
|
||||
static NSString *const LKDB_TypeKey_JSON = @"DB_Type_JSON";
|
||||
static NSString *const LKDB_TypeKey_Combo = @"DB_Type_Combo";
|
||||
static NSString *const LKDB_TypeKey_Date = @"DB_Type_Date";
|
||||
|
||||
static NSString *const LKDB_ValueKey = @"DB_Value";
|
||||
|
||||
static NSString *const LKDB_TableNameKey = @"DB_TableName";
|
||||
static NSString *const LKDB_ClassKey = @"DB_Class";
|
||||
static NSString *const LKDB_RowIdKey = @"DB_RowId";
|
||||
static NSString *const LKDB_PValueKey = @"DB_PKeyValue";
|
||||
|
||||
///Object-c type converted to SQLite type 把Object-c 类型 转换为sqlite 类型
|
||||
extern NSString *LKSQLTypeFromObjcType(NSString *objcType);
|
||||
|
||||
@interface LKDBQueryParams : NSObject
|
||||
|
||||
///columns or array
|
||||
@property (nullable, nonatomic, copy) NSString *columns;
|
||||
@property (nullable, nonatomic, copy) NSArray *columnArray;
|
||||
|
||||
@property (nullable, nonatomic, copy) NSString *tableName;
|
||||
|
||||
///where or dic
|
||||
@property (nullable, nonatomic, copy) NSString *where;
|
||||
@property (nullable, nonatomic, copy) NSDictionary *whereDic;
|
||||
|
||||
@property (nullable, nonatomic, copy) NSString *groupBy;
|
||||
@property (nullable, nonatomic, copy) NSString *orderBy;
|
||||
|
||||
@property (nonatomic, assign) NSInteger offset;
|
||||
@property (nonatomic, assign) NSInteger count;
|
||||
|
||||
@property (nullable, nonatomic, assign) Class toClass;
|
||||
|
||||
@property (nullable, nonatomic, copy) void (^callback)(NSMutableArray *_Nullable results);
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+241
@@ -0,0 +1,241 @@
|
||||
//
|
||||
// NSObject+LKUtils.m
|
||||
// LKDBHelper
|
||||
//
|
||||
// Created by LJH on 13-4-15.
|
||||
// Copyright (c) 2013年 ljh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LKDBUtils.h"
|
||||
|
||||
@interface LKDateFormatter : NSDateFormatter
|
||||
@property (nonatomic, strong) NSRecursiveLock *lock;
|
||||
@end
|
||||
|
||||
@implementation LKDateFormatter
|
||||
- (id)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.lock = [[NSRecursiveLock alloc] init];
|
||||
self.generatesCalendarDates = YES;
|
||||
self.dateStyle = NSDateFormatterNoStyle;
|
||||
self.timeStyle = NSDateFormatterNoStyle;
|
||||
self.AMSymbol = nil;
|
||||
self.PMSymbol = nil;
|
||||
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
|
||||
if (locale) {
|
||||
[self setLocale:locale];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
//防止在IOS5下 多线程 格式化时间时 崩溃
|
||||
- (NSDate *)dateFromString:(NSString *)string
|
||||
{
|
||||
[_lock lock];
|
||||
NSDate *date = [super dateFromString:string];
|
||||
[_lock unlock];
|
||||
return date;
|
||||
}
|
||||
- (NSString *)stringFromDate:(NSDate *)date
|
||||
{
|
||||
[_lock lock];
|
||||
NSString *string = [super stringFromDate:date];
|
||||
[_lock unlock];
|
||||
return string;
|
||||
}
|
||||
@end
|
||||
|
||||
@interface LKNumberFormatter : NSNumberFormatter
|
||||
|
||||
@end
|
||||
|
||||
@implementation LKNumberFormatter
|
||||
- (NSString *)stringFromNumber:(NSNumber *)number
|
||||
{
|
||||
NSString *string = [number stringValue];
|
||||
if (!string) {
|
||||
string = [NSString stringWithFormat:@"%lf", [number doubleValue]];
|
||||
}
|
||||
return string;
|
||||
}
|
||||
- (NSNumber *)numberFromString:(NSString *)string
|
||||
{
|
||||
NSNumber *number = [super numberFromString:string];
|
||||
if (!number) {
|
||||
number = @(string.doubleValue);
|
||||
}
|
||||
return number;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation LKDBUtils
|
||||
|
||||
+ (BOOL)createDirectoryWithFilePath:(NSString *)filePath
|
||||
{
|
||||
NSString *dirPath = filePath.stringByDeletingLastPathComponent;
|
||||
if (!dirPath) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
|
||||
BOOL isDir = NO;
|
||||
BOOL isCreated = [fileManager fileExistsAtPath:dirPath isDirectory:&isDir];
|
||||
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
NSDictionary *attributes = @{NSFileProtectionKey: NSFileProtectionNone};
|
||||
#else
|
||||
NSDictionary *attributes = nil;
|
||||
#endif
|
||||
|
||||
if (!isCreated || !isDir) {
|
||||
NSError *error = nil;
|
||||
BOOL success = [fileManager createDirectoryAtPath:dirPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:attributes
|
||||
error:&error];
|
||||
if (!success) {
|
||||
LKErrorLog(@"create dir error: %@", error.debugDescription);
|
||||
/// 下个主线程继续尝试次
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[fileManager createDirectoryAtPath:dirPath
|
||||
withIntermediateDirectories:YES
|
||||
attributes:attributes
|
||||
error:nil];
|
||||
});
|
||||
}
|
||||
return success;
|
||||
} else {
|
||||
/**
|
||||
* @brief Disk I/O error when device is locked
|
||||
* https://github.com/ccgus/fmdb/issues/262
|
||||
*/
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
[fileManager setAttributes:attributes
|
||||
ofItemAtPath:dirPath
|
||||
error:nil];
|
||||
#endif
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSString *)getDocumentPath
|
||||
{
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
return documentsDirectory;
|
||||
#else
|
||||
NSString *homePath = [[NSBundle mainBundle] resourcePath];
|
||||
return homePath;
|
||||
#endif
|
||||
}
|
||||
+ (NSString *)getDirectoryForDocuments:(NSString *)dir
|
||||
{
|
||||
NSString *dirPath = [[self getDocumentPath] stringByAppendingPathComponent:dir];
|
||||
BOOL isDir = NO;
|
||||
BOOL isCreated = [[NSFileManager defaultManager] fileExistsAtPath:dirPath isDirectory:&isDir];
|
||||
if (isCreated == NO || isDir == NO) {
|
||||
NSError *error = nil;
|
||||
BOOL success = [[NSFileManager defaultManager] createDirectoryAtPath:dirPath withIntermediateDirectories:YES attributes:nil error:&error];
|
||||
if (success == NO)
|
||||
NSLog(@"create dir error: %@", error.debugDescription);
|
||||
}
|
||||
return dirPath;
|
||||
}
|
||||
+ (NSString *)getPathForDocuments:(NSString *)filename
|
||||
{
|
||||
return [[self getDocumentPath] stringByAppendingPathComponent:filename];
|
||||
}
|
||||
+ (NSString *)getPathForDocuments:(NSString *)filename inDir:(NSString *)dir
|
||||
{
|
||||
return [[self getDirectoryForDocuments:dir] stringByAppendingPathComponent:filename];
|
||||
}
|
||||
+ (BOOL)isFileExists:(NSString *)filepath
|
||||
{
|
||||
return [[NSFileManager defaultManager] fileExistsAtPath:filepath];
|
||||
}
|
||||
+ (BOOL)deleteWithFilepath:(NSString *)filepath
|
||||
{
|
||||
return [[NSFileManager defaultManager] removeItemAtPath:filepath error:nil];
|
||||
}
|
||||
+ (NSArray *)getFilenamesWithDir:(NSString *)dir
|
||||
{
|
||||
NSFileManager *fileManager = [NSFileManager defaultManager];
|
||||
NSArray *fileList = [fileManager contentsOfDirectoryAtPath:dir error:nil];
|
||||
return fileList;
|
||||
}
|
||||
+ (BOOL)checkStringIsEmpty:(NSString *)string
|
||||
{
|
||||
if (string == nil) {
|
||||
return YES;
|
||||
}
|
||||
if ([string isKindOfClass:[NSString class]] == NO) {
|
||||
return YES;
|
||||
}
|
||||
if (string.length == 0) {
|
||||
return YES;
|
||||
}
|
||||
return [[self getTrimStringWithString:string] isEqualToString:@""];
|
||||
}
|
||||
+ (NSString *)getTrimStringWithString:(NSString *)string
|
||||
{
|
||||
return [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
}
|
||||
|
||||
+ (NSDateFormatter *)getDBDateFormat
|
||||
{
|
||||
static NSDateFormatter *format;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
format = [[LKDateFormatter alloc] init];
|
||||
format.dateFormat = @"yyyy-MM-dd HH:mm:ss";
|
||||
});
|
||||
return format;
|
||||
}
|
||||
+ (NSString *)stringWithDate:(NSDate *)date
|
||||
{
|
||||
NSDateFormatter *formatter = [self getDBDateFormat];
|
||||
NSString *datestr = [formatter stringFromDate:date];
|
||||
if (datestr.length > 19) {
|
||||
datestr = [datestr substringToIndex:19];
|
||||
}
|
||||
return datestr;
|
||||
}
|
||||
+ (NSDate *)dateWithString:(NSString *)str
|
||||
{
|
||||
NSDateFormatter *formatter = [self getDBDateFormat];
|
||||
NSDate *date = [formatter dateFromString:str];
|
||||
return date;
|
||||
}
|
||||
+ (NSNumberFormatter *)numberFormatter
|
||||
{
|
||||
static NSNumberFormatter *numberFormatter = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
numberFormatter = [[LKNumberFormatter alloc] init];
|
||||
});
|
||||
return numberFormatter;
|
||||
}
|
||||
@end
|
||||
|
||||
inline NSString *LKSQLTypeFromObjcType(NSString *objcType)
|
||||
{
|
||||
if ([LKSQL_Convert_IntType rangeOfString:objcType].length > 0) {
|
||||
return LKSQL_Type_Int;
|
||||
}
|
||||
if ([LKSQL_Convert_FloatType rangeOfString:objcType].length > 0) {
|
||||
return LKSQL_Type_Double;
|
||||
}
|
||||
if ([LKSQL_Convert_BlobType rangeOfString:objcType].length > 0) {
|
||||
return LKSQL_Type_Blob;
|
||||
}
|
||||
|
||||
return LKSQL_Type_Text;
|
||||
}
|
||||
|
||||
@implementation LKDBQueryParams
|
||||
|
||||
@end
|
||||
+110
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// NSObject+LKDBHelper.h
|
||||
// LKDBHelper
|
||||
//
|
||||
// Created by LJH on 13-6-8.
|
||||
// Copyright (c) 2013年 ljh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LKDBHelper.h"
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class LKDBHelper;
|
||||
|
||||
@interface NSObject (LKDBHelper_Delegate)
|
||||
|
||||
+ (void)dbDidCreateTable:(LKDBHelper *)helper tableName:(NSString *)tableName;
|
||||
+ (void)dbDidAlterTable:(LKDBHelper *)helper tableName:(NSString *)tableName addColumns:(NSArray *)columns;
|
||||
|
||||
+ (BOOL)dbWillInsert:(NSObject *)entity;
|
||||
+ (void)dbDidInserted:(NSObject *)entity result:(BOOL)result;
|
||||
|
||||
+ (BOOL)dbWillUpdate:(NSObject *)entity;
|
||||
+ (void)dbDidUpdated:(NSObject *)entity result:(BOOL)result;
|
||||
|
||||
+ (BOOL)dbWillDelete:(NSObject *)entity;
|
||||
+ (void)dbDidDeleted:(NSObject *)entity result:(BOOL)result;
|
||||
|
||||
///data read finish
|
||||
+ (void)dbDidSeleted:(NSObject *)entity;
|
||||
|
||||
@end
|
||||
|
||||
//only simplify synchronous function
|
||||
@interface NSObject (LKDBHelper_Execute)
|
||||
|
||||
/**
|
||||
* 返回行数
|
||||
*
|
||||
* @param where type can NSDictionary or NSString
|
||||
*
|
||||
* @return row count
|
||||
*/
|
||||
+ (NSInteger)rowCountWithWhere:(nullable id)where, ...;
|
||||
+ (NSInteger)rowCountWithWhereFormat:(nullable id)where, ...;
|
||||
|
||||
/**
|
||||
* 搜索
|
||||
*
|
||||
* @param columns type can NSArray or NSString(Search for a specific column. Search only one, only to return the contents of the column collection)
|
||||
|
||||
* @param where where type can NSDictionary or NSString
|
||||
* @param orderBy
|
||||
* @param offset
|
||||
* @param count
|
||||
*
|
||||
* @return model collection or contents of the columns collection
|
||||
*/
|
||||
+ (nullable NSMutableArray *)searchColumn:(nullable id)columns
|
||||
where:(nullable id)where
|
||||
orderBy:(nullable NSString *)orderBy
|
||||
offset:(NSInteger)offset
|
||||
count:(NSInteger)count;
|
||||
|
||||
+ (nullable NSMutableArray *)searchWithWhere:(nullable id)where
|
||||
orderBy:(nullable NSString *)orderBy
|
||||
offset:(NSInteger)offset
|
||||
count:(NSInteger)count;
|
||||
|
||||
+ (nullable NSMutableArray *)searchWithWhere:(nullable id)where;
|
||||
|
||||
+ (nullable NSMutableArray *)searchWithSQL:(NSString *)sql;
|
||||
|
||||
+ (nullable id)searchSingleWithWhere:(nullable id)where
|
||||
orderBy:(nullable NSString *)orderBy;
|
||||
|
||||
+ (BOOL)insertToDB:(NSObject *)model;
|
||||
+ (BOOL)insertWhenNotExists:(NSObject *)model;
|
||||
|
||||
+ (BOOL)updateToDB:(NSObject *)model
|
||||
where:(nullable id)where, ...;
|
||||
+ (BOOL)updateToDBWithSet:(NSString *)sets
|
||||
where:(nullable id)where, ...;
|
||||
|
||||
+ (BOOL)deleteToDB:(NSObject *)model;
|
||||
+ (BOOL)deleteWithWhere:(nullable id)where, ...;
|
||||
|
||||
+ (BOOL)isExistsWithModel:(NSObject *)model;
|
||||
|
||||
- (BOOL)updateToDB;
|
||||
- (BOOL)saveToDB;
|
||||
- (BOOL)deleteToDB;
|
||||
- (BOOL)isExistsFromDB;
|
||||
|
||||
///异步插入数据 async insert array , completed 也是在子线程直接回调的
|
||||
+ (void)insertArrayByAsyncToDB:(NSArray *)models;
|
||||
+ (void)insertArrayByAsyncToDB:(NSArray *)models completed:(void (^_Nullable)(BOOL allInserted))completedBlock;
|
||||
|
||||
///begin translate for insert models 开始事务插入数组
|
||||
+ (void)insertToDBWithArray:(NSArray *)models
|
||||
filter:(void (^_Nullable)(id model, BOOL inserted, BOOL *_Nullable rollback))filter;
|
||||
|
||||
+ (void)insertToDBWithArray:(NSArray *)models
|
||||
filter:(void (^_Nullable)(id model, BOOL inserted, BOOL *_Nullable rollback))filter
|
||||
completed:(void (^_Nullable)(BOOL allInserted))completedBlock;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+234
@@ -0,0 +1,234 @@
|
||||
//
|
||||
// NSObject+LKDBHelper.m
|
||||
// LKDBHelper
|
||||
//
|
||||
// Created by LJH on 13-6-8.
|
||||
// Copyright (c) 2013年 ljh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSObject+LKDBHelper.h"
|
||||
|
||||
@implementation NSObject (LKDBHelper_Delegate)
|
||||
|
||||
+ (void)dbDidCreateTable:(LKDBHelper *)helper tableName:(NSString *)tableName {}
|
||||
+ (void)dbDidAlterTable:(LKDBHelper *)helper tableName:(NSString *)tableName addColumns:(NSArray *)columns {}
|
||||
|
||||
+ (void)dbDidInserted:(NSObject *)entity result:(BOOL)result {}
|
||||
+ (void)dbDidDeleted:(NSObject *)entity result:(BOOL)result {}
|
||||
+ (void)dbDidUpdated:(NSObject *)entity result:(BOOL)result {}
|
||||
+ (void)dbDidSeleted:(NSObject *)entity {}
|
||||
|
||||
+ (BOOL)dbWillDelete:(NSObject *)entity
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)dbWillInsert:(NSObject *)entity
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
+ (BOOL)dbWillUpdate:(NSObject *)entity
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSObject (LKDBHelper)
|
||||
|
||||
#pragma mark - simplify synchronous function
|
||||
+ (BOOL)checkModelClass:(NSObject *)model
|
||||
{
|
||||
if ([model isMemberOfClass:self])
|
||||
return YES;
|
||||
|
||||
NSLog(@"%@ can not use %@", NSStringFromClass(self), NSStringFromClass(model.class));
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (NSInteger)rowCountWithWhereFormat:(id)where, ...
|
||||
{
|
||||
if ([where isKindOfClass:[NSString class]]) {
|
||||
va_list list;
|
||||
va_start(list, where);
|
||||
where = [[NSString alloc] initWithFormat:where arguments:list];
|
||||
va_end(list);
|
||||
}
|
||||
return [[self getUsingLKDBHelper] rowCount:self where:where];
|
||||
}
|
||||
|
||||
+ (NSInteger)rowCountWithWhere:(id)where, ...
|
||||
{
|
||||
if ([where isKindOfClass:[NSString class]]) {
|
||||
va_list list;
|
||||
va_start(list, where);
|
||||
where = [[NSString alloc] initWithFormat:where arguments:list];
|
||||
va_end(list);
|
||||
}
|
||||
return [[self getUsingLKDBHelper] rowCount:self where:where];
|
||||
}
|
||||
|
||||
+ (NSMutableArray *)searchColumn:(id)columns where:(id)where orderBy:(NSString *)orderBy offset:(NSInteger)offset count:(NSInteger)count
|
||||
{
|
||||
return [[self getUsingLKDBHelper] search:self column:columns where:where orderBy:orderBy offset:offset count:count];
|
||||
}
|
||||
|
||||
+ (NSMutableArray *)searchWithWhere:(id)where orderBy:(NSString *)orderBy offset:(NSInteger)offset count:(NSInteger)count
|
||||
{
|
||||
return [[self getUsingLKDBHelper] search:self where:where orderBy:orderBy offset:offset count:count];
|
||||
}
|
||||
|
||||
+ (NSMutableArray *)searchWithWhere:(id)where
|
||||
{
|
||||
return [[self getUsingLKDBHelper] search:self where:where orderBy:nil offset:0 count:0];
|
||||
}
|
||||
|
||||
+ (NSMutableArray *)searchWithSQL:(NSString *)sql
|
||||
{
|
||||
return [[self getUsingLKDBHelper] searchWithSQL:sql toClass:self];
|
||||
}
|
||||
|
||||
+ (id)searchSingleWithWhere:(id)where orderBy:(NSString *)orderBy
|
||||
{
|
||||
return [[self getUsingLKDBHelper] searchSingle:self where:where orderBy:orderBy];
|
||||
}
|
||||
|
||||
+ (BOOL)insertToDB:(NSObject *)model
|
||||
{
|
||||
|
||||
if ([self checkModelClass:model]) {
|
||||
return [[self getUsingLKDBHelper] insertToDB:model];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)insertWhenNotExists:(NSObject *)model
|
||||
{
|
||||
if ([self checkModelClass:model]) {
|
||||
return [[self getUsingLKDBHelper] insertWhenNotExists:model];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)updateToDB:(NSObject *)model where:(id)where, ...
|
||||
{
|
||||
if ([self checkModelClass:model]) {
|
||||
if ([where isKindOfClass:[NSString class]]) {
|
||||
va_list list;
|
||||
va_start(list, where);
|
||||
where = [[NSString alloc] initWithFormat:where arguments:list];
|
||||
va_end(list);
|
||||
}
|
||||
return [[self getUsingLKDBHelper] updateToDB:model where:where];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)updateToDBWithSet:(NSString *)sets where:(id)where, ...
|
||||
{
|
||||
if ([where isKindOfClass:[NSString class]]) {
|
||||
va_list list;
|
||||
va_start(list, where);
|
||||
where = [[NSString alloc] initWithFormat:where arguments:list];
|
||||
va_end(list);
|
||||
}
|
||||
return [[self getUsingLKDBHelper] updateToDB:self set:sets where:where];
|
||||
}
|
||||
|
||||
+ (BOOL)deleteToDB:(NSObject *)model
|
||||
{
|
||||
if ([self checkModelClass:model]) {
|
||||
return [[self getUsingLKDBHelper] deleteToDB:model];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)deleteWithWhere:(id)where, ...
|
||||
{
|
||||
if ([where isKindOfClass:[NSString class]]) {
|
||||
va_list list;
|
||||
va_start(list, where);
|
||||
where = [[NSString alloc] initWithFormat:where arguments:list];
|
||||
va_end(list);
|
||||
}
|
||||
return [[self getUsingLKDBHelper] deleteWithClass:self where:where];
|
||||
}
|
||||
|
||||
+ (BOOL)isExistsWithModel:(NSObject *)model
|
||||
{
|
||||
if ([self checkModelClass:model]) {
|
||||
return [[self getUsingLKDBHelper] isExistsModel:model];
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)updateToDB
|
||||
{
|
||||
if (self.rowid > 0) {
|
||||
return [self.class updateToDB:self where:nil];
|
||||
} else {
|
||||
return [self saveToDB];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)saveToDB
|
||||
{
|
||||
return [self.class insertToDB:self];
|
||||
}
|
||||
|
||||
- (BOOL)deleteToDB
|
||||
{
|
||||
return [self.class deleteToDB:self];
|
||||
}
|
||||
|
||||
- (BOOL)isExistsFromDB
|
||||
{
|
||||
return [self.class isExistsWithModel:self];
|
||||
}
|
||||
|
||||
+ (void)insertArrayByAsyncToDB:(NSArray *)models
|
||||
{
|
||||
[self insertArrayByAsyncToDB:models completed:nil];
|
||||
}
|
||||
|
||||
+ (void)insertArrayByAsyncToDB:(NSArray *)models completed:(void (^_Nullable)(BOOL))completedBlock
|
||||
{
|
||||
if (models.count > 0) {
|
||||
dispatch_async(dispatch_get_global_queue(0, 0), ^{
|
||||
[self insertToDBWithArray:models filter:nil completed:completedBlock];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)insertToDBWithArray:(NSArray *)models filter:(void (^)(id model, BOOL inserted, BOOL *rollback))filter
|
||||
{
|
||||
[self insertToDBWithArray:models filter:filter completed:nil];
|
||||
}
|
||||
|
||||
+ (void)insertToDBWithArray:(NSArray *)models filter:(void (^)(id model, BOOL inserted, BOOL *rollback))filter completed:(void (^)(BOOL))completedBlock
|
||||
{
|
||||
__block BOOL allInserted = YES;
|
||||
[[self getUsingLKDBHelper] executeForTransaction:^BOOL(LKDBHelper *helper) {
|
||||
BOOL isRollback = NO;
|
||||
for (int i = 0; i < models.count; i++) {
|
||||
id obj = [models objectAtIndex:i];
|
||||
BOOL inserted = [helper insertToDB:obj];
|
||||
allInserted &= inserted;
|
||||
if (filter) {
|
||||
filter(obj, inserted, &isRollback);
|
||||
}
|
||||
if (isRollback) {
|
||||
allInserted = NO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (isRollback == NO);
|
||||
}];
|
||||
|
||||
if (completedBlock) {
|
||||
completedBlock(allInserted);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// NSObject+LKModel.h
|
||||
// LKDBHelper
|
||||
//
|
||||
// Created by LJH on 13-4-15.
|
||||
// Copyright (c) 2013年 ljh. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class LKDBProperty;
|
||||
@class LKModelInfos;
|
||||
@class LKDBHelper;
|
||||
|
||||
#pragma mark - 表结构
|
||||
@interface NSObject (LKTabelStructure)
|
||||
|
||||
/**
|
||||
* overwrite in your models(option)
|
||||
*
|
||||
* @return # table name #
|
||||
*/
|
||||
+ (NSString *)getTableName;
|
||||
|
||||
/**
|
||||
* if you set it will use it as a table name
|
||||
*/
|
||||
@property (nullable, nonatomic, copy) NSString *db_tableName;
|
||||
|
||||
/**
|
||||
* the model is inserting ..
|
||||
*/
|
||||
@property (nonatomic, readonly) BOOL db_inserting;
|
||||
|
||||
/**
|
||||
* sqlite comes with rowid
|
||||
*/
|
||||
@property (nonatomic, assign) NSInteger rowid;
|
||||
|
||||
/**
|
||||
* overwrite in your models, if your table has primary key
|
||||
|
||||
* 主键列名 如果rowid<0 则跟据此名称update 和delete
|
||||
|
||||
* @return # column name #
|
||||
*/
|
||||
+ (nullable NSString *)getPrimaryKey;
|
||||
|
||||
/**
|
||||
* multi primary key
|
||||
* 联合主键
|
||||
* @return
|
||||
*/
|
||||
+ (nullable NSArray *)getPrimaryKeyUnionArray;
|
||||
|
||||
/**
|
||||
* overwrite in your models set column attribute
|
||||
*
|
||||
* @param property infos
|
||||
*/
|
||||
+ (void)columnAttributeWithProperty:(LKDBProperty *)property;
|
||||
|
||||
/**
|
||||
* @brief get saved pictures and data file path,can overwirte
|
||||
|
||||
获取保存的 图片和数据的文件路径
|
||||
*/
|
||||
+ (NSString *)getDBImagePathWithName:(NSString *)filename;
|
||||
+ (NSString *)getDBDataPathWithName:(NSString *)filename;
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark - 表数据操作
|
||||
@interface NSObject (LKTableData)
|
||||
|
||||
/***
|
||||
* @brief overwrite in your models,return insert sqlite table data
|
||||
*
|
||||
*
|
||||
* @return property the data after conversion
|
||||
*/
|
||||
- (nullable id)userGetValueForModel:(LKDBProperty *)property;
|
||||
|
||||
/***
|
||||
* @brief overwrite in your models,return insert sqlite table data
|
||||
*
|
||||
* @param property will set property
|
||||
* @param value sqlite value (NSString(NSData UTF8 Coding) or NSData)
|
||||
*/
|
||||
- (void)userSetValueForModel:(LKDBProperty *)property value:(nullable id)value;
|
||||
|
||||
///overwrite
|
||||
+ (NSDateFormatter *)getModelDateFormatter;
|
||||
|
||||
//lkdbhelper use
|
||||
- (nullable id)modelGetValue:(LKDBProperty *)property;
|
||||
- (void)modelSetValue:(LKDBProperty *)property value:(nullable NSString *)value;
|
||||
|
||||
- (nullable id)singlePrimaryKeyValue;
|
||||
- (BOOL)singlePrimaryKeyValueIsEmpty;
|
||||
- (nullable LKDBProperty *)singlePrimaryKeyProperty;
|
||||
+ (nullable NSString *)db_rowidAliasName;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSObject (LKModel)
|
||||
|
||||
/**
|
||||
* return model use LKDBHelper , default return global LKDBHelper;
|
||||
*
|
||||
* @return LKDBHelper
|
||||
*/
|
||||
+ (LKDBHelper *)getUsingLKDBHelper;
|
||||
|
||||
/**
|
||||
* class attributes
|
||||
*
|
||||
* @return LKModelInfos
|
||||
*/
|
||||
+ (LKModelInfos *)getModelInfos;
|
||||
|
||||
/**
|
||||
* @brief Containing the super class attributes 设置是否包含 父类 的属性
|
||||
*/
|
||||
+ (BOOL)isContainParent;
|
||||
|
||||
/**
|
||||
* 当前表中的列是否包含自身的属性。
|
||||
*
|
||||
* @return BOOL
|
||||
*/
|
||||
+ (BOOL)isContainSelf;
|
||||
|
||||
/**
|
||||
* @brief log all property 打印所有的属性名称和数据
|
||||
*/
|
||||
- (NSString *)printAllPropertys;
|
||||
- (NSString *)printAllPropertysIsContainParent:(BOOL)containParent;
|
||||
|
||||
- (NSMutableString *)getAllPropertysString;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
+922
@@ -0,0 +1,922 @@
|
||||
//
|
||||
// NSObject+LKModel.m
|
||||
// LKDBHelper
|
||||
//
|
||||
// Created by LJH on 13-4-15.
|
||||
// Copyright (c) 2013年 ljh. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LKDBHelper.h"
|
||||
#import "NSObject+LKModel.h"
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
#import <UIKit/UIKit.h>
|
||||
#define LKDBImage UIImage
|
||||
#define LKDBColor UIColor
|
||||
#else
|
||||
#import <AppKit/AppKit.h>
|
||||
#define LKDBImage NSImage
|
||||
#define LKDBColor NSColor
|
||||
#endif
|
||||
|
||||
static char LKModelBase_Key_RowID;
|
||||
static char LKModelBase_Key_TableName;
|
||||
static char LKModelBase_Key_Inserting;
|
||||
|
||||
@interface LKDBHelper (LKDBHelper_LKModel)
|
||||
+ (BOOL)nullIsEmpty;
|
||||
@end
|
||||
|
||||
@implementation NSObject (LKModel)
|
||||
|
||||
+ (LKDBHelper *)getUsingLKDBHelper
|
||||
{
|
||||
///ios8 能获取系统类的属性了 所以没有办法判断属性数量来区分自定义类和系统类
|
||||
///可能系统类的存取会不正确
|
||||
static LKDBHelper *helper;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
helper = [[LKDBHelper alloc] init];
|
||||
});
|
||||
return helper;
|
||||
}
|
||||
#pragma mark Tabel Structure Function 表结构
|
||||
+ (NSString *)getTableName
|
||||
{
|
||||
return NSStringFromClass(self);
|
||||
}
|
||||
|
||||
+ (NSString *)getPrimaryKey
|
||||
{
|
||||
return @"rowid";
|
||||
}
|
||||
|
||||
+ (NSArray *)getPrimaryKeyUnionArray
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
+ (void)columnAttributeWithProperty:(LKDBProperty *)property
|
||||
{
|
||||
//overwrite
|
||||
}
|
||||
#pragma 属性
|
||||
- (void)setRowid:(NSInteger)rowid
|
||||
{
|
||||
objc_setAssociatedObject(self, &LKModelBase_Key_RowID, [NSNumber numberWithInteger:rowid], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
- (NSInteger)rowid
|
||||
{
|
||||
return [objc_getAssociatedObject(self, &LKModelBase_Key_RowID) integerValue];
|
||||
}
|
||||
|
||||
- (void)setDb_tableName:(NSString *)db_tableName
|
||||
{
|
||||
objc_setAssociatedObject(self, &LKModelBase_Key_TableName, db_tableName, OBJC_ASSOCIATION_COPY_NONATOMIC);
|
||||
}
|
||||
- (NSString *)db_tableName
|
||||
{
|
||||
NSString *tableName = objc_getAssociatedObject(self, &LKModelBase_Key_TableName);
|
||||
if (tableName.length == 0) {
|
||||
tableName = [self.class getTableName];
|
||||
}
|
||||
return tableName;
|
||||
}
|
||||
- (BOOL)db_inserting
|
||||
{
|
||||
return [objc_getAssociatedObject(self, &LKModelBase_Key_Inserting) boolValue];
|
||||
}
|
||||
- (void)setDb_inserting:(BOOL)db_inserting
|
||||
{
|
||||
NSNumber *number = nil;
|
||||
if (db_inserting) {
|
||||
number = [NSNumber numberWithBool:YES];
|
||||
}
|
||||
objc_setAssociatedObject(self, &LKModelBase_Key_Inserting, number, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
}
|
||||
#pragma 无关紧要的
|
||||
+ (NSString *)getDBImagePathWithName:(NSString *)filename
|
||||
{
|
||||
NSString *dir = [NSString stringWithFormat:@"dbimg/%@", NSStringFromClass(self)];
|
||||
return [LKDBUtils getPathForDocuments:filename inDir:dir];
|
||||
}
|
||||
+ (NSString *)getDBDataPathWithName:(NSString *)filename
|
||||
{
|
||||
NSString *dir = [NSString stringWithFormat:@"dbdata/%@", NSStringFromClass(self)];
|
||||
return [LKDBUtils getPathForDocuments:filename inDir:dir];
|
||||
}
|
||||
+ (NSDictionary *)getTableMapping
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
#pragma mark - Table Data Function 表数据
|
||||
+ (NSDateFormatter *)getModelDateFormatter
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
///get
|
||||
- (id)modelGetValue:(LKDBProperty *)property
|
||||
{
|
||||
id value = [self valueForKey:property.propertyName];
|
||||
id returnValue = value;
|
||||
if (value == nil) {
|
||||
return nil;
|
||||
} else if ([value isKindOfClass:[NSString class]]) {
|
||||
returnValue = [value copy];
|
||||
} else if ([value isKindOfClass:[NSNumber class]]) {
|
||||
returnValue = [[LKDBUtils numberFormatter] stringFromNumber:value];
|
||||
} else if ([value isKindOfClass:[NSDate class]]) {
|
||||
NSDateFormatter *formatter = [self.class getModelDateFormatter];
|
||||
if (formatter) {
|
||||
returnValue = [formatter stringFromDate:value];
|
||||
} else {
|
||||
returnValue = [LKDBUtils stringWithDate:value];
|
||||
}
|
||||
returnValue = [returnValue stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
} else if ([value isKindOfClass:[LKDBColor class]]) {
|
||||
LKDBColor *color = value;
|
||||
CGFloat r, g, b, a;
|
||||
[color getRed:&r green:&g blue:&b alpha:&a];
|
||||
returnValue = [NSString stringWithFormat:@"%.3f,%.3f,%.3f,%.3f", r, g, b, a];
|
||||
} else if ([value isKindOfClass:[NSValue class]]) {
|
||||
NSString *columnType = property.propertyType;
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
if ([columnType isEqualToString:@"CGRect"]) {
|
||||
returnValue = NSStringFromCGRect([value CGRectValue]);
|
||||
} else if ([columnType isEqualToString:@"CGPoint"]) {
|
||||
returnValue = NSStringFromCGPoint([value CGPointValue]);
|
||||
} else if ([columnType isEqualToString:@"CGSize"]) {
|
||||
returnValue = NSStringFromCGSize([value CGSizeValue]);
|
||||
} else if ([columnType isEqualToString:@"_NSRange"]) {
|
||||
returnValue = NSStringFromRange([value rangeValue]);
|
||||
}
|
||||
#else
|
||||
if ([columnType hasSuffix:@"Rect"]) {
|
||||
returnValue = NSStringFromRect([value rectValue]);
|
||||
} else if ([columnType hasSuffix:@"Point"]) {
|
||||
returnValue = NSStringFromPoint([value pointValue]);
|
||||
} else if ([columnType hasSuffix:@"Size"]) {
|
||||
returnValue = NSStringFromSize([value sizeValue]);
|
||||
} else if ([columnType hasSuffix:@"Range"]) {
|
||||
returnValue = NSStringFromRange([value rangeValue]);
|
||||
}
|
||||
#endif
|
||||
} else if ([value isKindOfClass:[LKDBImage class]]) {
|
||||
long random = arc4random();
|
||||
long date = [[NSDate date] timeIntervalSince1970];
|
||||
NSString *filename = [NSString stringWithFormat:@"img%ld%ld", date & 0xFFFFF, random & 0xFFF];
|
||||
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
NSData *datas = UIImageJPEGRepresentation(value, 1);
|
||||
#else
|
||||
[value lockFocus];
|
||||
NSBitmapImageRep *srcImageRep = [NSBitmapImageRep imageRepWithData:[value TIFFRepresentation]];
|
||||
NSData *datas = [srcImageRep representationUsingType:NSJPEGFileType properties:@{}];
|
||||
[value unlockFocus];
|
||||
#endif
|
||||
[datas writeToFile:[self.class getDBImagePathWithName:filename]
|
||||
atomically:YES];
|
||||
|
||||
returnValue = filename;
|
||||
} else if ([value isKindOfClass:[NSData class]]) {
|
||||
long random = arc4random();
|
||||
long date = [[NSDate date] timeIntervalSince1970];
|
||||
NSString *filename = [NSString stringWithFormat:@"data%ld%ld", date & 0xFFFFF, random & 0xFFF];
|
||||
|
||||
[value writeToFile:[self.class getDBDataPathWithName:filename] atomically:YES];
|
||||
|
||||
returnValue = filename;
|
||||
} else if ([value isKindOfClass:[NSURL class]]) {
|
||||
returnValue = [value absoluteString];
|
||||
} else {
|
||||
if ([value isKindOfClass:[NSArray class]]) {
|
||||
returnValue = [self db_jsonObjectFromArray:value];
|
||||
} else if ([value isKindOfClass:[NSDictionary class]]) {
|
||||
returnValue = [self db_jsonObjectFromDictionary:value];
|
||||
} else {
|
||||
returnValue = [self db_jsonObjectFromModel:value];
|
||||
}
|
||||
returnValue = [self db_jsonStringFromObject:returnValue];
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
///set
|
||||
- (void)modelSetValue:(LKDBProperty *)property value:(NSString *)value
|
||||
{
|
||||
///参试获取属性的Class
|
||||
Class columnClass = NSClassFromString(property.propertyType);
|
||||
|
||||
id modelValue = nil;
|
||||
|
||||
if (columnClass == nil) {
|
||||
///当找不到 class 时,就是 基础类型 int,float CGRect 之类的
|
||||
NSString *columnType = property.propertyType;
|
||||
if ([LKSQL_Convert_FloatType rangeOfString:columnType].location != NSNotFound) {
|
||||
if (value) {
|
||||
modelValue = [[LKDBUtils numberFormatter] numberFromString:value];
|
||||
}
|
||||
} else if ([LKSQL_Convert_IntType rangeOfString:columnType].location != NSNotFound) {
|
||||
if (value) {
|
||||
modelValue = [[LKDBUtils numberFormatter] numberFromString:value];
|
||||
}
|
||||
}
|
||||
#ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
|
||||
else if ([columnType isEqualToString:@"CGRect"]) {
|
||||
if (value) {
|
||||
CGRect rect = CGRectFromString(value);
|
||||
modelValue = [NSValue valueWithCGRect:rect];
|
||||
} else {
|
||||
modelValue = [NSValue valueWithCGRect:CGRectZero];
|
||||
}
|
||||
} else if ([columnType isEqualToString:@"CGPoint"]) {
|
||||
if (value) {
|
||||
CGPoint point = CGPointFromString(value);
|
||||
modelValue = [NSValue valueWithCGPoint:point];
|
||||
} else {
|
||||
modelValue = [NSValue valueWithCGPoint:CGPointZero];
|
||||
}
|
||||
} else if ([columnType isEqualToString:@"CGSize"]) {
|
||||
if (value) {
|
||||
CGSize size = CGSizeFromString(value);
|
||||
modelValue = [NSValue valueWithCGSize:size];
|
||||
} else {
|
||||
modelValue = [NSValue valueWithCGSize:CGSizeZero];
|
||||
}
|
||||
} else if ([columnType isEqualToString:@"_NSRange"]) {
|
||||
if (value) {
|
||||
NSRange range = NSRangeFromString(value);
|
||||
modelValue = [NSValue valueWithRange:range];
|
||||
} else {
|
||||
modelValue = [NSValue valueWithRange:NSMakeRange(0, 0)];
|
||||
}
|
||||
}
|
||||
#else
|
||||
else if ([columnType hasSuffix:@"Rect"]) {
|
||||
if (value) {
|
||||
NSRect rect = NSRectFromString(value);
|
||||
modelValue = [NSValue valueWithRect:rect];
|
||||
} else {
|
||||
modelValue = [NSValue valueWithRect:NSZeroRect];
|
||||
}
|
||||
} else if ([columnType hasSuffix:@"Point"]) {
|
||||
if (value) {
|
||||
NSPoint point = NSPointFromString(value);
|
||||
modelValue = [NSValue valueWithPoint:point];
|
||||
} else {
|
||||
modelValue = [NSValue valueWithPoint:NSZeroPoint];
|
||||
}
|
||||
} else if ([columnType hasSuffix:@"Size"]) {
|
||||
if (value) {
|
||||
NSSize size = NSSizeFromString(value);
|
||||
modelValue = [NSValue valueWithSize:size];
|
||||
} else {
|
||||
modelValue = [NSValue valueWithSize:NSZeroSize];
|
||||
}
|
||||
} else if ([columnType hasSuffix:@"Range"]) {
|
||||
if (value) {
|
||||
NSRange range = NSRangeFromString(value);
|
||||
modelValue = [NSValue valueWithRange:range];
|
||||
} else {
|
||||
modelValue = [NSValue valueWithRange:NSMakeRange(0, 0)];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
///如果都没有值 默认给个0
|
||||
if (modelValue == nil) {
|
||||
modelValue = @0;
|
||||
}
|
||||
} else if (!value || ![value isKindOfClass:[NSString class]]) {
|
||||
//不继续遍历
|
||||
} else if ([columnClass isSubclassOfClass:[NSString class]]) {
|
||||
if (![LKDBHelper nullIsEmpty] || value.length > 0) {
|
||||
modelValue = [columnClass stringWithString:value];
|
||||
}
|
||||
} else if ([columnClass isSubclassOfClass:[NSNumber class]]) {
|
||||
modelValue = [[LKDBUtils numberFormatter] numberFromString:value];
|
||||
} else if ([columnClass isSubclassOfClass:[NSDate class]]) {
|
||||
NSString *datestr = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
NSDateFormatter *formatter = [self.class getModelDateFormatter];
|
||||
if (formatter) {
|
||||
modelValue = [formatter dateFromString:datestr];
|
||||
} else {
|
||||
modelValue = [LKDBUtils dateWithString:datestr];
|
||||
}
|
||||
} else if ([columnClass isSubclassOfClass:[LKDBColor class]]) {
|
||||
NSString *colorString = value;
|
||||
NSArray *array = [colorString componentsSeparatedByString:@","];
|
||||
float r, g, b, a;
|
||||
r = [[array objectAtIndex:0] floatValue];
|
||||
g = [[array objectAtIndex:1] floatValue];
|
||||
b = [[array objectAtIndex:2] floatValue];
|
||||
a = [[array objectAtIndex:3] floatValue];
|
||||
|
||||
modelValue = [LKDBColor colorWithRed:r green:g blue:b alpha:a];
|
||||
} else if ([columnClass isSubclassOfClass:[LKDBImage class]]) {
|
||||
NSString *filename = value;
|
||||
NSString *filepath = [self.class getDBImagePathWithName:filename];
|
||||
if ([LKDBUtils isFileExists:filepath]) {
|
||||
modelValue = [[LKDBImage alloc] initWithContentsOfFile:filepath];
|
||||
}
|
||||
} else if ([columnClass isSubclassOfClass:[NSData class]]) {
|
||||
NSString *filename = value;
|
||||
NSString *filepath = [self.class getDBDataPathWithName:filename];
|
||||
if ([LKDBUtils isFileExists:filepath]) {
|
||||
modelValue = [NSData dataWithContentsOfFile:filepath];
|
||||
}
|
||||
} else if ([columnClass isSubclassOfClass:[NSURL class]]) {
|
||||
NSString *urlString = value;
|
||||
modelValue = [NSURL URLWithString:urlString];
|
||||
} else {
|
||||
modelValue = [self db_modelWithJsonValue:value];
|
||||
BOOL isValid = NO;
|
||||
if ([modelValue isKindOfClass:[NSArray class]] && [columnClass isSubclassOfClass:[NSArray class]]) {
|
||||
isValid = YES;
|
||||
modelValue = [columnClass arrayWithArray:modelValue];
|
||||
} else if ([modelValue isKindOfClass:[NSDictionary class]] && [columnClass isSubclassOfClass:[NSDictionary class]]) {
|
||||
isValid = YES;
|
||||
modelValue = [columnClass dictionaryWithDictionary:modelValue];
|
||||
} else if ([modelValue isKindOfClass:columnClass]) {
|
||||
isValid = YES;
|
||||
}
|
||||
///如果类型不对 则设置为空
|
||||
if (!isValid) {
|
||||
modelValue = nil;
|
||||
}
|
||||
}
|
||||
|
||||
[self setValue:modelValue forKey:property.propertyName];
|
||||
}
|
||||
#pragma mark - 对 model NSArray NSDictionary 进行支持
|
||||
- (id)db_jsonObjectFromDictionary:(NSDictionary *)dic
|
||||
{
|
||||
if ([NSJSONSerialization isValidJSONObject:dic]) {
|
||||
NSDictionary *bomb = @{LKDB_TypeKey: LKDB_TypeKey_JSON, LKDB_ValueKey: dic};
|
||||
return bomb;
|
||||
} else {
|
||||
NSMutableDictionary *toDic = [NSMutableDictionary dictionary];
|
||||
[dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL *_Nonnull stop) {
|
||||
id jsonObject = [self db_jsonObjectWithObject:obj];
|
||||
if (jsonObject) {
|
||||
toDic[key] = jsonObject;
|
||||
}
|
||||
}];
|
||||
if (toDic.count) {
|
||||
NSDictionary *bomb = @{LKDB_TypeKey: LKDB_TypeKey_Combo, LKDB_ValueKey: toDic};
|
||||
return bomb;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
- (id)db_jsonObjectFromArray:(NSArray *)array
|
||||
{
|
||||
if ([NSJSONSerialization isValidJSONObject:array]) {
|
||||
NSDictionary *bomb = @{LKDB_TypeKey: LKDB_TypeKey_JSON, LKDB_ValueKey: array};
|
||||
return bomb;
|
||||
} else {
|
||||
NSMutableArray *toArray = [NSMutableArray array];
|
||||
NSInteger count = array.count;
|
||||
for (NSInteger i = 0; i < count; i++) {
|
||||
id obj = [array objectAtIndex:i];
|
||||
id jsonObject = [self db_jsonObjectWithObject:obj];
|
||||
if (jsonObject) {
|
||||
[toArray addObject:jsonObject];
|
||||
}
|
||||
}
|
||||
|
||||
if (toArray.count) {
|
||||
NSDictionary *bomb = @{LKDB_TypeKey: LKDB_TypeKey_Combo, LKDB_ValueKey: toArray};
|
||||
return bomb;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
///目前只支持 model、NSString、NSNumber 简单类型
|
||||
- (id)db_jsonObjectWithObject:(id)obj
|
||||
{
|
||||
id jsonObject = nil;
|
||||
if ([obj isKindOfClass:[NSString class]] || [obj isKindOfClass:[NSNumber class]]) {
|
||||
jsonObject = obj;
|
||||
} else if ([obj isKindOfClass:[NSDate class]]) {
|
||||
NSString *dateString = nil;
|
||||
NSDateFormatter *formatter = [self.class getModelDateFormatter];
|
||||
if (formatter) {
|
||||
dateString = [formatter stringFromDate:obj];
|
||||
} else {
|
||||
dateString = [LKDBUtils stringWithDate:obj];
|
||||
}
|
||||
dateString = [dateString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
||||
if (dateString.length > 0) {
|
||||
jsonObject = @{LKDB_TypeKey: LKDB_TypeKey_Date, LKDB_ValueKey: dateString};
|
||||
}
|
||||
} else if ([obj isKindOfClass:[NSArray class]]) {
|
||||
jsonObject = [self db_jsonObjectFromArray:obj];
|
||||
} else if ([obj isKindOfClass:[NSDictionary class]]) {
|
||||
jsonObject = [self db_jsonObjectFromDictionary:obj];
|
||||
} else {
|
||||
jsonObject = [self db_jsonObjectFromModel:obj];
|
||||
}
|
||||
|
||||
if (jsonObject == nil) {
|
||||
jsonObject = [obj description];
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
- (id)db_jsonObjectFromModel:(NSObject *)model
|
||||
{
|
||||
Class clazz = model.class;
|
||||
NSDictionary *jsonObject = nil;
|
||||
if (model.rowid > 0) {
|
||||
[model updateToDB];
|
||||
jsonObject = [self db_readInfoWithModel:model class:clazz];
|
||||
} else {
|
||||
if (model.db_inserting == NO && [clazz getModelInfos].count > 0) {
|
||||
BOOL success = [model saveToDB];
|
||||
if (success) {
|
||||
jsonObject = [self db_readInfoWithModel:model class:clazz];
|
||||
}
|
||||
} else {
|
||||
NSAssert(NO, @"目前LKDB 还不支持 循环引用。 比如 A 持有 B, B 持有 A,这种的存储");
|
||||
}
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
- (NSDictionary *)db_readInfoWithModel:(NSObject *)model class:(Class)clazz
|
||||
{
|
||||
NSMutableDictionary *jsonObject = [NSMutableDictionary dictionary];
|
||||
if (!model.db_tableName) {
|
||||
NSAssert(NO, @"none table name");
|
||||
return nil;
|
||||
}
|
||||
if (!NSStringFromClass(clazz)) {
|
||||
NSAssert(NO, @"none class");
|
||||
return nil;
|
||||
}
|
||||
|
||||
jsonObject[LKDB_TypeKey] = LKDB_TypeKey_Model;
|
||||
jsonObject[LKDB_TableNameKey] = model.db_tableName;
|
||||
jsonObject[LKDB_ClassKey] = NSStringFromClass(clazz);
|
||||
jsonObject[LKDB_RowIdKey] = @(model.rowid);
|
||||
|
||||
NSDictionary *dic = [model db_getPrimaryKeysValues];
|
||||
if (dic.count > 0 && [NSJSONSerialization isValidJSONObject:dic]) {
|
||||
jsonObject[LKDB_PValueKey] = dic;
|
||||
}
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
- (NSString *)db_jsonStringFromObject : (NSObject *)jsonObject
|
||||
{
|
||||
if (jsonObject && [NSJSONSerialization isValidJSONObject:jsonObject]) {
|
||||
NSData *data = [NSJSONSerialization dataWithJSONObject:jsonObject options:0 error:nil];
|
||||
if (data.length > 0) {
|
||||
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
return jsonString;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
- (id)db_modelWithJsonValue:(id)value
|
||||
{
|
||||
NSData *jsonData = nil;
|
||||
if ([value isKindOfClass:[NSString class]]) {
|
||||
jsonData = [value dataUsingEncoding:NSUTF8StringEncoding];
|
||||
} else if ([value isKindOfClass:[NSData class]]) {
|
||||
jsonData = value;
|
||||
}
|
||||
|
||||
if (jsonData.length > 0) {
|
||||
NSDictionary *jsonDic = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
|
||||
return [self db_objectWithDictionary:jsonDic];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
- (id)db_objectWithArray:(NSArray *)array
|
||||
{
|
||||
NSMutableArray *toArray = nil;
|
||||
|
||||
NSInteger count = array.count;
|
||||
for (NSInteger i = 0; i < count; i++) {
|
||||
id value = [array objectAtIndex:i];
|
||||
if ([value isKindOfClass:[NSDictionary class]]) {
|
||||
value = [self db_objectWithDictionary:value];
|
||||
} else if ([value isKindOfClass:[NSArray class]]) {
|
||||
value = [self db_objectWithArray:value];
|
||||
}
|
||||
|
||||
if (value) {
|
||||
if (toArray == nil) {
|
||||
toArray = [NSMutableArray array];
|
||||
}
|
||||
[toArray addObject:value];
|
||||
}
|
||||
}
|
||||
|
||||
return toArray;
|
||||
}
|
||||
- (id)db_objectWithDictionary:(NSDictionary *)dic
|
||||
{
|
||||
if (dic.count == 0) {
|
||||
return nil;
|
||||
}
|
||||
NSString *type = [dic objectForKey:LKDB_TypeKey];
|
||||
if (type) {
|
||||
if ([type isEqualToString:LKDB_TypeKey_Model]) {
|
||||
Class clazz = NSClassFromString([dic objectForKey:LKDB_ClassKey]);
|
||||
NSInteger rowid = [[dic objectForKey:LKDB_RowIdKey] integerValue];
|
||||
NSString *tableName = [dic objectForKey:LKDB_TableNameKey];
|
||||
|
||||
NSString *where = nil;
|
||||
|
||||
NSString *rowCountWhere = [NSString stringWithFormat:@"select count(rowid) from %@ where rowid=%ld limit 1", tableName, (long)rowid];
|
||||
NSInteger result = [[[clazz getUsingLKDBHelper] executeScalarWithSQL:rowCountWhere arguments:nil] integerValue];
|
||||
if (result > 0) {
|
||||
where = [NSString stringWithFormat:@"select rowid,* from %@ where rowid=%ld limit 1", tableName, (long)rowid];
|
||||
} else {
|
||||
NSDictionary *pv = [dic objectForKey:LKDB_PValueKey];
|
||||
if (pv.count > 0) {
|
||||
BOOL isNeedAddDot = NO;
|
||||
NSMutableString *sb = [NSMutableString stringWithFormat:@"select rowid,* from %@ where", tableName];
|
||||
|
||||
NSArray *allKeys = pv.allKeys;
|
||||
for (NSString *key in allKeys) {
|
||||
id obj = [pv objectForKey:key];
|
||||
if (isNeedAddDot) {
|
||||
[sb appendString:@" and"];
|
||||
}
|
||||
[sb appendFormat:@" %@ = '%@'", key, obj];
|
||||
|
||||
isNeedAddDot = YES;
|
||||
}
|
||||
|
||||
[sb appendString:@" limit 1"];
|
||||
|
||||
where = [NSString stringWithString:sb];
|
||||
}
|
||||
}
|
||||
|
||||
if (where) {
|
||||
NSArray *array = [[clazz getUsingLKDBHelper] searchWithSQL:where toClass:clazz];
|
||||
if (array.count > 0) {
|
||||
NSObject *result = [array objectAtIndex:0];
|
||||
result.db_tableName = tableName;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
} else if ([type isEqualToString:LKDB_TypeKey_JSON]) {
|
||||
id value = [dic objectForKey:LKDB_ValueKey];
|
||||
return value;
|
||||
} else if ([type isEqualToString:LKDB_TypeKey_Combo]) {
|
||||
id value = [dic objectForKey:LKDB_ValueKey];
|
||||
if ([value isKindOfClass:[NSArray class]]) {
|
||||
return [self db_objectWithArray:value];
|
||||
} else if ([value isKindOfClass:[NSDictionary class]]) {
|
||||
return [self db_objectWithDictionary:value];
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
} else if ([type isEqualToString:LKDB_TypeKey_Date]) {
|
||||
NSString *datestr = [dic objectForKey:LKDB_ValueKey];
|
||||
NSDateFormatter *formatter = [self.class getModelDateFormatter];
|
||||
if (formatter) {
|
||||
return [formatter dateFromString:datestr];
|
||||
} else {
|
||||
return [LKDBUtils dateWithString:datestr];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
NSMutableDictionary *toDic = [NSMutableDictionary dictionary];
|
||||
[dic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull value, BOOL *_Nonnull stop) {
|
||||
id saveObj = value;
|
||||
if ([value isKindOfClass:[NSArray class]]) {
|
||||
saveObj = [self db_objectWithArray:value];
|
||||
} else if ([value isKindOfClass:[NSDictionary class]]) {
|
||||
saveObj = [self db_objectWithDictionary:value];
|
||||
}
|
||||
|
||||
if (saveObj) {
|
||||
toDic[key] = saveObj;
|
||||
}
|
||||
}];
|
||||
return toDic;
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
#pragma mark - your can overwrite
|
||||
- (void)setNilValueForKey:(NSString *)key
|
||||
{
|
||||
NSLog(@"nil 这种设置到了 int 等基础类型中");
|
||||
}
|
||||
- (id)valueForUndefinedKey:(NSString *)key
|
||||
{
|
||||
NSLog(@"你有get方法没实现,key:%@", key);
|
||||
return nil;
|
||||
}
|
||||
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
|
||||
{
|
||||
NSLog(@"你有set方法没实现,key:%@", key);
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
- (void)userSetValueForModel:(LKDBProperty *)property value:(id)value
|
||||
{
|
||||
}
|
||||
- (id)userGetValueForModel:(LKDBProperty *)property
|
||||
{
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSDictionary *)db_getPrimaryKeysValues
|
||||
{
|
||||
LKModelInfos *infos = [self.class getModelInfos];
|
||||
NSArray *array = infos.primaryKeys;
|
||||
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
|
||||
[array enumerateObjectsUsingBlock:^(NSString *pname, NSUInteger idx, BOOL *_Nonnull stop) {
|
||||
LKDBProperty *property = [infos objectWithSqlColumnName:pname];
|
||||
id value = nil;
|
||||
if ([property.type isEqualToString:LKSQL_Mapping_UserCalculate]) {
|
||||
value = [self userGetValueForModel:property];
|
||||
} else {
|
||||
value = [self modelGetValue:property];
|
||||
}
|
||||
if (value) {
|
||||
dic[property.sqlColumnName] = value;
|
||||
}
|
||||
|
||||
}];
|
||||
return dic;
|
||||
}
|
||||
//主键值 是否为空
|
||||
- (BOOL)singlePrimaryKeyValueIsEmpty
|
||||
{
|
||||
LKDBProperty *property = [self singlePrimaryKeyProperty];
|
||||
if (property) {
|
||||
id pkvalue = [self singlePrimaryKeyValue];
|
||||
if ([property.sqlColumnType isEqualToString:LKSQL_Type_Int]) {
|
||||
if ([pkvalue isKindOfClass:[NSString class]]) {
|
||||
if ([LKDBUtils checkStringIsEmpty:pkvalue])
|
||||
return YES;
|
||||
|
||||
if ([pkvalue integerValue] == 0)
|
||||
return YES;
|
||||
|
||||
return NO;
|
||||
}
|
||||
if ([pkvalue isKindOfClass:[NSNumber class]]) {
|
||||
if ([pkvalue integerValue] == 0)
|
||||
return YES;
|
||||
else
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
} else {
|
||||
return (pkvalue == nil);
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
- (LKDBProperty *)singlePrimaryKeyProperty
|
||||
{
|
||||
LKModelInfos *infos = [self.class getModelInfos];
|
||||
if (infos.primaryKeys.count == 1) {
|
||||
NSString *name = [infos.primaryKeys objectAtIndex:0];
|
||||
return [infos objectWithSqlColumnName:name];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
- (id)singlePrimaryKeyValue
|
||||
{
|
||||
LKDBProperty *property = [self singlePrimaryKeyProperty];
|
||||
if (property) {
|
||||
if ([property.type isEqualToString:LKSQL_Mapping_UserCalculate]) {
|
||||
return [self userGetValueForModel:property];
|
||||
} else {
|
||||
return [self modelGetValue:property];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
+ (NSString *)db_rowidAliasName
|
||||
{
|
||||
LKModelInfos *infos = [self getModelInfos];
|
||||
if (infos.primaryKeys.count == 1) {
|
||||
NSString *primaryType = [infos objectWithSqlColumnName:[infos.primaryKeys lastObject]].sqlColumnType;
|
||||
if ([primaryType isEqualToString:LKSQL_Type_Int]) {
|
||||
return [infos.primaryKeys lastObject];
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
#pragma mark - get model property info
|
||||
+ (LKModelInfos *)getModelInfos
|
||||
{
|
||||
static __strong NSMutableDictionary *oncePropertyDic;
|
||||
static __strong NSRecursiveLock *lock;
|
||||
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
lock = [[NSRecursiveLock alloc] init];
|
||||
oncePropertyDic = [[NSMutableDictionary alloc] initWithCapacity:8];
|
||||
});
|
||||
|
||||
LKModelInfos *infos;
|
||||
[lock lock];
|
||||
NSString *className = NSStringFromClass(self);
|
||||
infos = [oncePropertyDic objectForKey:className];
|
||||
if (infos == nil) {
|
||||
NSMutableArray *pronames = [NSMutableArray array];
|
||||
NSMutableArray *protypes = [NSMutableArray array];
|
||||
NSDictionary *keymapping = [self getTableMapping];
|
||||
|
||||
if ([self isContainSelf] && self != [NSObject class]) {
|
||||
[self getSelfPropertys:pronames protypes:protypes];
|
||||
}
|
||||
|
||||
NSArray *pkArray = [self getPrimaryKeyUnionArray];
|
||||
if (pkArray.count == 0) {
|
||||
pkArray = nil;
|
||||
NSString *pk = [self getPrimaryKey];
|
||||
if ([LKDBUtils checkStringIsEmpty:pk] == NO) {
|
||||
pkArray = [NSArray arrayWithObject:pk];
|
||||
}
|
||||
}
|
||||
if ([self isContainParent] && [self superclass] != [NSObject class]) {
|
||||
LKModelInfos *superInfos = [[self superclass] getModelInfos];
|
||||
for (NSInteger i = 0; i < superInfos.count; i++) {
|
||||
LKDBProperty *db_p = [superInfos objectWithIndex:i];
|
||||
if (db_p.propertyName && db_p.propertyType && [db_p.propertyName isEqualToString:@"rowid"] == NO) {
|
||||
[pronames addObject:db_p.propertyName];
|
||||
[protypes addObject:db_p.propertyType];
|
||||
}
|
||||
}
|
||||
}
|
||||
if (pronames.count > 0) {
|
||||
infos = [[LKModelInfos alloc] initWithKeyMapping:keymapping propertyNames:pronames propertyType:protypes primaryKeys:pkArray];
|
||||
} else {
|
||||
infos = [[LKModelInfos alloc] init];
|
||||
}
|
||||
oncePropertyDic[className] = infos;
|
||||
}
|
||||
|
||||
[lock unlock];
|
||||
return infos;
|
||||
}
|
||||
|
||||
+ (BOOL)isContainParent
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)isContainSelf
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取自身的属性
|
||||
*
|
||||
* @param pronames 保存属性名称
|
||||
* @param protypes 保存属性类型
|
||||
*/
|
||||
+ (void)getSelfPropertys:(NSMutableArray *)pronames protypes:(NSMutableArray *)protypes
|
||||
{
|
||||
unsigned int outCount = 0, i = 0;
|
||||
objc_property_t *properties = class_copyPropertyList(self, &outCount);
|
||||
|
||||
for (i = 0; i < outCount; i++) {
|
||||
objc_property_t property = properties[i];
|
||||
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
|
||||
|
||||
//取消rowid 的插入 //子类 已重载的属性 取消插入
|
||||
if (propertyName.length == 0 || [propertyName isEqualToString:@"rowid"] ||
|
||||
[pronames indexOfObject:propertyName] != NSNotFound) {
|
||||
continue;
|
||||
}
|
||||
NSString *propertyType = [NSString stringWithCString:property_getAttributes(property) encoding:NSUTF8StringEncoding];
|
||||
|
||||
///过滤只读属性
|
||||
if ([propertyType rangeOfString:@",R,"].length > 0 || [propertyType hasSuffix:@",R"]) {
|
||||
NSString *firstWord = [[propertyName substringToIndex:1] uppercaseString];
|
||||
NSString *otherWord = [propertyName substringFromIndex:1];
|
||||
NSString *setMethodString = [NSString stringWithFormat:@"set%@%@:", firstWord, otherWord];
|
||||
SEL setSEL = NSSelectorFromString(setMethodString);
|
||||
///有set方法就不过滤了
|
||||
if ([self instancesRespondToSelector:setSEL] == NO) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
c char
|
||||
i int
|
||||
l long
|
||||
s short
|
||||
d double
|
||||
f float
|
||||
@ id //指针 对象
|
||||
... BOOL 获取到的表示 方式是 char
|
||||
.... ^i 表示 int * 一般都不会用到
|
||||
*/
|
||||
|
||||
NSString *propertyClassName = nil;
|
||||
if ([propertyType hasPrefix:@"T@"]) {
|
||||
|
||||
NSRange range = [propertyType rangeOfString:@","];
|
||||
if (range.location > 4 && range.location <= propertyType.length) {
|
||||
range = NSMakeRange(3, range.location - 4);
|
||||
propertyClassName = [propertyType substringWithRange:range];
|
||||
if ([propertyClassName hasSuffix:@">"]) {
|
||||
NSRange categoryRange = [propertyClassName rangeOfString:@"<"];
|
||||
if (categoryRange.length > 0) {
|
||||
propertyClassName = [propertyClassName substringToIndex:categoryRange.location];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if ([propertyType hasPrefix:@"T{"]) {
|
||||
NSRange range = [propertyType rangeOfString:@"="];
|
||||
if (range.location > 2 && range.location <= propertyType.length) {
|
||||
range = NSMakeRange(2, range.location - 2);
|
||||
propertyClassName = [propertyType substringWithRange:range];
|
||||
}
|
||||
} else {
|
||||
propertyType = [propertyType lowercaseString];
|
||||
if ([propertyType hasPrefix:@"ti"] || [propertyType hasPrefix:@"tb"]) {
|
||||
propertyClassName = @"int";
|
||||
} else if ([propertyType hasPrefix:@"tf"]) {
|
||||
propertyClassName = @"float";
|
||||
} else if ([propertyType hasPrefix:@"td"]) {
|
||||
propertyClassName = @"double";
|
||||
} else if ([propertyType hasPrefix:@"tl"] || [propertyType hasPrefix:@"tq"]) {
|
||||
propertyClassName = @"long";
|
||||
} else if ([propertyType hasPrefix:@"tc"]) {
|
||||
propertyClassName = @"char";
|
||||
} else if ([propertyType hasPrefix:@"ts"]) {
|
||||
propertyClassName = @"short";
|
||||
}
|
||||
}
|
||||
|
||||
if ([LKDBUtils checkStringIsEmpty:propertyClassName]) {
|
||||
///没找到具体的属性就放弃
|
||||
continue;
|
||||
}
|
||||
///添加属性
|
||||
[pronames addObject:propertyName];
|
||||
[protypes addObject:propertyClassName];
|
||||
}
|
||||
free(properties);
|
||||
if ([self isContainParent] && [self superclass] != [NSObject class]) {
|
||||
[[self superclass] getSelfPropertys:pronames protypes:protypes];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - log all property
|
||||
- (NSMutableString *)getAllPropertysString
|
||||
{
|
||||
Class clazz = [self class];
|
||||
NSMutableString *sb = [NSMutableString stringWithFormat:@"\n <%@> :\n", NSStringFromClass(clazz)];
|
||||
[sb appendFormat:@"rowid : %ld\n", (long)self.rowid];
|
||||
[self mutableString:sb appendPropertyStringWithClass:clazz containParent:YES];
|
||||
return sb;
|
||||
}
|
||||
- (NSString *)printAllPropertys
|
||||
{
|
||||
return [self printAllPropertysIsContainParent:NO];
|
||||
}
|
||||
- (NSString *)printAllPropertysIsContainParent:(BOOL)containParent
|
||||
{
|
||||
#ifdef DEBUG
|
||||
Class clazz = [self class];
|
||||
NSMutableString *sb = [NSMutableString stringWithFormat:@"\n <%@> :\n", NSStringFromClass(clazz)];
|
||||
[sb appendFormat:@"rowid : %ld\n", (long)self.rowid];
|
||||
[self mutableString:sb appendPropertyStringWithClass:clazz containParent:containParent];
|
||||
NSLog(@"%@", sb);
|
||||
return sb;
|
||||
#else
|
||||
return @"";
|
||||
#endif
|
||||
}
|
||||
- (void)mutableString:(NSMutableString *)sb appendPropertyStringWithClass:(Class)clazz containParent:(BOOL)containParent
|
||||
{
|
||||
if (clazz == [NSObject class]) {
|
||||
return;
|
||||
}
|
||||
unsigned int outCount = 0, i = 0;
|
||||
objc_property_t *properties = class_copyPropertyList(clazz, &outCount);
|
||||
for (i = 0; i < outCount; i++) {
|
||||
objc_property_t property = properties[i];
|
||||
NSString *propertyName = [NSString stringWithCString:property_getName(property) encoding:NSUTF8StringEncoding];
|
||||
[sb appendFormat:@" %@ : %@ \n", propertyName, [self valueForKey:propertyName]];
|
||||
}
|
||||
free(properties);
|
||||
if (containParent) {
|
||||
[self mutableString:sb appendPropertyStringWithClass:clazz.superclass containParent:containParent];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
Generated
+277
@@ -0,0 +1,277 @@
|
||||
|
||||
LKDBHelper
|
||||
====================================
|
||||
this is sqlite ORM (an automatic database operation) <br>
|
||||
thread-safe and not afraid of recursive deadlock
|
||||
|
||||
QQ群号 113767274 有什么问题或者改进的地方大家一起讨论
|
||||
|
||||
简书:不定时更新 [http://www.jianshu.com/users/376b950a20ec](http://www.jianshu.com/users/376b950a20ec/latest_articles)
|
||||
|
||||
# Big Upgrade 2.0
|
||||
|
||||
Supported __NSArray__,__NSDictionary__, __ModelClass__, __NSNumber__, __NSString__, __NSDate__, __NSData__, __UIColor__, __UIImage__, __CGRect__, __CGPoint__, __CGSize__, __NSRange__, __int__,__char__,__float__, __double__, __long__.. attribute to insert and select automation.
|
||||
|
||||
全面支持 __NSArray__,__NSDictionary__, __ModelClass__, __NSNumber__, __NSString__, __NSDate__, __NSData__, __UIColor__, __UIImage__, __CGRect__, __CGPoint__, __CGSize__, __NSRange__, __int__,__char__,__float__, __double__, __long__.. 等属性的自动化操作(插入和查询)
|
||||
|
||||
------------------------------------
|
||||
|
||||
Requirements
|
||||
====================================
|
||||
|
||||
* iOS 4.3+
|
||||
* ARC only
|
||||
* FMDB(https://github.com/ccgus/fmdb)
|
||||
|
||||
## Adding to your project
|
||||
|
||||
If you are using CocoaPods, then, just add this line to your PodFile<br>
|
||||
|
||||
```objective-c
|
||||
pod 'LKDBHelper'
|
||||
```
|
||||
|
||||
If you are using Encryption, Order can not be wrong<br>
|
||||
|
||||
```objective-c
|
||||
pod 'FMDB/SQLCipher'
|
||||
pod 'LKDBHelper'
|
||||
```
|
||||
|
||||
@property(strong,nonatomic)NSString* encryptionKey;
|
||||
|
||||
## Basic usage
|
||||
|
||||
1. Create a new Objective-C class for your data model
|
||||
|
||||
```objective-c
|
||||
@interface LKTest : NSObject
|
||||
@property(copy,nonatomic)NSString* name;
|
||||
@property NSUInteger age;
|
||||
@property BOOL isGirl;
|
||||
|
||||
@property(strong,nonatomic)LKTestForeign* address;
|
||||
@property(strong,nonatomic)NSArray* blah;
|
||||
@property(strong,nonatomic)NSDictionary* hoho;
|
||||
|
||||
@property char like;
|
||||
...
|
||||
```
|
||||
2. in the *.m file, overwirte getTableName function (option)
|
||||
|
||||
```objective-c
|
||||
+(NSString *)getTableName
|
||||
{
|
||||
return @"LKTestTable";
|
||||
}
|
||||
```
|
||||
3. in the *.m file, overwirte callback function (option)
|
||||
|
||||
```objective-c
|
||||
@interface NSObject(LKDBHelper_Delegate)
|
||||
|
||||
+(void)dbDidCreateTable:(LKDBHelper*)helper tableName:(NSString*)tableName;
|
||||
+(void)dbDidAlterTable:(LKDBHelper*)helper tableName:(NSString*)tableName addColumns:(NSArray*)columns;
|
||||
|
||||
+(BOOL)dbWillInsert:(NSObject*)entity;
|
||||
+(void)dbDidInserted:(NSObject*)entity result:(BOOL)result;
|
||||
|
||||
+(BOOL)dbWillUpdate:(NSObject*)entity;
|
||||
+(void)dbDidUpdated:(NSObject*)entity result:(BOOL)result;
|
||||
|
||||
+(BOOL)dbWillDelete:(NSObject*)entity;
|
||||
+(void)dbDidDeleted:(NSObject*)entity result:(BOOL)result;
|
||||
|
||||
///data read finish
|
||||
+(void)dbDidSeleted:(NSObject*)entity;
|
||||
|
||||
@end
|
||||
|
||||
```
|
||||
4. Initialize your model with data and insert to database
|
||||
|
||||
```objective-c
|
||||
LKTestForeign* foreign = [[LKTestForeign alloc]init];
|
||||
foreign.address = @":asdasdasdsadasdsdas";
|
||||
foreign.postcode = 123341;
|
||||
foreign.addid = 213214;
|
||||
|
||||
//插入数据 insert table row
|
||||
LKTest* test = [[LKTest alloc]init];
|
||||
test.name = @"zhan san";
|
||||
test.age = 16;
|
||||
|
||||
//外键 foreign key
|
||||
test.address = foreign;
|
||||
test.blah = @[@"1",@"2",@"3"];
|
||||
test.blah = @[@"0",@[@1],@{@"2":@2},foreign];
|
||||
test.hoho = @{@"array":test.blah,@"foreign":foreign,@"normal":@123456,@"date":[NSDate date]};
|
||||
|
||||
//同步 插入第一条 数据 Insert the first
|
||||
[test saveToDB];
|
||||
//or
|
||||
//[globalHelper insertToDB:test];
|
||||
|
||||
```
|
||||
5. select 、 delete 、 update 、 isExists 、 rowCount ...
|
||||
|
||||
```objective-c
|
||||
select:
|
||||
|
||||
NSMutableArray* array = [LKTest searchWithWhere:nil orderBy:nil offset:0 count:100];
|
||||
for (id obj in arraySync) {
|
||||
addText(@"%@",[obj printAllPropertys]);
|
||||
}
|
||||
|
||||
delete:
|
||||
|
||||
[LKTest deleteToDB:test];
|
||||
|
||||
update:
|
||||
|
||||
test.name = "rename";
|
||||
[LKTest updateToDB:test where:nil];
|
||||
|
||||
isExists:
|
||||
|
||||
[LKTest isExistsWithModel:test];
|
||||
|
||||
rowCount:
|
||||
|
||||
[LKTest rowCountWithWhere:nil];
|
||||
|
||||
|
||||
```
|
||||
6. Description of parameters "where"
|
||||
|
||||
```objective-c
|
||||
For example:
|
||||
single: @"rowid = 1" or @{@"rowid":@1}
|
||||
|
||||
more: @"rowid = 1 and sex = 0" or @{@"rowid":@1,@"sex":@0}
|
||||
|
||||
when where is "or" type , such as @"rowid = 1 or sex = 0"
|
||||
you only use NSString
|
||||
|
||||
array: @"rowid in (1,2,3)" or @{@"rowid":@[@1,@2,@3]}
|
||||
|
||||
composite: @"rowid in (1,2,3) and sex=0 " or @{@"rowid":@[@1,@2,@3],@"sex":@0}
|
||||
|
||||
If you want to be judged , only use NSString
|
||||
For example: @"date >= '2013-04-01 00:00:00'"
|
||||
```
|
||||
|
||||
## table mapping
|
||||
|
||||
overwirte getTableMapping Function (option)
|
||||
|
||||
```objective-c
|
||||
+(NSDictionary *)getTableMapping
|
||||
{
|
||||
//return nil
|
||||
return @{@"name":LKSQLInherit,
|
||||
@"MyAge":@"age",
|
||||
@"img":LKSQLInherit,
|
||||
@"MyDate":@"date",
|
||||
@"color":LKSQLInherit,
|
||||
@"address":LKSQLUserCalculate};
|
||||
}
|
||||
```
|
||||
|
||||
## table update (option)
|
||||
|
||||
```objective-c
|
||||
+(void)dbDidAlterTable:(LKDBHelper *)helper tableName:(NSString *)tableName addColumns:(NSArray *)columns
|
||||
{
|
||||
for (int i=0; i<columns.count; i++)
|
||||
{
|
||||
LKDBProperty* p = [columns objectAtIndex:i];
|
||||
if([p.propertyName isEqualToString:@"error"])
|
||||
{
|
||||
[helper executeDB:^(FMDatabase *db) {
|
||||
NSString* sql = [NSString stringWithFormat:@"update %@ set error = name",tableName];
|
||||
[db executeUpdate:sql];
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
## set column attribute (option)
|
||||
|
||||
```objective-c
|
||||
+(void)columnAttributeWithProperty:(LKDBProperty *)property
|
||||
{
|
||||
if([property.sqlColumnName isEqualToString:@"MyAge"])
|
||||
{
|
||||
property.defaultValue = @"15";
|
||||
}
|
||||
if([property.propertyName isEqualToString:@"date"])
|
||||
{
|
||||
property.isUnique = YES;
|
||||
property.checkValue = @"MyDate > '2000-01-01 00:00:00'";
|
||||
property.length = 30;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## demo screenshot
|
||||

|
||||
<br>table test data<br>
|
||||

|
||||
<br>foreign key data<br>
|
||||

|
||||
|
||||
----------
|
||||
# Use in swift
|
||||
|
||||
Remember to override the class function `getTableName` for model.
|
||||
|
||||
Change-log
|
||||
==========
|
||||
|
||||
**Version 1.1** @ 2012-6-20
|
||||
|
||||
- automatic table mapping
|
||||
- support optional columns
|
||||
- support column attribute settings
|
||||
- you can return column content
|
||||
|
||||
**Version 1.0** @ 2013-5-19
|
||||
|
||||
- overwrite and rename LKDBHelper
|
||||
- property type support: UIColor,NSDate,UIImage,NSData,CGRect,CGSize,CGPoint,int,float,double,NSString,short,char,bool,NSInterger..
|
||||
- fix a recursive deadlock.
|
||||
- rewrite the asynchronous operation -
|
||||
- thread-safe
|
||||
- various bug modified optimize cache to improve performance
|
||||
- test and demos
|
||||
- bug fixes, speed improvements
|
||||
|
||||
**Version 0.0.1** @ 2012-10-1
|
||||
|
||||
- Initial release with LKDAOBase
|
||||
|
||||
|
||||
-------
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This code is distributed under the terms and conditions of the MIT license.
|
||||
|
||||
-------
|
||||
|
||||
Contribution guidelines
|
||||
=======
|
||||
|
||||
* if you are fixing a bug you discovered, please add also a unit test so I know how exactly to reproduce the bug before merging
|
||||
|
||||
-------
|
||||
|
||||
Contributors
|
||||
=======
|
||||
|
||||
Author: Jianghuai Li
|
||||
|
||||
Contributors: waiting for you to join
|
||||
|
||||
Reference in New Issue
Block a user