// // NSObject+LKModel.m // LKDBHelper // // Created by upin on 13-4-15. // Copyright (c) 2013年 ljh. All rights reserved. // #import "NSObject+LKModel.h" #import "LKDBHelper.h" static char LKModelBase_Key_RowID; @implementation NSObject (LKModel) +(LKDBHelper *)getUsingLKDBHelper { 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 nil; } +(NSString *)getPrimaryKey { return nil; } +(NSArray *)getPrimaryKeyUnionArray { return nil; } +(void)columeAttributeWithProperty:(LKDBProperty *)property { //overwrite } -(void)setRowid:(int)rowid { objc_setAssociatedObject(self, &LKModelBase_Key_RowID,[NSNumber numberWithInt:rowid], OBJC_ASSOCIATION_RETAIN_NONATOMIC); } -(int)rowid { return [objc_getAssociatedObject(self, &LKModelBase_Key_RowID) intValue]; } +(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 表数据 -(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; } else if([value isKindOfClass:[NSNumber class]]) { returnValue = [value stringValue]; } else if([value isKindOfClass:[NSDate class]]) { returnValue = [LKDBUtils stringWithDate:value]; } else if([value isKindOfClass:[UIColor class]]) { UIColor* color = value; float 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* columeType = property.propertyType; if([columeType isEqualToString:@"CGRect"]) { returnValue = NSStringFromCGRect([value CGRectValue]); } else if([columeType isEqualToString:@"CGPoint"]) { returnValue = NSStringFromCGPoint([value CGPointValue]); } else if([columeType isEqualToString:@"CGSize"]) { returnValue = NSStringFromCGSize([value CGSizeValue]); } } else if([value isKindOfClass:[UIImage class]]) { long random = arc4random(); long date = [[NSDate date] timeIntervalSince1970]; NSString* filename = [NSString stringWithFormat:@"img%ld%ld",date&0xFFFFF,random&0xFFF]; NSData* datas = UIImageJPEGRepresentation(value, 1); [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; } return returnValue; } -(void)modelSetValue:(LKDBProperty *)property value:(id)value { id modelValue = value; NSString* columeType = property.propertyType; if([columeType isEqualToString:@"NSString"]) { } else if([LKSQLFloatType rangeOfString:columeType].location != NSNotFound) { modelValue = [NSNumber numberWithFloat:[value floatValue]]; } else if([LKSQLIntType rangeOfString:columeType].location != NSNotFound) { modelValue = [NSNumber numberWithFloat:[value intValue]]; } else if([columeType isEqualToString:@"NSDate"]) { NSString* datestr = value; modelValue = [LKDBUtils dateWithString:datestr]; } else if([columeType isEqualToString:@"UIColor"]) { NSString* color = value; NSArray* array = [color 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 = [UIColor colorWithRed:r green:g blue:b alpha:a]; } else if([columeType isEqualToString:@"CGRect"]) { modelValue = [NSValue valueWithCGRect:CGRectFromString(value)]; } else if([columeType isEqualToString:@"CGPoint"]) { modelValue = [NSValue valueWithCGPoint:CGPointFromString(value)]; } else if([columeType isEqualToString:@"CGSize"]) { modelValue = [NSValue valueWithCGSize:CGSizeFromString(value)]; } else if([columeType isEqualToString:@"UIImage"]) { NSString* filename = value; NSString* filepath = [self.class getDBImagePathWithName:filename]; if([LKDBUtils isFileExists:filepath]) { UIImage* img = [UIImage imageWithContentsOfFile:filepath]; modelValue = img; } else { modelValue = nil; } } else if([columeType isEqualToString:@"NSData"]) { NSString* filename = value; NSString* filepath = [self.class getDBDataPathWithName:filename]; if([LKDBUtils isFileExists:filepath]) { NSData* data = [NSData dataWithContentsOfFile:filepath]; modelValue = data; } else { modelValue = nil; } } [self setValue:modelValue forKey:property.propertyName]; } -(void)userSetValueForModel:(LKDBProperty *)property value:(id)value{} -(id)userGetValueForModel:(LKDBProperty *)property { return nil; } -(id)getPrimaryValue { NSString* primarykey = [self.class getPrimaryKey]; LKModelInfos* infos = [self.class getModelInfos]; LKDBProperty* property = [infos objectWithSqlColumeName:primarykey]; if(property && [property.type isEqualToString:LKSQLUserCalculate]) { return [self userGetValueForModel:property]; } else if(primarykey && property) { return [self modelGetValue:property]; } return nil; } #pragma mark- get model property info +(LKModelInfos *)getModelInfos { static __strong NSMutableDictionary* oncePropertyDic; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ oncePropertyDic = [[NSMutableDictionary alloc]initWithCapacity:8]; }); LKModelInfos* infos; @synchronized(self) { infos = [oncePropertyDic objectForKey:NSStringFromClass(self)]; if(infos == nil) { NSMutableArray* pronames = [NSMutableArray array]; NSMutableArray* protypes = [NSMutableArray array]; NSDictionary* keymapping = [self getTableMapping]; [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]; } } infos = [[LKModelInfos alloc]initWithKeyMapping:keymapping propertyNames:pronames propertyType:protypes primaryKeys:pkArray]; [oncePropertyDic setObject:infos forKey:NSStringFromClass(self)]; } } return infos; } +(BOOL)isContainParent { return NO; } /** * @brief 获取自身的属性 * * @param pronames 保存属性名称 * @param protypes 保存属性类型 */ + (void)getSelfPropertys:(NSMutableArray *)pronames protypes:(NSMutableArray *)protypes { unsigned int outCount, i; 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 isEqualToString:@"rowid"] || [pronames indexOfObject:propertyName] != NSNotFound) { continue; } [pronames addObject:propertyName]; NSString *propertyType = [NSString stringWithCString: property_getAttributes(property) encoding:NSUTF8StringEncoding]; /* c char i int l long s short d double f float @ id //指针 对象 ... BOOL 获取到的表示 方式是 char .... ^i 表示 int* 一般都不会用到 */ if ([propertyType hasPrefix:@"T@"]) { [protypes addObject:[propertyType substringWithRange:NSMakeRange(3, [propertyType rangeOfString:@","].location-4)]]; } else if([propertyType hasPrefix:@"T{"]) { [protypes addObject:[propertyType substringWithRange:NSMakeRange(2, [propertyType rangeOfString:@"="].location-2)]]; } else { propertyType = [propertyType lowercaseString]; if ([propertyType hasPrefix:@"ti"]) { [protypes addObject:@"int"]; } else if ([propertyType hasPrefix:@"tf"]) { [protypes addObject:@"float"]; } else if([propertyType hasPrefix:@"td"]) { [protypes addObject:@"double"]; } else if([propertyType hasPrefix:@"tl"]) { [protypes addObject:@"long"]; } else if ([propertyType hasPrefix:@"tc"]) { [protypes addObject:@"char"]; } else if([propertyType hasPrefix:@"ts"]) { [protypes addObject:@"short"]; } else { [protypes addObject:@"NSString"]; } } } free(properties); if([self isContainParent] && [self superclass] != [NSObject class]) { [[self superclass] getSelfPropertys:pronames protypes:protypes]; } } #pragma mark - log all property -(NSString*)printAllPropertys { #ifdef DEBUG NSMutableString* sb = [NSMutableString stringWithFormat:@"<%@> \n", [self class]]; unsigned int outCount, i; objc_property_t *properties = class_copyPropertyList([self class], &outCount); [sb appendFormat:@" %@ : %@ \n",@"rowid",[self valueForKey:@"rowid"]]; 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); NSLog(@"%@",sb); return sb; #else return @""; #endif } @end