昨天我花了几个小时找出为什么我无法访问我的混合wkWebView的(显然是起作用的)参数。在正确启动的iOS覆盖下的DidFinishNavigation部件中,当尝试EvaluateJavaScriptAsync甚至访问NullObjectReference参数时,我总是会得到一个NullObjectReference异常。
然后,我终于发现我看错了对象:我访问的是Forms HybridWebView对象(在“chain”中向上),而不是iOS webview对象(从呈现器向下)。在下面的代码中,"webView“参数来自DidFinishNavingation,而不是webViewRenderer.Element中的_wkWebView (参见最后的代码部分)
现在,我的代码正在工作,但我仍然想知道,我对平台特定集成的总体概念是否正确,还是表单混合视图(如EvaluateJavaScript)中可用的表单函数应该直接工作?我是不是遗漏了一些链接来连接那些与底层iOS网页的链接?
我的HybidWebView共享表单代码:
public class MyWebView : WebView
{
public event EventHandler SwipeLeft;
public event EventHandler SwipeRight;
public void OnSwipeLeft() =>
SwipeLeft?.Invoke(this, null);
public void OnSwipeRight() =>
SwipeRight?.Invoke(this, null);
public static readonly BindableProperty UrlProperty = BindableProperty.Create(
propertyName: "Url",
returnType: typeof(string),
declaringType: typeof(MyWebView),
defaultValue: default(string));
public string Url
{
get { return (string)GetValue(UrlProperty); }
set
{
SetValue(UrlProperty, value);
NotifyPropertyChanged(nameof(HTML));
}
}
public static readonly BindableProperty HTMLProperty = BindableProperty.Create(
propertyName: "HTML",
returnType: typeof(string),
declaringType: typeof(MyWebView),
defaultValue: default(string));
public string HTML
{
get { return (string)GetValue(HTMLProperty); }
set
{
SetValue(HTMLProperty, value);
NotifyPropertyChanged(nameof(HTML));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}以及渲染器的连接iOS部件:
public class MyWebViewRenderer : ViewRenderer<MyWebView, WKWebView>
{
WKWebView _wkWebView;
protected override void OnElementChanged(ElementChangedEventArgs<MyWebView> e)
{
System.Console.WriteLine("--- Loading wkWebView ---");
base.OnElementChanged(e);
if (Control == null)
{
Console.WriteLine("+++ WKW: Control null -> init");
var config = new WKWebViewConfiguration();
_wkWebView = new WKWebView(Frame, config);
SetNativeControl(_wkWebView);
_wkWebView.NavigationDelegate = new ExtendedWKWebViewDelegate(this);
}
if (e.NewElement != null)
{
Console.WriteLine("+++ WKW: Control exists -> init GestureRecognizers");
UISwipeGestureRecognizer leftgestureRecognizer = new UISwipeGestureRecognizer(this, new Selector("SwipeEvent:"));
leftgestureRecognizer.Direction = UISwipeGestureRecognizerDirection.Left;
UISwipeGestureRecognizer rightgestureRecognizer = new UISwipeGestureRecognizer(this, new Selector("SwipeEvent:"));
rightgestureRecognizer.Direction = UISwipeGestureRecognizerDirection.Right;
leftgestureRecognizer.Delegate = new MyWebViewDelegate();
rightgestureRecognizer.Delegate = new MyWebViewDelegate();
this.AddGestureRecognizer(leftgestureRecognizer);
this.AddGestureRecognizer(rightgestureRecognizer);
}
NSUrl baseURL = new NSUrl(App.dirNews, true);
string viewFile = Path.Combine(App.dirNews, "view.html");
NSUrl fileURL = new NSUrl(viewFile, false);
if (Element?.HTML != null && Element?.HTML != "")
{
System.Console.WriteLine("--- Showing HTTP content ---");
File.WriteAllText(viewFile, Element.HTML, System.Text.Encoding.UTF8);
Control.LoadFileUrl(fileURL, baseURL);
}
else if (Element?.Url != null && Element?.Url != "")
{
System.Console.WriteLine("--- Loading Web page ---");
System.Console.WriteLine("--- " + Element.Url + " ---");
NSUrlRequest myRequest = new NSUrlRequest(new NSUrl(Element.Url), NSUrlRequestCachePolicy.ReloadIgnoringLocalAndRemoteCacheData, 120);
Control.LoadRequest(myRequest);
}
}最后,DidFinishLoading类中的iOS事件处理程序:
class ExtendedWKWebViewDelegate : WKNavigationDelegate
{
MyWebViewRenderer webViewRenderer;
public ExtendedWKWebViewDelegate(MyWebViewRenderer _webViewRenderer = null)
{
webViewRenderer = _webViewRenderer ?? new MyWebViewRenderer();
}
[Export("webView:didFinishNavigation:")]
public override async void DidFinishNavigation(WKWebView webView, WKNavigation navigation)
{
try
{
var _webView = webViewRenderer.Element as WebView;
if (_webView != null)
{
await System.Threading.Tasks.Task.Delay(100); // wait here till content is rendered
_webView.HeightRequest = (double)webView.ScrollView.ContentSize.Height;
//### get html from site
var myRes = await webView.EvaluateJavaScriptAsync("document.body.innerHTML");
//### Flag complete status
MessagingCenter.Send<object, string>(this, "didFinishNavigation", myRes.ToString());
}
}
catch (Exception ex)
{
//Log the Exception
Console.WriteLine("*** CustomWebView Exception: " + ex.Message + "/" + ex.InnerException);
}
}
}发布于 2020-06-19 12:16:26
当我们调用行时
SetNativeControl(_wkWebView);您在窗体中定义的WebView再次初始化。因此,您需要在自定义渲染器中实现大部分功能。特别是在WebView of iOS中,如果您想要添加侦听器的生命周期或调用某些JS方法,那么在自定义渲染器中实现它是最好的方法(或者说是唯一的方法)。
https://stackoverflow.com/questions/62465839
复制相似问题