From eb2f38c07f37fac0cf2d43987a7fcfa9a4761bb8 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Tue, 16 Nov 2021 17:36:27 +0100 Subject: [PATCH 1/3] Revert "Fix hangs and NREs with Entry Observer (#14859)" This reverts commit 5188c4fe0a1d045c9353c6243e1bdf7905337bd6. --- .../Renderers/EntryRenderer.cs | 27 +++++++++---------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs index c4295e3c170..460f66d38ea 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs @@ -39,8 +39,8 @@ public abstract class EntryRendererBase : ViewRenderer e) textField.ShouldChangeCharacters += ShouldChangeCharacters; _selectedTextRangeObserver = textField.AddObserver("selectedTextRange", NSKeyValueObservingOptions.New, UpdateCursorFromControl); - ClearButton?.Layer.AddObserver(this, new NSString("sublayers"), NSKeyValueObservingOptions.New, IntPtr.Zero); - _observedSublayers = true; + _clearButtonSublayerObserver = ClearButton?.Layer.AddObserver(new NSString("sublayers"), NSKeyValueObservingOptions.New, UpdateClearButtonSublayer); } // When we set the control text, it triggers the UpdateCursorFromControl event, which updates CursorPosition and SelectionLength; @@ -166,12 +160,6 @@ protected override void OnElementChanged(ElementChangedEventArgs e) UpdateClearButtonVisibility(); } - public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context) - { - if (keyPath == new NSString("sublayers") && _defaultClearImage == null) - UpdateClearButtonVisibility(); - } - protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == Entry.PlaceholderProperty.PropertyName || e.PropertyName == Entry.PlaceholderColorProperty.PropertyName) @@ -446,6 +434,15 @@ void UpdateCursorFromControl(NSObservedChange obj) } } + void UpdateClearButtonSublayer(NSObservedChange obj) + { + if (Control == null || Element == null) + return; + + if (_defaultClearImage == null) + UpdateClearButtonVisibility(); + } + void UpdateCursorSelection() { if (_nativeSelectionIsUpdating || Control == null || Element == null) From 1816bdfe67d6929dd219f02d4ec7f31110cdecfa Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Tue, 16 Nov 2021 17:36:40 +0100 Subject: [PATCH 2/3] Revert "Refactor observer lifecycle (#14828)" This reverts commit f95f671c416a4dc46da1f0783b5cda96d33b85fc. --- .../Renderers/EntryRenderer.cs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs index 460f66d38ea..069d994aff0 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs @@ -40,7 +40,6 @@ public abstract class EntryRendererBase : ViewRenderer e) textField.ShouldChangeCharacters += ShouldChangeCharacters; _selectedTextRangeObserver = textField.AddObserver("selectedTextRange", NSKeyValueObservingOptions.New, UpdateCursorFromControl); - _clearButtonSublayerObserver = ClearButton?.Layer.AddObserver(new NSString("sublayers"), NSKeyValueObservingOptions.New, UpdateClearButtonSublayer); + ClearButton?.Layer.AddObserver(this, new NSString("sublayers"), NSKeyValueObservingOptions.New, IntPtr.Zero); } // When we set the control text, it triggers the UpdateCursorFromControl event, which updates CursorPosition and SelectionLength; @@ -160,6 +160,12 @@ protected override void OnElementChanged(ElementChangedEventArgs e) UpdateClearButtonVisibility(); } + public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context) + { + if (keyPath == new NSString("sublayers") && _defaultClearImage == null) + UpdateClearButtonVisibility(); + } + protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == Entry.PlaceholderProperty.PropertyName || e.PropertyName == Entry.PlaceholderColorProperty.PropertyName) @@ -434,15 +440,6 @@ void UpdateCursorFromControl(NSObservedChange obj) } } - void UpdateClearButtonSublayer(NSObservedChange obj) - { - if (Control == null || Element == null) - return; - - if (_defaultClearImage == null) - UpdateClearButtonVisibility(); - } - void UpdateCursorSelection() { if (_nativeSelectionIsUpdating || Control == null || Element == null) From 782318ab96694a30c7423833da6d961f180a92d7 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Tue, 16 Nov 2021 17:36:50 +0100 Subject: [PATCH 3/3] Revert "Fix crashing on iOS < 14 if ClearButtonVisibility = WhileEditing in Entry (#14479 #14510) (#14526)" This reverts commit a21b36a016dec5bc0425bc3d9a0264894dd004cc. --- .../Renderers/EntryRenderer.cs | 40 ++++++++----------- 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs b/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs index 069d994aff0..9e30571c226 100644 --- a/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs +++ b/Xamarin.Forms.Platform.iOS/Renderers/EntryRenderer.cs @@ -7,6 +7,7 @@ using UIKit; using Xamarin.Forms.PlatformConfiguration.iOSSpecific; using Specifics = Xamarin.Forms.PlatformConfiguration.iOSSpecific.Entry; +using RectangleF = CoreGraphics.CGRect; namespace Xamarin.Forms.Platform.iOS { @@ -50,8 +51,6 @@ public abstract class EntryRendererBase : ViewRenderer Control?.ValueForKey(new NSString("clearButton")) as UIButton; - public EntryRendererBase() { } @@ -92,8 +91,6 @@ protected override void Dispose(bool disposing) Control.EditingDidEnd -= OnEditingEnded; Control.ShouldChangeCharacters -= ShouldChangeCharacters; _selectedTextRangeObserver?.Dispose(); - - ClearButton?.Layer?.RemoveObserver(this, new NSString("sublayers")); } } @@ -127,8 +124,6 @@ protected override void OnElementChanged(ElementChangedEventArgs e) textField.EditingDidEnd += OnEditingEnded; textField.ShouldChangeCharacters += ShouldChangeCharacters; _selectedTextRangeObserver = textField.AddObserver("selectedTextRange", NSKeyValueObservingOptions.New, UpdateCursorFromControl); - - ClearButton?.Layer.AddObserver(this, new NSString("sublayers"), NSKeyValueObservingOptions.New, IntPtr.Zero); } // When we set the control text, it triggers the UpdateCursorFromControl event, which updates CursorPosition and SelectionLength; @@ -160,12 +155,6 @@ protected override void OnElementChanged(ElementChangedEventArgs e) UpdateClearButtonVisibility(); } - public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context) - { - if (keyPath == new NSString("sublayers") && _defaultClearImage == null) - UpdateClearButtonVisibility(); - } - protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == Entry.PlaceholderProperty.PropertyName || e.PropertyName == Entry.PlaceholderColorProperty.PropertyName) @@ -576,33 +565,36 @@ void UpdateClearButtonVisibility() void UpdateClearButtonColor() { - if (ClearButton != null) + if (Control.ValueForKey(new NSString("clearButton")) is UIButton clearButton) { - ClearButton.TintColor = Element.TextColor.ToUIColor(); - - if(_defaultClearImage == null) - _defaultClearImage = ClearButton.ImageForState(UIControlState.Highlighted); + clearButton.TintColor = Element.TextColor.ToUIColor(); - if (_defaultClearImage == null) - return; + if(_defaultClearImage == null) + _defaultClearImage = clearButton.ImageForState(UIControlState.Highlighted); - if(Element.TextColor == Color.Default) + if (Element.TextColor == Color.Default) { - ClearButton.SetImage(_defaultClearImage, UIControlState.Normal); - ClearButton.SetImage(_defaultClearImage, UIControlState.Highlighted); + clearButton.SetImage(_defaultClearImage, UIControlState.Normal); + clearButton.SetImage(_defaultClearImage, UIControlState.Highlighted); } else { var tintedClearImage = GetClearButtonTintImage(_defaultClearImage, Element.TextColor.ToUIColor()); - ClearButton.SetImage(tintedClearImage, UIControlState.Normal); - ClearButton.SetImage(tintedClearImage, UIControlState.Highlighted); + if (tintedClearImage != null) + { + clearButton.SetImage(tintedClearImage, UIControlState.Normal); + clearButton.SetImage(tintedClearImage, UIControlState.Highlighted); + } } } } UIImage GetClearButtonTintImage(UIImage image, UIColor color) { + if (image == null) + return null; + var size = image.Size; UIGraphics.BeginImageContextWithOptions(size, false, UIScreen.MainScreen.Scale);