-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
Don’t call NSAttributedString with HTML from a background thread #26153
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?xml version="1.0" encoding="utf-8" ?> | ||
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" | ||
x:Class="Maui.Controls.Sample.Issues.Issue25946"> | ||
<Grid RowDefinitions="*,Auto"> | ||
<CarouselView x:Name="collectionView"> | ||
<CarouselView.ItemsSource> | ||
<x:Array Type="{x:Type x:String}"> | ||
<x:String>Item1</x:String> | ||
<x:String>Item2</x:String> | ||
<x:String>Item3</x:String> | ||
</x:Array> | ||
</CarouselView.ItemsSource> | ||
<CarouselView.ItemTemplate> | ||
<DataTemplate> | ||
<ContentView> | ||
<VerticalStackLayout HorizontalOptions="Center" | ||
WidthRequest="200" | ||
HeightRequest="200" | ||
Background="Green"> | ||
<Label Text="{Binding .}"/> | ||
<Label Text="{Binding .}" | ||
TextType="Html"/> | ||
</VerticalStackLayout> | ||
</ContentView> | ||
</DataTemplate> | ||
</CarouselView.ItemTemplate> | ||
</CarouselView> | ||
<Button Grid.Row="1" | ||
AutomationId="btnScrollToLastItem" | ||
Clicked="ButtonClicked" | ||
Text="Scroll to last Item"/> | ||
</Grid> | ||
</ContentPage> |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
namespace Maui.Controls.Sample.Issues | ||
{ | ||
[Issue(IssueTracker.Github, 25946, "App crashes on iOS 18 when placing html label in carousel view with > 2 elements", PlatformAffected.iOS)] | ||
public partial class Issue25946 : ContentPage | ||
{ | ||
public Issue25946() | ||
{ | ||
InitializeComponent(); | ||
} | ||
|
||
void ButtonClicked(object sender, EventArgs e) | ||
{ | ||
collectionView.ScrollTo(1, animate: true); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using NUnit.Framework; | ||
using UITest.Appium; | ||
using UITest.Core; | ||
|
||
namespace Microsoft.Maui.TestCases.Tests.Issues | ||
{ | ||
public class Issue25946 : _IssuesUITest | ||
{ | ||
public Issue25946(TestDevice testDevice) : base(testDevice) | ||
{ | ||
} | ||
|
||
public override string Issue => "App crashes on iOS 18 when placing html label in carousel view with > 2 elements"; | ||
|
||
[Test] | ||
[Category(UITestCategories.CarouselView)] | ||
[Category(UITestCategories.Label)] | ||
public void AppShouldNotCrash() | ||
{ | ||
App.WaitForElement("btnScrollToLastItem"); | ||
App.Click("btnScrollToLastItem"); | ||
|
||
App.WaitForElement("Item2"); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,9 +88,14 @@ internal static void UpdateTextHtml(this UILabel platformLabel, ILabel label) | |
}; | ||
|
||
NSError nsError = new(); | ||
#pragma warning disable CS8601 | ||
platformLabel.AttributedText = new NSAttributedString(text, attr, ref nsError); | ||
#pragma warning restore CS8601 | ||
CoreFoundation.DispatchQueue.MainQueue.DispatchAsync(() => | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I might not be following your description quite right but should we check if we're on a background thread before dispatching? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With something like this: NSError nsError = new();
if (NSThread.IsMain)
{
platformLabel.AttributedText = new NSAttributedString(text, attr, ref nsError);
if (label.Handler is ILabelHandler labelHandler)
{
labelHandler.UpdateValue(nameof(ILabel.TextColor));
labelHandler.UpdateValue(nameof(ILabel.Font));
}
label.InvalidateMeasure();
}
else
{
CoreFoundation.DispatchQueue.MainQueue.DispatchAsync(() =>
{
platformLabel.AttributedText = new NSAttributedString(text, attr, ref nsError);
if (label.Handler is ILabelHandler labelHandler)
{
labelHandler.UpdateValue(nameof(ILabel.TextColor));
labelHandler.UpdateValue(nameof(ILabel.Font));
}
label.InvalidateMeasure();
});
} The list view/collection view with the HTML label looks right, but the app crashes when using the collection view There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe use a local function to avoid code duplication. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will the async cause issues because that would be unexpected? Will DispatchSync work/have issues/locking? |
||
{ | ||
platformLabel.AttributedText = new NSAttributedString(text, attr, ref nsError); | ||
if (label.Handler is ILabelHandler labelHandler) | ||
LabelHandler.ReapplyFormattingForHTMLLabel(labelHandler, label); | ||
|
||
label.InvalidateMeasure(); | ||
jfversluis marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
} | ||
|
||
internal static void UpdateTextPlainText(this UILabel platformLabel, IText label) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like I wrote this code and overengineered this. It appears there is just 1 usage of the MapFormatting method, and it was already weird. Maybe this should just be merged with the MapText or UpdateText?