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