Пользовательский компонент Maui аварийно завершает работу только в версии iOS
В настоящее время я обновил приложение Xamarin до приложения MAUI .net8, и, похоже, оно работает достаточно правильно в отладке как на iOS, так и на Android.
Выпуск Android также работает, но когда я пытаюсь запустить выпуск iOS, он вылетает с этой ошибкой:
System.InvalidProgramException:
Invalid IL code in (wrapper dynamic-method) object:InvokeStub_ScheduleItem.get_Address (object,object,intptr*): IL_0001: callvirt 0x00000001
это происходит только тогда, когда он пытается заполнить/отобразить этот пользовательский компонент:
<?xml
version="1.0"
encoding="UTF-8"?>
<Frame
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="***.Views.Component.ScheduleItemView"
x:Name="ThisComponent"
VerticalOptions="Fill"
CornerRadius="5"
Padding="0"
Margin="0"
Style="{DynamicResource ListFrameItem}"
BorderColor="{Binding Item.FrameworkColorFromHex, Source={x:Reference ThisComponent}}"
BackgroundColor="{Binding Item.FillColorFromHex, Source={x:Reference ThisComponent}}">
<Frame.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapped"
CommandParameter="{Binding Id}" />
</Frame.GestureRecognizers>
<Grid
Padding="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60" /> <!-- Time -->
<ColumnDefinition
Width="*" /> <!-- Info -->
<ColumnDefinition
Width="30" /> <!-- TotalHoursPlanningItem -->
</Grid.ColumnDefinitions>
<!-- Timeline -->
<StackLayout
Orientation="Horizontal"
Padding="5"
Grid.Column="0">
<!-- the line -->
<BoxView
Color="{Binding Item.FrameworkColorFromHex, Source={x:Reference ThisComponent}}"
Margin="2"
WidthRequest="4"
VerticalOptions="Fill" />
<!-- time -->
<StackLayout
Margin="2"
Orientation="Vertical">
<Label
TextColor="{Binding Item.TextColorFromHex, Source={x:Reference ThisComponent}}"
FontSize="Small"
Text="{Binding Item.StartTimePeriod, Source={x:Reference ThisComponent}}" />
<Label
VerticalOptions="EndAndExpand"
TextColor="{Binding Item.TextColorFromHex, Source={x:Reference ThisComponent}}"
FontSize="Small"
Text="{Binding Item.EndTimePeriod, Source={x:Reference ThisComponent}}"
HorizontalOptions="Start" />
</StackLayout>
</StackLayout>
<!-- Info -->
<StackLayout
Padding="5"
Grid.Column="1"
Orientation="Vertical"
VerticalOptions="Center"
Margin="0">
<Label
VerticalOptions="Center"
HorizontalOptions="Start"
Margin="7"
Text="{Binding Item.AbsenceType, Source={x:Reference ThisComponent}}"
IsVisible="{Binding IsVisibleAbsenceType, Source={x:Reference ThisComponent}}"
FontSize="Medium"
TextColor="{Binding Item.TextColorFromHex, Source={x:Reference ThisComponent}}" />
<Label
HorizontalOptions="Start"
FontSize="20"
MaxLines="5"
Margin="0"
TextColor="{Binding Item.TextColorFromHex, Source={x:Reference ThisComponent}}"
Text="{Binding Item.Client.Name, Source={x:Reference ThisComponent}}"
IsVisible="{Binding IsVisibleClientName, Source={x:Reference ThisComponent}}">
</Label>
<Label
Margin="{Binding LabelMargin, Source={x:Reference ThisComponent}}"
HorizontalOptions="Start"
FontSize="Small"
TextColor="{Binding Item.TextColorFromHex, Source={x:Reference ThisComponent}}"
Text="{Binding Item.Client.EChequeSodexoUserNumberToString , Source={x:Reference ThisComponent}}"
IsVisible="{Binding IsVisibleSodexoUserNumber, Source={x:Reference ThisComponent}}" />
<Label
Margin="{Binding LabelMargin, Source={x:Reference ThisComponent}}"
HorizontalOptions="Start"
FontSize="Small"
TextColor="{Binding Item.TextColorFromHex, Source={x:Reference ThisComponent}}"
Text="{Binding Item.Client.PhoneNumber , Source={x:Reference ThisComponent}}"
IsVisible="{Binding IsVisibleCustomerPhoneNr, Source={x:Reference ThisComponent}}" />
<Label
Margin="{Binding LabelMargin, Source={x:Reference ThisComponent}}"
HorizontalOptions="Start"
FontSize="Small"
TextColor="{Binding Item.TextColorFromHex, Source={x:Reference ThisComponent}}"
IsVisible="{Binding IsVisibleAddress, Source={x:Reference ThisComponent}}">
<Label.Text>
<MultiBinding
StringFormat="{}{0} {1}, {2} {3}">
<Binding
Source="{x:Reference ThisComponent}"
Path="Item.Address.Street" />
<Binding
Source="{x:Reference ThisComponent}"
Path="Item.Address.Number" />
<Binding
Source="{x:Reference ThisComponent}"
Path="Item.Address.ZipCode" />
<Binding
Source="{x:Reference ThisComponent}"
Path="Item.Address.City" />
</MultiBinding>
</Label.Text>
</Label>
</StackLayout>
<!-- Total Hours indicator -->
<Frame
Grid.Column="2"
Margin="0,0,0,0"
Padding="5,0"
HeightRequest="25"
HorizontalOptions="End"
BackgroundColor="Transparent"
BorderColor="{Binding Item.FrameworkColorFromHex, Source={x:Reference ThisComponent}}"
VerticalOptions="Start">
<Label
Margin="0"
VerticalTextAlignment="Center"
HorizontalTextAlignment="Start"
Text="{Binding Item.TotalHoursPlanningItem, Source={x:Reference ThisComponent}}"
TextColor="{Binding Item.TextColorFromHex, Source={x:Reference ThisComponent}}"
FontSize="Small" />
</Frame>
</Grid>
</Frame>
С кодом:
using ***.Structures.Client.ScheduleItems;
using ***.Structures.Enums;
using ***.Structures.Extensions;
namespace ***.Views.Component;
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ScheduleItemView : Frame
{
// private readonly ScheduleDetailViewModel _scheduleDetailViewModel;
// private readonly CustomTitleViewModel _titleViewModel;
// private readonly IPopUpMessageService _popUpMessageService;
public static readonly BindableProperty ItemProperty = BindableProperty.Create(nameof(Item), typeof(ScheduleItem),
typeof(ScheduleItemView), defaultBindingMode: BindingMode.OneTime, propertyChanged: PropertyChanged);
private bool _isAbsenceType;
private bool _isSmallView;
private bool _isVisibleAbsenceType;
private bool _isVisibleAddress;
private bool _isVisibleClientName;
private bool _isVisibleCustomerPhoneNr;
private bool _isVisibleSodexoUserNumber;
private int _margin;
public ScheduleItemView()
{
InitializeComponent();
}
// public ScheduleItemView(ScheduleDetailViewModel scheduleDetailViewModel, CustomTitleViewModel titleViewModel, IPopUpMessageService popUpMessageService)
// {
// _scheduleDetailViewModel = scheduleDetailViewModel;
// _titleViewModel = titleViewModel;
// _popUpMessageService = popUpMessageService;
// InitializeComponent();
// }
public ScheduleItem? Item
{
get => (ScheduleItem) GetValue(ItemProperty);
set
{
if (value == null)
return;
var item = value;
item.FillColor ??= "#ffffff";
item.TextColor ??= "#000000";
item.FrameworkColor ??= "#d3d3d3";
SetValue(ItemProperty, item);
SetVisibility();
OnPropertyChanged();
}
}
public bool IsVisibleAbsenceType
{
get => _isVisibleAbsenceType;
set
{
_isVisibleAbsenceType = value;
OnPropertyChanged();
}
}
public bool IsVisibleClientName
{
get => _isVisibleClientName;
set
{
_isVisibleClientName = value;
OnPropertyChanged();
}
}
public bool IsVisibleCustomerPhoneNr
{
get => _isVisibleCustomerPhoneNr;
set
{
_isVisibleCustomerPhoneNr = value;
OnPropertyChanged();
}
}
public bool IsAbsenceType
{
get => _isAbsenceType;
set
{
_isAbsenceType = value;
OnPropertyChanged();
}
}
public bool IsVisibleSodexoUserNumber
{
get => _isVisibleSodexoUserNumber;
set
{
_isVisibleSodexoUserNumber = value;
OnPropertyChanged();
}
}
public bool IsVisibleAddress
{
get => _isVisibleAddress;
set
{
_isVisibleAddress = value;
OnPropertyChanged();
}
}
public bool IsSmallView
{
get => _isSmallView;
set
{
_isSmallView = value;
OnPropertyChanged();
}
}
public int LabelMargin
{
get => _margin;
set
{
_margin = value;
OnPropertyChanged();
}
}
private new static void PropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
var view = (ScheduleItemView) bindable;
view.Item = (ScheduleItem) newValue;
}
private void SetVisibility()
{
var f = (ScheduleItem) GetValue(ItemProperty);
ResetAll();
switch (f.ForegroundInfo)
{
case ViewPlanningType.ClientName:
IsVisibleClientName = true;
IsSmallView = true;
LabelMargin = 8;
break;
case ViewPlanningType.ClientDetailed:
IsVisibleSodexoUserNumber = true;
IsVisibleClientName = true;
IsVisibleCustomerPhoneNr = true;
IsVisibleAddress = true;
IsSmallView = false;
break;
case ViewPlanningType.ClientBasicInfo:
IsVisibleSodexoUserNumber = true;
IsVisibleClientName = true;
IsSmallView = false;
break;
case ViewPlanningType.AbsenceType:
IsVisibleAbsenceType = !string.IsNullOrEmpty(f.AbsenceType);
IsVisibleClientName = !IsVisibleAbsenceType;
IsSmallView = true;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void ResetAll()
{
IsVisibleSodexoUserNumber =
IsVisibleCustomerPhoneNr =
IsVisibleClientName =
IsVisibleAddress =
IsSmallView =
IsVisibleAbsenceType = false;
LabelMargin = 0;
}
private async void OnTapped(object sender, EventArgs e)
{
if (Item?.DbId == null)
return;
await Shell.Current.Navigation.PushOnceAsync(new ScheduleDetailPage(Item.Id));
}
}
кто использует класс:
using System.ComponentModel.DataAnnotations.Schema;
using ***.Structures.Enums;
using ***.Structures.Extensions;
namespace ***.Structures.Client.ScheduleItems;
public class ScheduleItem : BaseDbItem
{
public Guid UserId { get; set; }
public virtual UserObjects.Client? Client { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public string? StartTimePeriod => StartTime.ToString("HH:mm");
public string? EndTimePeriod => EndTime.ToString("HH:mm");
public string? DayDate => StartTime.ToString("ddd dd/MM/yyyy");
public string TotalHoursPlanningItem
{
get
{
var difference = EndTime - StartTime;
return difference.ToReadAbleString();
}
}
public int ServiceVoucherCount { get; set; }
public virtual Address? Address { get; set; } = new();
public string? ItemDescription { get; set; }
public string? FillColor { get; set; }
[NotMapped]
public Color FillColorFromHex => Color.FromArgb(FillColor);
public string? TextColor { get; set; }
[NotMapped]
public Color TextColorFromHex => Color.FromArgb(TextColor);
public string? FrameworkColor { get; set; }
[NotMapped]
public Color FrameworkColorFromHex => Color.FromArgb(FrameworkColor);
public ViewPlanningType ForegroundInfo { get; set; }
public ViewPlanningType BackgroundInfo { get; set; }
public string? AbsenceType { get; set; }
}
public class Address : BaseDbItem
{
public string? Street { get; set; }
public string? City { get; set; }
public string? Number { get; set; }
public string? ZipCode { get; set; }
public string? Bus { get; set; }
}
компонент просто используется в представлении коллекции следующим образом:
<ScrollView
Orientation="Vertical"
VerticalOptions="Fill"
VerticalScrollBarVisibility="Always"
IsVisible="{Binding NotEmptySchedule}">
<CollectionView
ItemsSource="{Binding ScheduleItems}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<component:ScheduleItemView
Item="{Binding .}"
Margin="10,5"/>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ScrollView>
Я пытался определить резервные значения для всех адресов xaml, которые используют адрес, но ничего не дало, и я добавил тег new() к указанному адресу элемента в классе, чтобы он не был нулевым.