向js发送含有NSDictionary对象或NSArray对象的消息

简介: 向js发送含有NSDictionary对象或NSArray对象的消息

先把NSDictionary对象或NSArray对象转化为json字符串,然后去掉空格和换行符,然后拼接字符,调用WKWebView的evaluateJavaScript方法向js发送消息。

js调用WKWebView的注册函数通过特殊的格式发送消息:window.webkit.messageHandlers.WeipaiJSBridge.postMessage({title:’测试分享的标题’,content:’测试分享的内容’,url:’https://github.com/mayin1992‘});

WeipaiJSBridge是WKWebView注册的函数,括号里面的是发送的json字符串。

那么在WKWebView页面向js发送消息也是按照特别格式发送的:wxCallBack.chooseImage.success({“localIds”:[“yxLocalFile:\/\/9B445E4B-6559-4352-9186-69A82A3E5332\/L0\/001.PNG”,”yxLocalFile:\/\/3F0D46B1-A473-4020-9D3A-D55751D44163\/L0\/001.GIF”]});

其中wxCallBack是js里面的对象名,chooseImage其中的成员变量,success是方法名,括号中的是相应消息的json字符串,最后要以分号结束。这个相应消息字符串如何产生呢?里面有转义符号,不可能一个一个拼接吧。要说一个一个拼接那也太low了,iOS自带现成的转换函数为何不用呢?但是也不是所有都靠它,也要结合字符串拼接。你直接给js发送一个NSDictionary对象,js也解析不了,NSDictionary变量只是一个地址,js可没有这种类型,你向服务器发送不外乎是字符串(本问介绍的向服务器发送的消息中键值对json串)或数据流(如:《WKWebView采用HybridNSURLProtocol协议拦截图片等资源预加载》所介绍的图片预加载,返回给js就是图片的NSData数据流)。参照《WKWebView和js互调方法的实现》更便于理解。

我拼装转换这些消息时,走过很多弯路。要在拼装后去掉空格和换行符,这个茅坑我掉进去过。不能转换过为json字符串拼装字符串后再调用转换函数转换成json,这个茅坑我掉进去过。正确的做法是:把要转换的NSDictionary对象或NSArray等复合对象转换成json字符串,然后拼接字符串。若你的NSDictionary对象不是简单的键值对,而是值为一个非字符串对象,那么你就悲剧了,那么你只能把那个非字符串对象转换成json字符串,其它的你自己拼接去吧,当然你也可以采用把那个值设置一个特定字符串,把这个值修改过的NSDictionary对象转化为json字符串,把那个键值对象也转换为json字符串,别忘记去空格和换行符,然后把那个设置的特殊的字符串替换那个键值对象json字符串,然后去拼装字符就可以了。当然你那个键值对里若含有了你那个特殊字符串就乱套了,可以把那个特殊字符串设置长些,可以避免这种情况。同样处理NSArray复合对象问题。当然最好在设计上不要设计成这样的复合对象数据。

下面是我代码中一个把根据PHAsset对象数组,把取出的localIdentifier存入NSMutableArray类型组,把它转换成json字符串,拼装向服务器发送的消息。注释的部分是当时的部分测试代码:

-(void)chooseImageResponseWithPhotos:(NSArray<UIImage *> *)photos
                              assets:(NSArray *)assets
{

    if((photos.count == 0) || (assets.count == 0))
    {
        return;
    }
    NSMutableArray *localIds = [NSMutableArray array];
    for(NSUInteger i = 0; (i < assets.count) && (i < photos.count); i++)
    {
        PHAsset *phAsset = assets[i];
        NSString *localIdentifier = phAsset.localIdentifier;
        NSString*fileName=[phAsset valueForKey:@"filename"];
        NSLog(@"File name %@",fileName);
        NSArray* arr = [fileName componentsSeparatedByString:@"."];
        NSString *fileExtend = @"";
        if(arr.count != 0)
        {
            fileExtend = [NSString stringWithFormat:@".%@", arr[arr.count - 1]];
        }
        NSString *yxLocalFile = [NSString stringWithFormat:@"yxLocalFile://%@%@", localIdentifier,fileExtend];
        [localIds addSafeObject:yxLocalFile];
//        UIImage *image = photos[i];
//        [self storageImageWithFilePath:filePath image:image];
    }
    NSLog(@"localIds :%@", localIds);
    NSString *localIdsString = [localIds getJsonString];
    NSLog(@"localIdsString :%@", localIdsString);
//    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
//    [dic setSafeObject:localIds forKey:@"localIds"];
//    NSString *jsonString = [dic getJsonString];
//    NSLog(@"jsonString :%@", jsonString);

    NSString *callBackStr = @"";
//    callBackStr = @"{\"localIds\":\"[\"yxLocalFile:/var/mobile/Containers/Data/Application/5F229EFD-CABA-46C7-A292-6ED0D6863220/Documents/chooseImageDir/b63745ef93585a46aa22e270f8af285b.png\"]\"}";
//    callBackStr = [NSString stringWithFormat:@"wxCallBack.chooseImage.success(%@);", callBackStr];
    if(isEmptyString(localIdsString))
    {
        callBackStr = @"wxCallBack.chooseImage.fail();";
    }
    else
    {
//        callBackStr = [NSString stringWithFormat:@"wxCallBack.chooseImage.success(%@)};", jsonString];
    callBackStr = [NSString stringWithFormat:@"wxCallBack.chooseImage.success({\"localIds\":%@});", localIdsString];

//    callBackStr = [NSString stringWithFormat:@"wxCallBack.chooseImage.success({\"localIds\":[\"yxLocalFile:\/\/5B85924B-E238-4173-A084-CAC3E023BA12\/L0\/001\"]});"];

//    callBackStr = [NSString stringWithFormat:@"wxCallBack.chooseImage.success({\"localIds\":[\"yxLocalFile://5B85924B-E238-4173-A084-CAC3E023BA12/L0/001\"]});"];
    }
    NSLog(@"callBackStr :%@", callBackStr);

    [self callBackWithCallBackStr:callBackStr];
}

NSArray扩展类处理转换json字符串,根据下标安全获取数组元素的完成代码:

NSArray+SafeCheck.h文件

//  NSArray+SafeCheck.h
#import <Foundation/Foundation.h>

@interface NSArray (SafeCheck)

- (id)objectAtSafeIndex:(NSUInteger)index;

-(NSString *)getJsonString;
@end

NSArray+SafeCheck.m文件

//  NSArray+SafeCheck.m
#import "NSArray+SafeCheck.h"

@implementation NSArray (SafeCheck)

- (id)objectAtSafeIndex:(NSUInteger)index
{
    if (index >= self.count) {
        return nil;
    }
    return [self objectAtIndex:index];
}

-(NSString *)getJsonString
{
    NSError *error;
    NSData *infoData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&error];
    NSString *infoString = @"";
    if (infoData) {
        infoString = [[NSString alloc] initWithData:infoData encoding:NSUTF8StringEncoding];
        infoString = [infoString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

        infoString = [infoString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        infoString = [infoString stringByReplacingOccurrencesOfString:@" " withString:@""];
    }
    return infoString;
}

@end

NSDictionary扩展类处理转换json字符串,根据key安全获取value的完成代码:

NSDictionary+SafeCheck.h文件

//NSDictionary+SafeCheck.h
#import <Foundation/Foundation.h>

@interface NSDictionary (SafeCheck)

- (id)safeObjectForKey:(NSString *)aKey;

- (NSString *)jsonString;
-(NSString *)getJsonString;

- (BOOL)containKey:(NSString *)key;

- (NSDictionary *)deepCopy;


@end

NSDictionary+SafeCheck.m文件

//  NSDictionary+SafeCheck.m
#import "NSDictionary+SafeCheck.h"

@implementation NSDictionary (SafeCheck)

- (id)safeObjectForKey:(NSString *)aKey
{
    if (![self containKey:aKey]) {
        return nil;
    }
    return [self objectForKey:aKey];
}

- (NSString *)jsonString
{
    NSData *data = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:nil];
    return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
}

- (BOOL)containKey:(NSString *)key
{
    return [[self allKeys] containsObject:key];
}

- (NSDictionary *)deepCopy
{
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self];
    return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}

-(NSString *)getJsonString
{
    NSError *error;
    NSData *infoData = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:&error];
    NSString *infoString = @"";
    if (infoData) {
        infoString = [[NSString alloc] initWithData:infoData encoding:NSUTF8StringEncoding];
        infoString = [infoString stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

        infoString = [infoString stringByReplacingOccurrencesOfString:@"\n" withString:@""];
        infoString = [infoString stringByReplacingOccurrencesOfString:@" " withString:@""];
    }
    return infoString;
}

@end
目录
相关文章
|
3月前
|
JavaScript 前端开发
JavaScript Date(日期) 对象
JavaScript Date(日期) 对象
53 2
|
2月前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
2月前
|
Web App开发 JavaScript 前端开发
如何确保 Math 对象的方法在不同的 JavaScript 环境中具有一致的精度?
【10月更文挑战第29天】通过遵循标准和最佳实践、采用固定精度计算、进行全面的测试与验证、避免隐式类型转换以及持续关注和更新等方法,可以在很大程度上确保Math对象的方法在不同的JavaScript环境中具有一致的精度,从而提高代码的可靠性和可移植性。
|
2月前
|
JSON 前端开发 JavaScript
JavaScript中对象的数据拷贝
本文介绍了JavaScript中对象数据拷贝的问题及解决方案。作者首先解释了对象赋值时地址共享导致的值同步变化现象,随后提供了五种解决方法:手动复制、`Object.assign`、扩展运算符、`JSON.stringify`与`JSON.parse`组合以及自定义深拷贝函数。每种方法都有其适用场景和局限性,文章最后鼓励读者关注作者以获取更多前端知识分享。
26 1
JavaScript中对象的数据拷贝
|
2月前
|
JavaScript 前端开发 图形学
JavaScript 中 Math 对象常用方法
【10月更文挑战第29天】JavaScript中的Math对象提供了丰富多样的数学方法,涵盖了基本数学运算、幂运算、开方、随机数生成、极值获取以及三角函数等多个方面,为各种数学相关的计算和处理提供了强大的支持,是JavaScript编程中不可或缺的一部分。
|
3月前
|
存储 JavaScript 前端开发
JavaScript 对象的概念
JavaScript 对象的概念
49 4
|
3月前
|
缓存 JavaScript 前端开发
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
JavaScript中数组、对象等循环遍历的常用方法介绍(二)
52 1
|
3月前
|
存储 JavaScript 前端开发
js中函数、方法、对象的区别
js中函数、方法、对象的区别
25 2
|
3月前
|
JavaScript 前端开发 Unix
Node.js 全局对象
10月更文挑战第5天
42 2
|
3月前
|
存储 JavaScript 前端开发
js中的对象
js中的对象
26 3