diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6387.xaml b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6387.xaml
new file mode 100644
index 00000000000..c0d618e903f
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6387.xaml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6387.xaml.cs b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6387.xaml.cs
new file mode 100644
index 00000000000..538f43ac492
--- /dev/null
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Issue6387.xaml.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using Xamarin.Forms.CustomAttributes;
+using Xamarin.Forms.Internals;
+using System.Reflection;
+
+#if UITEST
+using Xamarin.UITest;
+using NUnit.Framework;
+using Xamarin.Forms.Core.UITests;
+#endif
+
+namespace Xamarin.Forms.Controls.Issues
+{
+#if UITEST
+ [Category(UITestCategories.ToolbarItem)]
+#endif
+ [Preserve(AllMembers = true)]
+ [Issue(IssueTracker.Github, 6387,
+ "[Bug] [iOS] Crash When the First Toolbar Item Has an Icon and a Second Item Gets Added",
+ PlatformAffected.iOS)]
+ public partial class Issue6387 : TestContentPage
+ {
+#if APP
+ readonly ToolbarItem _item0;
+ readonly ToolbarItem _item1;
+#endif
+ public Issue6387()
+ {
+#if APP
+ InitializeComponent();
+
+ _item0 = new ToolbarItem("Item 0", null, ClearAndAddToolbarItems)
+ {
+ IconImageSource = ImageSource.FromResource("Xamarin.Forms.Controls.GalleryPages.crimson.jpg", typeof(Issue6387).GetTypeInfo().Assembly)
+ };
+ _item1 = new ToolbarItem("Item 1", null, ClearAndAddToolbarItems)
+ {
+ // It doesn't matter if this item has an image or not.
+ };
+
+ ClearAndAddToolbarItems();
+#endif
+ }
+
+ protected override void Init()
+ {
+
+ }
+#if APP
+ void ClearAndAddToolbarItems()
+ {
+ ToolbarItems.Clear();
+
+ ToolbarItems.Add(_item0);
+ ToolbarItems.Add(_item1);
+ }
+#endif
+ }
+}
\ No newline at end of file
diff --git a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
index 37c1424198e..423d34104c0 100644
--- a/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
+++ b/Xamarin.Forms.Controls.Issues/Xamarin.Forms.Controls.Issues.Shared/Xamarin.Forms.Controls.Issues.Shared.projitems
@@ -1796,6 +1796,7 @@
+
@@ -2279,6 +2280,9 @@
MSBuild:UpdateDesignTimeXaml
+
+ MSBuild:UpdateDesignTimeXaml
+
@@ -2799,7 +2803,7 @@
Designer
- MSBuild:Compile
+ MSBuild:UpdateDesignTimeXaml
Designer
diff --git a/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs b/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs
index 29d919138a8..d92a97f2b41 100644
--- a/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs
+++ b/Xamarin.Forms.Platform.iOS/Extensions/ToolbarItemExtensions.cs
@@ -1,4 +1,5 @@
using System.ComponentModel;
+using System.Threading.Tasks;
using CoreGraphics;
using UIKit;
using PointF = CoreGraphics.CGPoint;
@@ -23,6 +24,7 @@ public static UIBarButtonItem ToUIBarButtonItem(this ToolbarItem item, bool forc
sealed class PrimaryToolbarItem : UIBarButtonItem
{
+ bool _disposed;
readonly bool _forceName;
readonly ToolbarItem _item;
@@ -32,7 +34,7 @@ public PrimaryToolbarItem(ToolbarItem item, bool forceName)
_item = item;
if (item.IconImageSource != null && !item.IconImageSource.IsEmpty && !forceName)
- UpdateIconAndStyle();
+ Device.BeginInvokeOnMainThread(async () => { await UpdateIconAndStyleAsync(); });
else
UpdateTextAndStyle();
UpdateIsEnabled();
@@ -50,11 +52,15 @@ public PrimaryToolbarItem(ToolbarItem item, bool forceName)
protected override void Dispose(bool disposing)
{
if (disposing)
+ {
_item.PropertyChanged -= OnPropertyChanged;
+ _disposed = true;
+ }
+
base.Dispose(disposing);
}
- void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ async void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName)
UpdateIsEnabled();
@@ -68,7 +74,7 @@ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
if (!_forceName)
{
if (_item.IconImageSource != null && !_item.IconImageSource.IsEmpty)
- UpdateIconAndStyle();
+ await UpdateIconAndStyleAsync();
else
UpdateTextAndStyle();
}
@@ -79,8 +85,11 @@ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
this.SetAccessibilityLabel(_item);
}
- async void UpdateIconAndStyle()
+ async Task UpdateIconAndStyleAsync()
{
+ if (_disposed)
+ return;
+
Image = await _item.IconImageSource.GetNativeImageAsync();
Style = UIBarButtonItemStyle.Plain;
}
@@ -100,13 +109,14 @@ void UpdateTextAndStyle()
sealed class SecondaryToolbarItem : UIBarButtonItem
{
+ bool _disposed;
readonly ToolbarItem _item;
public SecondaryToolbarItem(ToolbarItem item) : base(new SecondaryToolbarItemContent())
{
_item = item;
UpdateText();
- UpdateIcon();
+ Device.BeginInvokeOnMainThread(async () => { await UpdateIconAsync(); });
UpdateIsEnabled();
((SecondaryToolbarItemContent)CustomView).TouchUpInside += (sender, e) => ((IMenuItemController)_item).Activate();
@@ -122,16 +132,20 @@ public SecondaryToolbarItem(ToolbarItem item) : base(new SecondaryToolbarItemCon
protected override void Dispose(bool disposing)
{
if (disposing)
+ {
_item.PropertyChanged -= OnPropertyChanged;
+ _disposed = true;
+ }
+
base.Dispose(disposing);
}
- void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
+ async void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == MenuItem.TextProperty.PropertyName)
UpdateText();
else if (e.PropertyName == MenuItem.IconImageSourceProperty.PropertyName)
- UpdateIcon();
+ await UpdateIconAsync();
else if (e.PropertyName == MenuItem.IsEnabledProperty.PropertyName)
UpdateIsEnabled();
else if (e.PropertyName == AutomationProperties.HelpTextProperty.PropertyName)
@@ -140,8 +154,11 @@ void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
this.SetAccessibilityLabel(_item);
}
- async void UpdateIcon()
+ async Task UpdateIconAsync()
{
+ if (_disposed)
+ return;
+
UIImage image = null;
if (_item.IconImageSource != null && !_item.IconImageSource.IsEmpty)
{