Bug 51629 - ShouldInteractWithUrl not getting called on iOS 10.
Summary: ShouldInteractWithUrl not getting called on iOS 10.
Status: CONFIRMED
Alias: None
Product: iOS
Classification: Xamarin
Component: General (show other bugs)
Version: XI 10.4 (C9)
Hardware: PC Windows
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2017-01-18 23:36 UTC by ye_he
Modified: 2017-07-17 23:12 UTC (History)
9 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
A few changes to the blank Xamarin forms App template. (540.78 KB, application/x-rar)
2017-01-18 23:36 UTC, ye_he
Details
Modified TestApp (276.41 KB, application/x-zip-compressed)
2017-07-17 23:12 UTC, Ammar Mheir
Details


Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report for Bug 51629 on Developer Community or GitHub if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: Developer Community HTML or GitHub Markdown
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
CONFIRMED

Description ye_he 2017-01-18 23:36:55 UTC
Created attachment 19393 [details]
A few changes to the blank Xamarin forms App template.

I've created a blank Xamarin Forms app on Visual Studio 2016. And I added only a few things to test the 'ShouldInteractWithUrl' delegate.

1. A custom label class with empty content in the forms project.

    public class AutoHyperLinkLabel : Label
    {
    }

2. Reference this custom label in the MainPage.

    <local:AutoHyperLinkLabel Text="Welcome to Xamarin Forms! http://www.google.com"
                              VerticalOptions="Center"
                              HorizontalOptions="Center" />
3. Custom iOS view renderer.

    public class AutoHyperLinkRenderer : ViewRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<View> e)
        {
            base.OnElementChanged(e);

            var view = (AutoHyperLinkLabel) Element;
            if (view == null) return;

            UITextView uiTextView = new UITextView(new CGRect(0, 0, view.Width, view.Height))
            {
                Editable = false,
                ScrollEnabled = false,
                Selectable = true,
                UserInteractionEnabled = true,
                Text = view.Text,
                BackgroundColor = UIColor.Clear,
                DataDetectorTypes = UIDataDetectorType.All,
            };

            uiTextView.TextContainer.LineFragmentPadding = 0;
            uiTextView.TextContainerInset = new UIEdgeInsets(0, 0, 0, 0);

            uiTextView.ShouldInteractWithUrl = (arg1, url, arg3) =>
            {
                // breakpoint gets hit on iOS 9 but not on iOS 10.
                return false;
            };
            
            SetNativeControl(uiTextView);
        }
    }

The issue is the anonymous method set to ShouldInteractWithUrl not called on iOS 10.
The result is that I cannot intercept URL clicks on the UITextView on iOS 10.

It's kind of urgent, anyone has any idea?

Above behaviours are noticed on real devices:
iPhone 5S (iOS 9)
iPhone SE (iOS 10)

The project fils is in the attachment.
Comment 1 adrianknight89 2017-02-13 00:05:44 UTC
I can confirm this issue. Have you tried creating a custom View with a bindable TextProperty? You're using a Label but converting it into a UITextView on the iOS side. Now, I don't think that's the problem since you said it works for iOS 9, but if you are looking for solutions, it's one thing to check.

Also, using a named method instead of a lambda doesn't seem to fix the issue.
Comment 2 ye_he 2017-02-13 00:34:30 UTC
The workaround of this issue is to set the Delegate manually.

In the initialisation of UITextView:

Delegate = new MyTextViewDelegate(this)

Create a separate class:

        private class MyTextViewDelegate : UITextViewDelegate
        {
            private AutoHyperLinkRenderer _renderer;

            public MyTextViewDelegate(AutoHyperLinkRenderer renderer)
            {
                _renderer = renderer;
            }

            public override bool ShouldInteractWithUrl(UITextView textView, NSUrl URL, NSRange characterRange)
            {
                return _renderer.ShouldInteractWithUrl(textView, URL, characterRange);
            }
        }

Works on iOS 9 and 10.

I guess these things are doing exactly the same jobs as what `ShouldInteractWithUrl` claims to do.
Comment 3 Paul DiPietro [MSFT] 2017-02-15 19:35:47 UTC
I'm rather sure that this is a Xamarin.iOS issue. It appears to do the same thing in a Xamarin.iOS project where clicking the link will open the browser on iOS 10, but not on iOS 9.
Comment 4 Onur Hazar 2017-03-29 12:27:36 UTC
Yes, I am having the same issue on Xamarin iOS project (with the latest version of Xamarin) 

I did the workaround below;

TxtView.WeakDelegate = new MyTextViewDelegate(Owner);

public class MyTextViewDelegate : UITextViewDelegate
	{
		public UIViewController Owner { get; set; }

		public MyTextViewDelegate(UIViewController owner)
		{
			Owner = owner;
		}

		public override bool ShouldInteractWithUrl(UITextView textView, Foundation.NSUrl URL, Foundation.NSRange characterRange)
		{
			//DO SOMETHING HERE WITH URL
                        return true;
		}
	}

Downgrading to xamarin cycle 8 also works.
Comment 5 Ezra 2017-04-19 16:12:46 UTC
@yehe01@gmail.com 

Do you mind sharing your Renderer class please?  

Delegate = new MyTextViewDelegate(this) does not seem to work for me. Am I missing something in my renderer class below?

I am using Xamarin.iOS 10.8. 

public class MarkdownViewRenderer : ViewRenderer<MarkdownView, UITextView>
	{
		protected override void OnElementChanged(ElementChangedEventArgs<MarkdownView> e)
		{
			if (Control == null) {
				UITextView uiView = new UITextView()
				{
					TextAlignment = UITextAlignment.Left,
					Editable = false,
					SelectedRange = new NSRange(0, 0),
					Selectable = true,
					DataDetectorTypes = UIDataDetectorType.All,
					ScrollEnabled = false,
					Delegate = new MyTextViewDelegate(this)
				};
				uiView.Text = Element.Markdown; //this is a string of html

				SetNativeControl(uiView);

			}
		}

                bool ShouldInteractWithUrl(UITextView arg1, NSUrl arg2, NSRange arg3)
		{
	            string clickedUrl = arg2.ToString().ToLower(); //does not get called?		
                    System.Diagnostics.Debug.WriteLine("clicked url: " + clickedUrl );
			return false;
                }

private class MyTextViewDelegate : UITextViewDelegate
		{
			private MarkdownViewRenderer _renderer;

			public MyTextViewDelegate(MarkdownViewRenderer renderer)
			{
				_renderer = renderer;
			}

			public override bool ShouldInteractWithUrl(UITextView textView, NSUrl URL, NSRange characterRange)
			{
				
				return _renderer.ShouldInteractWithUrl(textView, URL, characterRange);
			}
		}
Comment 6 Andy 2017-06-23 15:07:44 UTC
It's broken Xamarin team. You need to fix it.
Comment 7 Ammar Mheir 2017-07-17 23:12:37 UTC
Created attachment 23613 [details]
Modified TestApp

Was able to replicate this issue on my end using the attached sample project in Comment 1


#Replication steps

1. Downloaded sample project attached in Comment 1
2. Set breakpoint within the ShouldInteractWithUrl
3. Ran on iOS Simulator 10.3
4. Clicked on link to google.com
5. Breakpoint not hit, ShouldInteractWithUrl not being called


#Current Workaround

As indicated in Comment 2, it seems that the current workaround is to create the delegate for the UITextView manually. I attached the sample replication project from the original comment containing the workaround, I made the modification to the TestApp.iOS/AutoHyperLinkLabel.Renderer.cs file.


#Version Information

Microsoft Visual Studio Enterprise 2015
Version 14.0.25431.01 Update 3
Microsoft .NET Framework
Version 4.7.02046
Installed Version: Enterprise

Xamarin   4.5.0.486 (fec6f88)
Xamarin.iOS   10.10.0.37 (ad35de4)


#Additional Information

Although I am not specifically sure if this might be of relevance, or if the appropriate use of ShouldInteractWithUrl would need a manually created delegate: https://stackoverflow.com/a/38170861/5957162