HHuiHao / Universal-Jump-ViewController

【demo】万能动态跳转界面 - runtime
305 stars 91 forks source link

BOOL属性,crash问题 #3

Open jkqs opened 8 years ago

jkqs commented 8 years ago

问题描述:类中存在BOOL属性、iPhone5(包括5)之前的设备crash。 原因:iPhone5之后,为32bit系统,BOOL用signed char 类型表示,64bit用bool类型表示。在使用kvc的时候,系统将NSString类型转化成signed char时没有对应方法导致crash。 解决方法:可以将类中BOOL类型参数改成NSString或者NSInteger类型。 update:2016.07.13 该问题还存在于NSInteger,NSUInteger,CGFloat等,给controller赋值的时候,基于runtime自己写了个方法如下:

/**
 *  给对象赋值
 *
 *  @param obj      任意对象
 *  @param paramers 传入的参数,参数名需要和obj对象属性同名
 */
- (void)setProptyWithObject:(id)obj paramers:(NSDictionary *)paramers
{
    const char *className = object_getClassName(obj);
    id creditorDetail = objc_getClass(className);
    unsigned int outCount, i;
    objc_property_t *properties = class_copyPropertyList(creditorDetail, &outCount);
    for (NSString *parm in paramers) {
        for (i = 0; i < outCount; i++) {
            objc_property_t property = properties[i];
            NSString *propName = [NSString stringWithUTF8String:property_getName(property)];
            if ([propName isEqualToString:parm]) {
                const char *p_type_str = property_getAttributes(property);
                NSString *attrTypeStrS = [NSString stringWithUTF8String:p_type_str];
                NSArray *attrArray = [attrTypeStrS componentsSeparatedByString:@","];
                NSString *attrTypeStr = attrArray[0];
                const char *p_type = [[attrTypeStr substringFromIndex:1] UTF8String];
                if (!strcmp(p_type, @encode(BOOL))) {
                    NSNumber *number = [NSNumber numberWithBool:[((NSString *)paramers[propName])boolValue]];
                    [obj setValue:number forKey:propName];
                }
                else if (!strcmp(p_type, @encode(NSInteger)) || !strcmp(p_type, @encode(NSUInteger))) {
                    NSNumber *number = [NSNumber numberWithInteger:[((NSString *)paramers[propName])integerValue]];
                    [obj setValue:number forKey:propName];
                }
                else if ([attrTypeStrS containsSubstring:@"NSString"]) {
                    [obj setValue:paramers[propName] forKey:propName];
                }
                else if (!strcmp(p_type, @encode(double))) {
                    NSNumber *number = [NSNumber numberWithDouble:[((NSString *)paramers[propName])doubleValue]];
                    [obj setValue:number forKey:propName];
                }
                else if (!strcmp(p_type, @encode(float))) {
                    NSNumber *number = [NSNumber numberWithFloat:[((NSString *)paramers[propName])floatValue]];
                    [obj setValue:number forKey:propName];
                }
                else if ([attrTypeStrS containsSubstring:@"NSNumber"]) {
                    NSNumberFormatter *numFormat = [[NSNumberFormatter alloc] init];
                    numFormat.numberStyle = NSNumberFormatterDecimalStyle;
                    NSNumber *number = [numFormat numberFromString:(NSString *)paramers[propName]];
                    [obj setValue:number forKey:propName];
                }
                else { //目前只能处理BOOL,NSInteger,NSUInteger,CGFloat,NSString,NSNumber类型,其他类型不能处理
                    NSAssert(0, @"not support");
                }
            }
        }
    }
}