Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Updated workaround for iOS 16 UITextInput.SelectedTextRange crashes #9559

Merged
merged 5 commits into from
Aug 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions build/PackageDiffIgnore.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8903,6 +8903,12 @@
<Member
fullName="System.Void Windows.UI.Xaml.Controls.SinglelineTextBoxView::set_SelectedTextRange(UIKit.UITextRange value)"
reason="Workaround for iOS 16" />
<Member
jeromelaban marked this conversation as resolved.
Show resolved Hide resolved
fullName="UIKit.UITextRange Windows.UI.Xaml.Controls.MultilineTextBoxView::get_SelectedTextRange()"
reason="Workaround for iOS 16" />
<Member
fullName="System.Void Windows.UI.Xaml.Controls.MultilineTextBoxView::set_SelectedTextRange(UIKit.UITextRange value)"
reason="Workaround for iOS 16" />
<!-- END iOS 16 workaround -->
</Methods>
<Properties>
Expand All @@ -8919,6 +8925,9 @@
<Member
fullName="UIKit.UITextRange Windows.UI.Xaml.Controls.SinglelineTextBoxView::SelectedTextRange()"
reason="Workaround for iOS 16" />
<Member
fullName="UIKit.UITextRange Windows.UI.Xaml.Controls.MultilineTextBoxView::SelectedTextRange()"
reason="Workaround for iOS 16" />
<!-- END iOS 16 workaround -->
</Properties>
</IgnoreSet>
Expand Down
4 changes: 2 additions & 2 deletions src/SamplesApp/SamplesApp.iOS/SamplesApp.iOS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<MtouchArch>x86_64</MtouchArch>
<MtouchLink>None</MtouchLink>
<MtouchDebug>true</MtouchDebug>
<MtouchExtraArgs>--dlsym:Microsoft.Win32.Registry.dll --xml=./LinkerExclusions.xml --linkskip=$(AssemblyName) --setenv=MONO_GC_PARAMS=soft-heap-limit=1024m,nursery-size=64m,evacuation-threshold=66,major=marksweep,concurrent-sweep</MtouchExtraArgs>
<MtouchExtraArgs>--dlsym:Microsoft.Win32.Registry.dll --xml=./LinkerExclusions.xml --linkskip=$(AssemblyName) --setenv=MONO_GC_PARAMS=soft-heap-limit=1024m,nursery-size=64m,evacuation-threshold=66,major=marksweep,concurrent-sweep --registrar=static</MtouchExtraArgs>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchEnableSGenConc>true</MtouchEnableSGenConc>
</PropertyGroup>
Expand All @@ -42,7 +42,7 @@
<MtouchLink>None</MtouchLink>
<MtouchArch>x86_64</MtouchArch>
<ConsolePause>false</ConsolePause>
<MtouchExtraArgs>--dlsym:Microsoft.Win32.Registry.dll --xml=./LinkerExclusions.xml --linkskip=$(AssemblyName) --setenv=MONO_GC_PARAMS=soft-heap-limit=1024m,nursery-size=64m,evacuation-threshold=66,major=marksweep,concurrent-sweep</MtouchExtraArgs>
<MtouchExtraArgs>--dlsym:Microsoft.Win32.Registry.dll --xml=./LinkerExclusions.xml --linkskip=$(AssemblyName) --setenv=MONO_GC_PARAMS=soft-heap-limit=1024m,nursery-size=64m,evacuation-threshold=66,major=marksweep,concurrent-sweep --registrar=static</MtouchExtraArgs>
<MtouchEnableSGenConc>true</MtouchEnableSGenConc>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
Expand Down
7 changes: 2 additions & 5 deletions src/Uno.UI/Controls/Window.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Input;
using Windows.System;
using Windows.UI.Core;

#if NET6_0_OR_GREATER
using ObjCRuntime;
#endif

namespace Uno.UI.Controls
{
Expand Down Expand Up @@ -329,7 +325,8 @@ internal void MakeVisible(UIView view, BringIntoViewMode? bringIntoViewMode, boo
}
if (multilineTextBoxView != null && multilineTextBoxView.IsFirstResponder)
{
viewRectInScrollView = multilineTextBoxView.GetCaretRectForPosition(multilineTextBoxView.SelectedTextRange.Start);
using var range = Runtime.GetNSObject<UITextRange>(multilineTextBoxView.SelectedTextRange);
viewRectInScrollView = multilineTextBoxView.GetCaretRectForPosition(range.Start);

// We need to add an additional margins because the caret is too tight to the text. The font is cutoff under the keyboard.
viewRectInScrollView.Y -= KeyboardMargin;
Expand Down
9 changes: 0 additions & 9 deletions src/Uno.UI/FeatureConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -452,15 +452,6 @@ public static class TextBox
/// </remarks>
public static bool UseLegacyInputScope { get; set; }
#endif

#if __IOS__
/// <summary>
/// As of iOS 16 Beta 4, the selection events are crashing the application. This feature configuration is added
/// to provide the ability to restore the original behavior if/when the underlying UIKit is fixed.
/// See https://github.com/unoplatform/uno/issues/9430 for additional details.
/// </summary>
public static bool IOS16EnableSelectionSupport { get; set; }
#endif
}

public static class ScrollViewer
Expand Down
17 changes: 9 additions & 8 deletions src/Uno.UI/UI/Xaml/Controls/TextBox/MultilineTextBoxView.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,7 @@
using Uno.UI.Controls;
using Windows.UI;
using Uno.Disposables;

#if NET6_0_OR_GREATER
using ObjCRuntime;
#endif

namespace Windows.UI.Xaml.Controls
{
Expand Down Expand Up @@ -240,17 +237,21 @@ public void UpdateTextAlignment()
}
}

public override UITextRange SelectedTextRange
/// <summary>
/// Workaround for https://github.com/unoplatform/uno/issues/9430
/// </summary>
[Export("selectedTextRange")]
public new IntPtr SelectedTextRange
{
get
{
return base.SelectedTextRange;
return SinglelineTextBoxView.IntPtr_objc_msgSendSuper(SuperHandle, Selector.GetHandle("selectedTextRange"));
}
set
{
if (base.SelectedTextRange != value)
if (SelectedTextRange != value)
{
base.SelectedTextRange = value;
SinglelineTextBoxView.void_objc_msgSendSuper(SuperHandle, Selector.GetHandle("setSelectedTextRange:"), value);
_textBox.GetTarget()?.OnSelectionChanged();
}
}
Expand All @@ -262,6 +263,6 @@ public void RefreshFont()
}

public void Select(int start, int length)
=> SelectedTextRange = this.GetTextRange(start: start, end: start + length);
=> SelectedTextRange = this.GetTextRange(start: start, end: start + length).GetHandle();
}
}
51 changes: 16 additions & 35 deletions src/Uno.UI/UI/Xaml/Controls/TextBox/SinglelineTextBoxView.iOS.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using CoreGraphics;
using ObjCRuntime;
using Uno.UI.DataBinding;
using Uno.UI.Views.Controls;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using UIKit;
using Uno.Extensions;
Expand All @@ -24,8 +26,6 @@ public partial class SinglelineTextBoxView : UITextField, ITextBoxView, Dependen
private readonly WeakReference<TextBox> _textBox;
private readonly SerialDisposable _foregroundChanged = new();

private static bool _issue9430WarnSingle = false;

public SinglelineTextBoxView(TextBox textBox)
{
_textBox = new WeakReference<TextBox>(textBox);
Expand All @@ -34,24 +34,6 @@ public SinglelineTextBoxView(TextBox textBox)
Initialize();
}

internal static SinglelineTextBoxView CreateSinglelineTextBoxView(TextBox textBox)
{
if (UIDevice.CurrentDevice.CheckSystemVersion(16, 0) && !FeatureConfiguration.TextBox.IOS16EnableSelectionSupport)
{
if (!_issue9430WarnSingle && typeof(SinglelineTextBoxView).Log().IsEnabled(LogLevel.Error))
{
_issue9430WarnSingle = true;
typeof(SinglelineTextBoxView).Log().Error($"TextBox selection events are disabled on iOS 16. See https://github.com/unoplatform/uno/issues/9430 for additional details.");
}

return new SinglelineTextBoxView(textBox);
}
else
{
return new SinglelineTextBoxViewWithSelection(textBox);
}
}

internal TextBox TextBox => _textBox.GetTarget();

public override string Text
Expand Down Expand Up @@ -237,32 +219,31 @@ public void RefreshFont()
}

public void Select(int start, int length)
=> SelectedTextRange = this.GetTextRange(start: start, end: start + length);
}
=> SelectedTextRange = this.GetTextRange(start: start, end: start + length).GetHandle();

/// <summary>
/// Workaround for https://github.com/unoplatform/uno/issues/9430
/// </summary>
internal partial class SinglelineTextBoxViewWithSelection : SinglelineTextBoxView
{
public SinglelineTextBoxViewWithSelection(TextBox textBox)
: base(textBox)
{
}
/// <summary>
/// Workaround for https://github.com/unoplatform/uno/issues/9430
/// </summary>
[DllImport(Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSendSuper")]
static internal extern IntPtr IntPtr_objc_msgSendSuper(IntPtr receiver, IntPtr selector);

[DllImport(Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSendSuper")]
static internal extern void void_objc_msgSendSuper(IntPtr receiver, IntPtr selector, IntPtr arg);

public override UITextRange SelectedTextRange
[Export("selectedTextRange")]
public new IntPtr SelectedTextRange
{
get
{
return base.SelectedTextRange;
return IntPtr_objc_msgSendSuper(SuperHandle, Selector.GetHandle("selectedTextRange"));
}
set
{
var textBox = TextBox;

if (textBox != null && base.SelectedTextRange != value)
if (textBox != null && SelectedTextRange != value)
{
base.SelectedTextRange = value;
void_objc_msgSendSuper(SuperHandle, Selector.GetHandle("setSelectedTextRange:"), value);
textBox.OnSelectionChanged();
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.iOS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private void UpdateTextBoxView()
return;
}

_textBoxView = SinglelineTextBoxView.CreateSinglelineTextBoxView(this);
_textBoxView = new SinglelineTextBoxView(this);

_contentElement.Content = _textBoxView;
_textBoxView.SetTextNative(Text);
Expand Down