| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875 |
- //
- // 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];
- }
- #pragma mark - Table Data Function 表数据
- + (NSDateFormatter *)getModelDateFormatter {
- return nil;
- }
- ///get
- - (id)modelGetValue:(LKDBProperty *)property {
- NSString * const pKey = property.propertyName;
- id const value = [self valueForKey:pKey];
- 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 = CFAbsoluteTimeGetCurrent();
- 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 = CFAbsoluteTimeGetCurrent();
- 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 pKey:pKey];
- } else if ([value isKindOfClass:[NSDictionary class]]) {
- returnValue = [self db_jsonObjectFromDictionary:value pKey:pKey];
- } else {
- returnValue = [self db_jsonObjectFromModel:value pKey:pKey];
- }
- 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 pKey:(NSString *)pKey {
- 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 pKey:pKey];
- 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 pKey:(NSString *)pKey {
- 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 pKey:pKey];
- 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 pKey:(NSString *)pKey {
- 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 pKey:pKey];
- } else if ([obj isKindOfClass:[NSDictionary class]]) {
- jsonObject = [self db_jsonObjectFromDictionary:obj pKey:pKey];
- } else {
- jsonObject = [self db_jsonObjectFromModel:obj pKey:pKey];
- }
- if (jsonObject == nil) {
- jsonObject = [obj description];
- }
- return jsonObject;
- }
- - (id)db_jsonObjectFromModel:(NSObject *)model pKey:(NSString *)pKey {
- 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不支持循环引用。Model:%@ Key:%@ Value:%@", self, pKey, model);
- }
- }
- 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 *subSQL = 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) {
- subSQL = [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 *mutableString = [NSMutableString stringWithFormat:@"select rowid,* from %@ where", tableName];
- NSArray *allKeys = pv.allKeys;
- for (NSString *key in allKeys) {
- id obj = [pv objectForKey:key];
- if (isNeedAddDot) {
- [mutableString appendString:@" and"];
- }
- [mutableString appendFormat:@" %@ = '%@'", key, obj];
- isNeedAddDot = YES;
- }
- [mutableString appendString:@" limit 1"];
- subSQL = mutableString.copy;
- }
- }
- if (subSQL.length > 0) {
- NSArray *array = [[clazz getUsingLKDBHelper] searchWithSQL:subSQL 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 {
- MOLogV(@"nil 这种设置到了 int 等基础类型中");
- }
- - (id)valueForUndefinedKey:(NSString *)key {
- MOLogV(@"你有get方法没实现,key:%@", key);
- return nil;
- }
- - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
- MOLogV(@"你有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];
- MOLogV(@"%@", 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
|