先把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