Quantcast
Channel: Xamarin.Forms — Xamarin Community Forums
Viewing all articles
Browse latest Browse all 91519

WebView HTML or Javascript limitations?

$
0
0

Hi all,

I have a custom renderer for my webview with a custom webview delegate in ios.

My Problem is, that I often got the NSError "0" - "The operation couldn’t be completed. (Invalid .ctor used error 0.)"

I spend a lot of time in debugging, but I'am not able to solve it.
I know, I got the error if there are much HTML and Javascript.

In my Example: Article Lists up to 60 articles per page -> Error
Articles up to 10 per page -> Success.

Problem is: Not all javascript will execute, if I got the error. All HTML is available. So it should be a javascript problem? Any Javascript limitation?

I got the error via: UIWebViewDelegate -> LoadFailed(UIWebView webView, NSError error)

Does anybody have a solution or idea?

public class ExtendedWebViewDelegate : UIWebViewDelegate
{
    protected ExtendedWebViewRenderer extendedWebViewRenderer;

    protected ExtendedWebView extendedWebView;

    public ExtendedWebViewDelegate(ExtendedWebViewRenderer renderer, ExtendedWebView extendedWebView) {
        this.extendedWebViewRenderer = renderer;
        this.extendedWebView = extendedWebView;
    }

    /// <summary>
    /// Shoulds the start load and send headers to shop and check for custom requests
    /// </summary>
    /// <returns><c>true</c>, if start load was shoulded, <c>false</c> otherwise.</returns>
    /// <param name="webView">Web view.</param>
    /// <param name="request">Request.</param>
    /// <param name="navigationType">Navigation type.</param>
    public override bool ShouldStartLoad(UIWebView webView, NSUrlRequest request, UIWebViewNavigationType navigationType)
    {

        //return false to cancle the request, if custom request execute successfull
        if (this.HandleCustomWebRequests(request, navigationType) == true) {
            return false;
        }

        //fire tc custom event fpr load start
        this.extendedWebView.OnStartLoading(this, new System.EventArgs());

        // Set cookies here
        var cookieJar = NSHttpCookieStorage.SharedStorage;
        cookieJar.AcceptPolicy = NSHttpCookieAcceptPolicy.Always;

        //set up the new cookies
        var jCookies = extendedWebView.Cookies.GetCookies(request.Url);
        IList<NSHttpCookie> eCookies =
            (from object jCookie in jCookies
             where jCookie != null
             select (Cookie)jCookie
             into netCookie
             select new NSHttpCookie(netCookie)).ToList();

        //sets the new cookies to the storage
        NSHttpCookieStorage.SharedStorage.SetCookies(eCookies.ToArray(), request.Url, request.Url);

        //adds the needed headers for a app call, if not set
        if (request.Headers.ContainsKey(new NSString("TC-APP-Request")) == false)
        {
            var copy = request.MutableCopy() as NSMutableUrlRequest;
            copy.TimeoutInterval = 50;

            if (copy.Headers == null)
            {
                copy.Headers = new NSMutableDictionary();
            }
            NSMutableDictionary dic = new NSMutableDictionary();

            //var geoLocator = new GeoLocation();
            //string position = geoLocator.GetPositionString();

            int SystemVersion = Convert.ToInt16(UIDevice.CurrentDevice.SystemVersion.Split('.')[0]);
            dic.Add(new NSString("TC-APP-Request"), new NSString("true"));
            //dic.Add(new NSString("TC-APP-GeoData"), new NSString(position));
            dic.Add(new NSString("TC-APP-OS-Name"), new NSString("iOS"));
            dic.Add(new NSString("TC-APP-OS-Version"), new NSString(SystemVersion.ToString()));

            copy.Headers = dic;
            copy.CachePolicy = NSUrlRequestCachePolicy.UseProtocolCachePolicy;

            request = copy;

            webView.LoadRequest(request);

            return false;
        }

        return true;
    }

    /// <summary>
    /// gives header to event if load finished
    /// </summary>
    /// <param name="webView">Web view.</param>
    public override void LoadingFinished(UIWebView webView)
    {
        //fire tc custom event
        var responseHeaders = GetResponseHeader(webView);
        this.extendedWebView.OnFinishedLoading(this, new TC.Events.EventArgs.WebViewFinishedLoadingEventArgs(responseHeaders));

        return;
    }

    /// <summary>
    /// Gets the response header.
    /// </summary>
    /// <returns>The response header.</returns>
    /// <param name="webView">Web view.</param>
    protected Dictionary<string, String> GetResponseHeader(UIWebView webView) {
        var headers = new NSDictionary();

        try
        {
            var cache = NSUrlCache.SharedCache.CachedResponseForRequest(webView.Request);
            var response = (NSHttpUrlResponse)cache.Response;

            headers = response.AllHeaderFields;
        } catch (NullReferenceException exception) {
            var nsError = new NSError();
            this.LoadFailed(webView, nsError);

            Console.WriteLine(exception.ToString());
            return new Dictionary<string, String>();
        } catch (System.Exception e) {
            Console.WriteLine(e.ToString());
            return new Dictionary<string, String>();
        }

        Dictionary<string, String> convertedHeaders = new Dictionary<string, String>();
        foreach (KeyValuePair<NSObject, NSObject> header in headers)
        {
            convertedHeaders.Add(header.Key.ToString(), header.Value.ToString());
        }

        return convertedHeaders;
    }

    /// <summary>
    /// Loads the failed.
    /// </summary>
    /// <param name="webView">Web view.</param>
    /// <param name="error">Error.</param>
    public override void LoadFailed(UIWebView webView, NSError error)
    {
        if (error.Code == -999) {
            return;
        }

        if (error.Code == 0) {
            return;
        }
        //fire tc custom event
        this.extendedWebView.OnFailedLoading(this, new System.EventArgs());

    }

    /// <summary>
    /// Handles the custom web requests (like: app://myFunction?test=test&test1=test). Return false, if request is no custom request or true, if the custom request executeded successfull
    /// </summary>
    /// <returns><c>true</c>, if custom web requests was handled, <c>false</c> otherwise.</returns>
    /// <param name="request">Request.</param>
    /// <param name="navigationType">Navigation type.</param>
    protected bool HandleCustomWebRequests(NSUrlRequest request, UIWebViewNavigationType navigationType) {
        //check for other navigation types
        if (navigationType == UIWebViewNavigationType.Other)
        {
            string scheme = request.Url.Scheme; //like app

            //if scheme is app, handle the request!
            if (scheme == "app")
            {
                string webParams = request.Url.Query; //like test=tst&test2=232
                string javascriptFunction = request.Url.Host; //like myFunction

                string[] paramPairs = webParams.Split('&');

                Dictionary<string, string> convertedParams = new Dictionary<string, string>();

                foreach (string pair in paramPairs)
                {
                    string[] elements = pair.Split('=');

                    if (elements.Length == 2)
                    {
                        if (convertedParams.ContainsKey(elements[0]))
                        {
                            convertedParams[elements[0]] = elements[1];
                        }
                        else
                        {
                            convertedParams.Add(elements[0], elements[1]);
                        }
                    }
                }

                var executeableObject = (TC.Core.JavascriptInvoker)TC.Core.Base.GetInstance("TC.Custom.iOS.JavascriptInvokers." + javascriptFunction);

                if (executeableObject == null) {
                    throw new TC.Exception.JavascriptInvokeException("JAVASCRIPT_FUNCTION_INVALID", javascriptFunction, convertedParams);
                }

                executeableObject.Initialize(javascriptFunction, convertedParams);

                executeableObject.RunAsync();

                return true;
            }
        }

        return false;
    }
}

Error Object:


Viewing all articles
Browse latest Browse all 91519

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>