Bug 53174 - UITextField.Ended not being fired
Summary: UITextField.Ended not being fired
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: XI 10.4 (C9)
Hardware: Macintosh Mac OS
: High critical
Target Milestone: 15.1
Assignee: Sebastien Pouliot
: 53235 ()
Depends on:
Reported: 2017-03-08 23:40 UTC by brock
Modified: 2017-03-17 13:58 UTC (History)
12 users (show)

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

Test case for verification (9.74 KB, application/zip)
2017-03-15 03:47 UTC, Sebastien Pouliot
Bug 53174 Verification Logs and Output Stacktrace (866.96 KB, application/x-zip-compressed)
2017-03-17 13:56 UTC, Mohak Barokar

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 on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description brock 2017-03-08 23:40:31 UTC
# Steps to reproduce
1) Create a new single view iOS App
2) Change the ViewController.cs body to this:

		UITextField textField1;
		UITextField textField2;

		void TextField_Ended(object sender, EventArgs e)
			Console.WriteLine(sender == textField1 ? "TextField1" : "TextField2");

		protected ViewController(IntPtr handle) : base(handle)
			// Note: this .ctor should not contain any initialization logic.

		public override void ViewDidLoad()

			textField1 = new UITextField() { Frame = new CoreGraphics.CGRect(0, 20, 200, 25), BorderStyle = UITextBorderStyle.Line };
			textField1.Ended += TextField_Ended;

			textField2 = new UITextField() { Frame = new CoreGraphics.CGRect(0, 55, 200, 25), BorderStyle = UITextBorderStyle.Line };
			textField2.AddTarget((sender, e) => TextField_Ended(sender, e), UIControlEvent.EditingDidEnd);


# Expected behavior
Expect that Ended is called properly.  In the test case above, only the work around fires the Ended event.

# Actual behavior
Only textField2 fires the event

# Supplemental info (logs, images, videos)

# Test environment (full version information)
Xamarin Studio Professional
Version 6.2 (build 1821)
Installation UUID: 64f3fa95-d0c1-48f2-ae9a-dc11e6160c90
	Mono 4.8.0 (mono-4.8.0-branch/e4a3cf3) (64-bit)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 408000495


Version: 0.33.2
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

Apple Developer Tools
Xcode 8.2.1 (11766.1)
Build 8C1002

Version: (Visual Studio Professional)
Hash: 35d1ccd
Branch: cycle9
Build date: 2017-02-16 17:40:00-0500

Xamarin Inspector
Not Installed

Version: (Visual Studio Professional)

Version: (Visual Studio Professional)
Android SDK: /Users/brockbr/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		4.0.3 (API level 15)
		4.1   (API level 16)
		4.4   (API level 19)
		5.0   (API level 21)
		5.1   (API level 22)
		6.0   (API level 23)
		7.0   (API level 24)
		7.1   (API level 25)

SDK Tools Version: 25.2.5
SDK Platform Tools Version: 25.0.3
SDK Build Tools Version: 25.0.2

Java SDK: /usr
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)

Android Designer EPL code available here:

Xamarin Android Player
Version: 0.6.5
Location: /Applications/Xamarin Android Player.app

Build Information
Release ID: 602001821
Git revision: d41b6e51f3fa46a1943f2e31a778d28a7c73d069
Build date: 2017-02-17 15:18:19-05
Xamarin addins: 1363a8d943bab7700c93a97474060b6734aa7f94
Build lane: monodevelop-lion-cycle9

Operating System
Mac OS X 10.11.6
Darwin Brocks-MacBook-Pro.local 15.6.0 Darwin Kernel Version 15.6.0
    Thu Jun 23 18:25:34 PDT 2016
    root:xnu-3248.60.10~1/RELEASE_X86_64 x86_64
Comment 1 Vincent Dondain [MSFT] 2017-03-09 22:58:20 UTC
Indeed I can confirm this issue, the `Started` and `EndedWithReason` events are working just fine when `Ended` isn't

Test environment: https://gist.github.com/VincentDondain/4d65bf889dfe66bf2accfb7ad50a57f4
Comment 2 Jon Goldberger [MSFT] 2017-03-09 23:04:34 UTC
I have another customer reporting this issue. In my investigation I found that on iOS 9, Ended is fired, but on iOS 10 only EndedWithReason is fired. So not sure if this is a change in iOS 10? However I could find no apple documents indicating such. 

However "Ended" fires on iOS 10 device/sim when using Cycle 8. On Cycle 8, however, the "EndedWithReason" event was not added to the XI SDK yet. See:


but was added on Cycle 9:

Comment 4 Jon Goldberger [MSFT] 2017-03-09 23:10:41 UTC
As an additional note, On cycle 9 if you subscribe to both "Ended" and "EndedWithReason", e.g.:

>textField.Ended += TextField_Ended;
>textField.EndedWithReason += TextField_EndedWithReason

running in iOS < 10 TextField_Ended is fired, and on iOS 10 TextField_EndedWithReason is fired.
Comment 5 Vincent Dondain [MSFT] 2017-03-10 15:56:42 UTC
I can confirm what Jon said. The `Ended` event fires on iOS 10.3 with XI cycle8.

The `Ended` event also fires with XI master but only on iOS < 10...

The fact it works with cycle8 XI removes the idea of filing a radar with Apple. This needs more investigation.

However, I'm lowering the importance as using `EndedWithReason` always works and will achieve the same goal as `Ended`.
Comment 6 Nate Cook 2017-03-10 16:02:50 UTC
@Vincent Does Ended work on iOS 9? Jon Goldberger's comment indicates that EndedWithReason only works on iOS 10. Having to subscribe to both events is not a good solution.
Comment 7 brock 2017-03-10 16:03:34 UTC
Yes - When I posted it, the link I used defaulted to Private.  That's the only reason it was left that way.
Comment 8 brock 2017-03-10 16:06:31 UTC
@Vincent - If you lower the importance, the problem will be shipping customers, who already have code in production, will be hugely impacted since (1) there's no evidence of the problem during compilation and (2) it silently fails.
Comment 9 Vincent Dondain [MSFT] 2017-03-10 19:01:09 UTC
*** Bug 53235 has been marked as a duplicate of this bug. ***
Comment 10 Vincent Dondain [MSFT] 2017-03-10 19:01:56 UTC
Agreed let's put this back to blocker.
Comment 12 Vincent Dondain [MSFT] 2017-03-10 20:34:26 UTC
Ok so it would seem that internally we are listening to both `textFieldDidEndEditing:` (Ended) and `textFieldDidEndEditing:withReason:` (EndedWithReason).

I tried with Xcode and when implementing both methods of `UITextFieldDelegate`, `textFieldDidEndEditing:withReason:` when `textFieldDidEndEditing:` doesn't.

Removing the first one makes the second fire.

It would seem the addition of `EndedWithReason` with iOS 10 is what broke `Ended`, that also explains why it's working on iOS < 10 and on versions of XI that didn't ship `EndedWithReason` (like XI cycle8).

The solution seems to be the addition of manual code that overrides `RespondToSelector` like this: https://github.com/xamarin/xamarin-macios/blob/master/src/AddressBookUI/ABPeoplePickerNavigationController.cs#L69-L90

This way we don't listen to events without event handlers.
Comment 13 Vincent Dondain [MSFT] 2017-03-13 18:51:29 UTC
Decreasing the importance to critical this time after talking to Sebastien.

Blocker is internally used to mark a bug that should "block" a release, as in the bug has not yet hit stable, since this is *already* broken in stable and there's a workaround (even if not optimal) we cannot use "blocker" for this bug.

Setting the 2nd maximal priority of critical because I suppose this issue might be hit pretty frequently and it silently fails.
Comment 14 Sebastien Pouliot 2017-03-14 16:31:22 UTC
Turning any `*Delegate` into events has a few pitfalls like this one (new API can change the behaviour of old ones).

In this case I believe the right action if to have the new `textFieldDidEndEditing:withReason:` implementation call the event for `textFieldDidEndEditing:` if no event exists on the former (but one does on the later).

So the code would be like:

	[Preserve (Conditional = true)]
	[Export ("textFieldDidEndEditing:reason:")]
	public void EditingEnded (UITextField textField, UITextFieldDidEndEditingReason reason)
		EventHandler<UITextFieldEditingEndedEventArgs> handler = editingEnded1;
		if (handler != null) {
			var args = new UITextFieldEditingEndedEventArgs (reason);
			handler (textField, args);
		} else {
			EventHandler handler2 = editingEnded;
			if (handler2 != null)
				handler2 (textField, EventArgs.Empty);

and code that only listen to the old (pre iOS10) event will still get notified when running on iOS10+

The tricky part is getting that extra, custom/manual, code inside the generated code, but maybe we can switch to manual bindings until then.
Comment 15 Sebastien Pouliot 2017-03-15 03:47:28 UTC
Created attachment 20332 [details]
Test case for verification

PR master https://github.com/xamarin/xamarin-macios/pull/1875

QA: The attached test case needs to be executed on:

1. iOS 9.x (or earlier); and 
2. iOS 10.x

This can be simulators or devices. You need to go thru each field, e.g. use TAB on the simulator, to trigger the events. In both cases (iOS versions) you should see 3 PASS with a fixed build.

On iOD 9.x (or earlier) you should see:

2017-03-14 22:30:28.884 bug53174[7756:97915238] Ended: PASS (1/2)
2017-03-14 22:30:29.417 bug53174[7756:97915238] Ended: PASS (2/2)
2017-03-14 22:30:36.996 bug53174[7756:97915238] EndedWithReason: PASS (Unknown)

On iOS 10.x it will look like:

2017-03-14 22:15:50.013 bug53174[7399:97850463] Ended: PASS (1/2)
2017-03-14 22:15:50.787 bug53174[7399:97850463] Ended: PASS (2/2)
2017-03-14 22:15:54.716 bug53174[7399:97850463] EndedWithReason: PASS (Committed)

That shows that using either events will work both before and after iOS 10.
Comment 16 Nate Cook 2017-03-15 04:02:03 UTC
Dumb question: A PR to master means it would go out in Cycle 9 SR 1? I'm not sure how to interpret a target milestone of "15.1". Is there a way in general to know based on a PR in what release that would be included?
Comment 17 Sebastien Pouliot 2017-03-15 04:50:24 UTC
@Nate there's no such thing :)

Short answers:

> A PR to master means it would go out in Cycle 9 SR 1?

No it does not. Also there should not be an C9 SR1. The good news it that the next release (15.1) should come up before we would normally (before C9) released an SR1.

> Is there a way in general to know based on a PR in what release that would be included?

Yes, look at the branches where PRs are merged. In particular looks for the backports to release branches. That branch names will match with our release blog https://releases.xamarin.com

If a fix was already released (e.g. any channel, including alpha) then you can look up the bug number from the release notes.

Long answer:

The SDK is open source and you can track our next release(s) from our wiki [1]. For iOS we're presently working on `xcode8.3`, `d15-1` and `master` and you can download any of our builds for them.

As you can see 15.1 is already branched [2]. This means that any fix we do must go to master first. Once the PR has been peer reviewed and merged (in master) then QA verify/confirm the fix. This opens the door for another PR to backport the fix to a release branch (like 15.1)...

Depending when this all happens the fix might be included in 15.1. If not it should be in 15.2 (since it will branch from master where the PR should be merged) or, in exceptional cases, never (if the PR is not merged or reverted).

As for the 15.x names it's because we are aligning our releases with visual studio 2017 updates (known as dev15). 15.1 will be its first update.

[1] https://github.com/xamarin/xamarin-macios/wiki
[2] and has been released twice in the alpha channel
Comment 18 Nate Cook 2017-03-15 05:25:04 UTC
This explanation was extremely helpful in understanding your branching strategy and release process. Thank you for writing that up Sebastien.
Comment 20 Sebastien Pouliot 2017-03-15 13:20:37 UTC
PR d15-1 https://github.com/xamarin/xamarin-macios/pull/1876
Comment 21 Ivan Herrera 2017-03-15 16:53:15 UTC
Bug is not happening in build: https://bosstoragemirror.blob.core.windows.net/wrench/macios-mac-master/7f/7f6f2bf81d8280129848219957bed32c594aba59/xamarin.ios-

Output is written as expected:

2017-03-15 13:42:13.520 textfieldtest[80323:5981183] TextField1
2017-03-15 13:42:19.089 textfieldtest[80323:5981183] TextField2

Env: https://gist.github.com/anonymous/1c06932650b2d8a54a247b713dd3daff
Comment 22 Sebastien Pouliot 2017-03-15 17:02:39 UTC
@Ivan that's not the correct output. Please use the *attached* sample and instructions (from comment #15) as it cover more cases than the original instructions.
Comment 23 Ivan Herrera 2017-03-15 17:45:20 UTC
Ok. Retested it again with the provided test project. Still passes.

In iOS Simulator 10.3

2017-03-15 14:33:48.378 bug53174[81866:6252742] Ended: PASS (1/2)
2017-03-15 14:33:51.004 bug53174[81866:6252742] Ended: PASS (2/2)
2017-03-15 14:33:59.648 bug53174[81866:6252742] EndedWithReason: PASS (Committed)

In iOS Simulator 8.1

2017-03-15 14:35:49.450 bug53174[81980:6276889] Ended: PASS (1/2)
2017-03-15 14:35:50.742 bug53174[81980:6276889] Ended: PASS (2/2)
2017-03-15 14:35:56.926 bug53174[81980:6276889] EndedWithReason: PASS (Unknown)

Env: https://gist.github.com/anonymous/1c06932650b2d8a54a247b713dd3daff
Comment 24 Sebastien Pouliot 2017-03-15 20:23:00 UTC
Thanks @Ivan :)

PR for d15-1 merged in https://github.com/xamarin/xamarin-macios/commit/c27db45c47a4f49830e247bce8c91dd56ad54f86
Comment 25 Mohak Barokar 2017-03-17 13:56:21 UTC
Created attachment 20429 [details]
Bug 53174 Verification Logs and Output Stacktrace

Verified this bug on following config and found to be fixed :

=== Xamarin Studio Enterprise ===

Version 6.3 (build 834)
Installation UUID: 1556bf59-77b8-4ed6-abe9-32ef4bc21a9c
 Mono 4.8.0 (mono-4.8.0-branch/8f6d0f6) (64-bit)
 GTK+ 2.24.23 (Raleigh theme)

 Package version: 408000520

=== NuGet ===


=== Xamarin.Profiler ===

Version: 1.3.2
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Apple Developer Tools ===

Xcode 8.2.1 (11766.1)
Build 8C1002

=== Xamarin.iOS ===

Version: (Visual Studio Enterprise Trial)
Hash: f94cf26
Branch: d15-1
Build date: 2017-03-14 12:37:51-0400

=== Xamarin Inspector ===

Hash: cdc01b9
Branch: 1.1-release
Build date: Wed, 22 Feb 2017 23:24:11 GMT

=== Xamarin.Android ===

Version: (Visual Studio Enterprise Trial)
Android SDK: /Users/globallogic/Library/Developer/Xamarin/android-sdk-macosx
 Supported Android versions:
  4.4 (API level 19)
  6.0 (API level 23)
  7.1 (API level 25)

SDK Tools Version: 25.2.5
SDK Platform Tools Version: 25.0.3
SDK Build Tools Version: 25.0.1

Java SDK: /usr
java version "1.8.0_101"
Java(TM) SE Runtime Environment (build 1.8.0_101-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)

Android Designer EPL code available here:

=== Xamarin.Mac ===

Version: (Visual Studio Enterprise Trial)

=== Build Information ===

Release ID: 603000834
Git revision: bb1dff522ee38d9963b4d97f6cfa0f92c85e8ecb
Build date: 2017-03-14 13:38:37-04
Xamarin addins: 8aac7919dc66c1ce0d9d75fe150ddc1ab15fd941
Build lane: monodevelop-lion-d15-1

=== Operating System ===

Mac OS X 10.12.3
Darwin NAG1-DMAC-26706 16.4.0 Darwin Kernel Version 16.4.0
    Thu Dec 22 22:53:21 PST 2016
    root:xnu-3789.41.3~3/RELEASE_X86_64 x86_64

Attached Verification Logs and Application Output Stacktrace