NJCS-数据模型

一个对象在JS和OC之间传递的时候会有个对应的类型转换,在JSValue.h源码中有个简单的介绍:

@textblock
   Objective-C type  |   JavaScript type
 --------------------+---------------------
         nil         |     undefined
        NSNull       |        null
       NSString      |       string
       NSNumber      |   number, boolean
     NSDictionary    |   Object object
       NSArray       |    Array object
        NSDate       |     Date object
       NSBlock (1)   |   Function object (1)
          id (2)     |   Wrapper object (2)
        Class (3)    | Constructor object (3)
@/textblock
这里重点提一下OC 的 id类型到JS环境后会是Wrapper object,在IOS7 及以下的系统中这个Wrapper object在被访问的时候会引起崩溃异常,这个坑很深,困扰了好几天才想到比较好的解决办法,将id类型封装到NSDictionary内部返回的,详细的情况在[原理部分]()会进行介绍。Native的方法在被执行的时候参数来源有两种,第一种:从OC传给JS,再从JS回传给OC,这种参数是不需要进行类型转换可以直接使用的;第二种:直接在JS生成,简单的类型如:Array、Dictionary、Data会在传递过程中自动转换,复杂的类型:如 CGRect、UIColor以及自定义的数据类型是无法自动转换的就需要手动封装。 1:现有的数据类型封装 CGRect CGPoint CGSize UIColor UIFont …… 2:如何封装数据 JS生成自定义对象都是Dictionary的实例,其中有个className字段代表到OC中想要被转换成的类型,JS的封装如下:
var NJCSCGPoint_JS = {
create:function(x, y){
    var CGPoint = NJCSStruct_JS.create("{CGPoint=dd}");
    CGPoint.x = x;
    CGPoint.y = y;

    return CGPoint;
}
}

var NJCSCGSize_JS = {
create:function(width, height){
    var CGSize = NJCSStruct_JS.create("{CGSize=dd}");
    CGSize.width = width;
    CGSize.height = height;

    return CGSize;
}
}

var NJCSCGRect = {
create:function(x, y, width, height){
    var CGRect = NJCSStruct_JS.create("{CGRect={CGPoint=dd}{CGSize=dd}}");
    CGRect.x = x;
    CGRect.y = y;
    CGRect.width = width;
    CGRect.height = height;
    return CGRect;
}
}
与之对应的OC封装如下,以UIFont为例: 模型转换协议:
#import 

@protocol NJCSModelTypeAdapterProtocol 

- (id)OCModel2JSModel:(id)ocModel;
- (id)JSModel2OCModel:(id)jsModel;

@end

.h文件:

#import 
#import "NJCSModelTypeAdapterProtocol.h"

@interface UIFontModelAdapter : NSObject 

@end

.m文件:

#import "UIFontModelAdapter.h"
#import 

@implementation UIFontModelAdapter

- (id)OCModel2JSModelWith:(void *)value
{
    UIFont *font = (__bridge UIFont *)value;
    UIFontDescriptor *fontDes = font.fontDescriptor;
    NSNumber *fontSize = [fontDes objectForKey:@"NSFontSizeAttribute"];
    NSString *fontName = [fontDes objectForKey:@"NSFontNameAttribute"];

    return @{@"fontSize":fontSize, @"fontName":fontName};
}

- (id)OCModel2JSModel:(id)ocModel
{
    UIFont *font = (UIFont *)ocModel;
    NSNumber *fontSize = [NSNumber numberWithFloat:[font pointSize]];
    return fontSize;
}

- (id)JSModel2OCModel:(id)jsModel
{
    NSParameterAssert(jsModel);
    float fontSize = 12.0f;
    if ([jsModel isKindOfClass:[NSDictionary class]]) {
        NSNumber *fontSizeNumber = [jsModel objectForKey:@"fontSize"];
        fontSize = [fontSizeNumber floatValue];

        NSString *fontName = [jsModel objectForKey:@"fontName"];
        if(fontName && ![fontName isEqualToString:@""]){
            return [UIFont fontWithName:fontName size:fontSize];
        }
    }
    return [UIFont systemFontOfSize:fontSize];
}

@end

热评文章