首页 > 趣闻 > 正文内容

WKWebView高效传参指南:JS调用原生传对象 数组的解决方案

趣闻2025-05-27 22:41:37

有没有遇到过这种情况?你在JS里辛辛苦苦组装了一个用户数据对象,想传给iOS原生代码处理,结果iOS那边死活收不到参数,或者收到一堆乱码。更气人的是,网上搜到的方法要么只教传字符串,要么代码写着写着就崩溃了——特别是新手如何快速涨粉这种热门话题下,居然还有人推荐用已经淘汰的UIWebView!今天咱们就来撕开这个技术黑洞,手把手教你怎么用WKWebView安全高效地传递对象和数组。


为什么要用WKWebView传参?

老有人问:“UIWebView用得好好的,为啥非要换WKWebView?”这么说吧,UIWebView就像个老式收音机,只能接收简单的信号,而WKWebView是智能音箱。举个例子:你用JS传个包含日期、地理位置的对象给UIWebView,大概率会丢失数据类型,但WKWebView能精准保留数据结构。更重要的是,??WKWebView的内存占用比UIWebView少60%??,这对手机应用来说就是生死线。


基础传参踩坑实录

刚开始学的时候,你是不是这样写的JS代码?

javascript复制
// 错误示范!
window.webkit.messageHandlers.myHandler.postMessage({name: "张三", age: 25});

然后在iOS端用message.body直接取字典?结果一运行就报类型错误。这是因为WKWebView的postMessage??不能直接传JS对象??,得先转成JSON字符串:

javascript复制
// 正确姿势
const userInfo = JSON.stringify({name: "张三", age: 25});
window.webkit.messageHandlers.myHandler.postMessage(userInfo);

iOS端要这么接:

swift复制
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if let jsonString = message.body as? String,
       let data = jsonString.data(using: .utf8),
       let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any] {
        print("收到用户信息:\(dict["name"] ?? "")")
    }
}

数组传递的死亡陷阱

传单个对象还算简单,传数组才是真坑王。很多新手会犯这两个致命错误:

  1. 忘记给数组元素统一数据类型(比如混用字符串和数字)
  2. 直接传递多维数组不做特殊处理

来看个真实案例:JS要传一个商品规格数组

javascript复制
// 错误写法导致iOS崩溃
const specs = [
    {color: "红色", stock: 100},
    {color: "蓝色", stock: 80}
];
window.webkit.messageHandlers.specHandler.postMessage(JSON.stringify(specs));

iOS端必须用NSArray接,而且每个元素要转成字典:

swift复制
if let jsonString = message.body as? String,
   let data = jsonString.data(using: .utf8),
   let array = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] {
    for spec in array {
        print("颜色:\(spec["color"] ?? "") 库存:\(spec["stock"] ?? 0)")
    }
}

特殊数据类型抢救方案

日期、二进制文件这些妖魔鬼怪怎么传?记住三大法则:

  1. ??日期统一转时间戳??(JS用Date.now(),iOS用Date(timeIntervalSince1970:))
  2. ??图片先转Base64??(iOS端用UIImage(data: Data)解码)
  3. ??循环引用对象要斩断??(用JSON.stringify的replacer参数过滤)

比如传用户头像+注册时间:

javascript复制
// JS端处理
const userData = {
    avatar: canvas.toDataURL("image/png"), // Base64编码
    registerTime: new Date().getTime()     // 时间戳
};
window.webkit.messageHandlers.avatarHandler.postMessage(JSON.stringify(userData));

iOS端解码:

swift复制
if let dict = parseJSON(message.body) {
    let avatarData = Data(base64Encoded: dict["avatar"]?.split(separator: ",").last ?? "")
    let registerDate = Date(timeIntervalSince1970: dict["registerTime"] as? TimeInterval ?? 0)
}

灵魂拷问环节

??Q:为什么我按教程写了代码还是收不到参数???
A:检查三处死穴:

  1. WKWebViewConfiguration是否注册了消息处理器(addScriptMessageHandler)
  2. JS里的handlerName是否和iOS端注册的名字完全一致(区分大小写!)
  3. 网页是否完全加载完成再调postMessage(建议在window.onload里执行)

??Q:传参过程中最容易被忽略的安全问题是什么???
A:90%的开发者会忘记做这两件事:

  • 在iOS端校验JSON格式(防止注入攻击)
  • 在JS端过滤undefined值(会导致JSON.parse失败)

加固后的代码应该长这样:

javascript复制
// JS安全写法
function safeStringify(obj) {
    return JSON.stringify(obj, (key, value) => {
        return value === undefined ? null : value;
    });
}
swift复制
// iOS安全解析
func safeParse(_ jsonString: String) -> [String: Any]? {
    guard let data = jsonString.data(using: .utf8),
          let dict = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
          dict.keys.contains("requiredKey") else {
        return nil
    }
    return dict
}

小编观点

别再相信那些过时的UIWebView教程了,苹果早就在iOS 12把它判了死刑。WKWebView才是混合开发的未来,特别是处理复杂数据传参时,就像给你的App装上了高速公路ETC——又快又稳。新手记住这个口诀:??对象先转JSON,数组元素要统一,特殊类型转文本,安全校验不能弃??。按照这个思路走,保你三天内打通JS和原生的任督二脉!

搜索