You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms WebView iOS端执行Javascript适配WKWebViewRenderer求助

适配iOS WKWebViewRenderer执行JavaScript的解决方案

我刚好处理过这个问题,iOS升级后WKWebView的EvaluateJavaScript API确实改成了异步回调模式,替代了原来同步返回结果的方式,下面是具体的适配方案,完美兼容你原来的调用逻辑:

1. 自定义WKWebView渲染器

首先替换原来的WebViewRenderer为WKWebViewRenderer,并通过TaskCompletionSource将回调式的API包装成Task,这样上层调用时可以保持和Android端一致的异步语法:

using System;
using System.Threading.Tasks;
using Foundation;
using WebKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(HybridWebView), typeof(HybridWebViewRenderer))]
namespace YouriOSProjectNamespace
{
    public class HybridWebViewRenderer : WKWebViewRenderer, IWKScriptMessageHandler
    {
        public HybridWebViewRenderer() : base(new WKWebViewConfiguration())
        {
        }

        protected override void OnElementChanged(VisualElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if (e.NewElement is HybridWebView hybridWebView)
            {
                // 这里可以添加WKWebView的额外配置,比如脚本消息监听(如果需要和JS交互的话)
            }
        }

        // 包装WKWebView的异步API为Task<string>
        public Task<string> EvaluateJavaScriptAsync(string script)
        {
            var taskCompletionSource = new TaskCompletionSource<string>();

            this.EvaluateJavaScript(script, (result, error) =>
            {
                if (error != null)
                {
                    // 将iOS原生错误包装成.NET异常
                    taskCompletionSource.SetException(new Exception(error.LocalizedDescription));
                    return;
                }

                // 处理返回结果:iOS会把JS返回值序列化为JSON格式,字符串会带双引号,需要处理
                string jsResult = result?.ToString() ?? string.Empty;
                if (!string.IsNullOrEmpty(jsResult) && jsResult.StartsWith("\"") && jsResult.EndsWith("\""))
                {
                    // 去掉首尾引号并还原转义的双引号
                    jsResult = jsResult.Substring(1, jsResult.Length - 2).Replace("\\\"", "\"");
                }

                taskCompletionSource.SetResult(jsResult);
            });

            return taskCompletionSource.Task;
        }

        // 实现IWKScriptMessageHandler接口的方法(如果需要和JS双向交互的话,否则可以忽略)
        public void DidReceiveScriptMessage(WKUserContentController userContentController, WKScriptMessage message)
        {
            // 处理JS发送过来的消息
        }
    }
}

2. 自定义Xamarin.Forms WebView类

在共享项目中定义自定义WebView,提供统一的调用方法:

using Xamarin.Forms;

public class HybridWebView : WebView
{
    /// <summary>
    /// 统一的执行JavaScript方法,跨平台调用
    /// </summary>
    public Task<string> EvaluateJavaScriptAsync(string script)
    {
        var renderer = Platform.GetRenderer(this) as HybridWebViewRenderer;
        return renderer?.EvaluateJavaScriptAsync(script) ?? Task.FromResult<string>(null);
    }
}

3. 上层调用方式

现在你可以在共享项目中像原来一样调用,保持跨平台代码一致性:

var result = await yourHybridWebView.EvaluateJavaScriptAsync("your javascript code here");

关键注意点

  • 错误处理:通过TaskCompletionSource将iOS原生的NSError转换为.NET异常,上层可以用try-catch捕获
  • 结果格式化:iOS返回的JS结果是JSON序列化后的字符串,比如JS返回"hello",iOS会返回"\"hello\"",所以需要处理掉多余的引号和转义字符
  • 渲染器注册:确保在iOS项目的AssemblyInfo.cs或者渲染器类上添加ExportRenderer特性,让Xamarin.Forms识别自定义渲染器

内容的提问来源于stack exchange,提问作者user132397

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 06:57:40