iPad真机Release模式下MAUI应用TypedBinding抛出InvalidProgramException
MAUI iOS真机Release模式下
InvalidProgramException问题排查 问题现象
MAUI应用在iOS模拟器的Debug模式运行正常,但在iPad真机的Release模式下打开Settings页面时,抛出如下异常:
System.Reflection.TargetInvocationException: Arg_TargetInvocationException ---> System.InvalidProgramException at Microsoft.Maui.Controls.Internals.TypedBinding`2[[OIL.ISA.ViewModels.SettingsViewModel, OIL.ISA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ApplyCore(Object sourceObject, BindableObject target, BindableProperty property, Boolean fromTarget) at Microsoft.Maui.Controls.Internals.TypedBinding`2[[OIL.ISA.ViewModels.SettingsViewModel, OIL.ISA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Apply(Object context, BindableObject bindObj, BindableProperty targetProperty, Boolean fromBindingContextChanged) at Microsoft.Maui.Controls.BindableObject.ApplyBindings(Boolean skipBindingContext, Boolean fromBindingContextChanged) at Microsoft.Maui.Controls.BindableObject.SetInheritedBindingContext(BindableObject bindable, Object value) at Microsoft.Maui.Controls.Element.SetChildInheritedBindingContext(Element child, Object context) at Microsoft.Maui.Controls.Element.<OnBindingContextChanged>b__82_0(BindableObject child, Object bc) at Microsoft.Maui.Controls.BindableObjectExtensions.PropagateBindingContext[Element](BindableObject self, IEnumerable`1 children, Action`2 setChildBindingContext) at Microsoft.Maui.Controls.Element.OnBindingContextChanged() at Microsoft.Maui.Controls.VisualElement.OnBindingContextChanged() at Microsoft.Maui.Controls.View.OnBindingContextChanged() at Microsoft.Maui.Controls.BindableObject.SetInheritedBindingContext(BindableObject bindable, Object value) at Microsoft.Maui.Controls.Element.SetChildInheritedBindingContext(Element child, Object context) at Microsoft.Maui.Controls.Element.<OnBindingContextChanged>b__82_0(BindableObject child, Object bc) at Microsoft.Maui.Controls.BindableObjectExtensions.PropagateBindingContext[Element](BindableObject self, IEnumerable`1 children, Action`2 setChildBindingContext) at Microsoft.Maui.Controls.Element.OnBindingContextChanged() at Microsoft.Maui.Controls.VisualElement.OnBindingContextChanged() at Microsoft.Maui.Controls.View.OnBindingContextChanged() at Microsoft.Maui.Controls.BindableObject.SetInheritedBindingContext(BindableObject bindable, Object value) at Microsoft.Maui.Controls.Element.SetChildInheritedBindingContext(Element child, Object context) at Microsoft.Maui.Controls.TemplatedPage.SetChildInheritedBindingContext(Element child, Object context) at Microsoft.Maui.Controls.Element.<OnBindingContextChanged>b__82_0(BindableObject child, Object bc) at Microsoft.Maui.Controls.BindableObjectExtensions.PropagateBindingContext[Element](BindableObject self, IEnumerable`1 children, Action`2 setChildBindingContext) at Microsoft.Maui.Controls.Element.OnBindingContextChanged() at Microsoft.Maui.Controls.VisualElement.OnBindingContextChanged() at Microsoft.Maui.Controls.Page.OnBindingContextChanged() at Microsoft.Maui.Controls.ContentPage.OnBindingContextChanged() at Microsoft.Maui.Controls.BindableObject.BindingContextPropertyChanged(BindableObject bindable, Object oldvalue, Object newvalue) at Microsoft.Maui.Controls.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent) at Microsoft.Maui.Controls.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes) at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value, Boolean fromStyle, Boolean checkAccess) at Microsoft.Maui.Controls.BindableObject.SetValue(BindableProperty property, Object value) at Microsoft.Maui.Controls.BindableObject.set_BindingContext(Object value) at OIL.ISA.Views.SettingsPage..ctor() at System.Reflection.RuntimeConstructorInfo.InternalInvoke(Object , Object[] , Boolean ) Exception_EndOfInnerExceptionStack at ObjCRuntime.Runtime.ThrowException(IntPtr ) at UIKit.UIApplication.UIApplicationMain(Int32 , String[] , IntPtr , IntPtr ) at UIKit.UIApplication.Main(String[] , Type , Type ) at OIL.ISA.Platforms.iOS.Program.Main(String[] args) Unhandled managed exception: Arg_TargetInvocationException (System.Reflection.TargetInvocationException) at ObjCRuntime.Runtime.ThrowException(IntPtr ) at UIKit.UIApplication.UIApplicationMain(Int32 , String[] , IntPtr , IntPtr ) at UIKit.UIApplication.Main(String[] , Type , Type ) at OIL.ISA.Platforms.iOS.Program.Main(String[] args) (System.InvalidProgramException) at Microsoft.Maui.Controls.Internals.TypedBinding`2[[OIL.ISA.ViewModels.SettingsViewModel, OIL.ISA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ApplyCore(Object sourceObject, BindableObject target, BindableProperty property, Boolean fromTarget) at Microsoft.Maui.Controls.Internals.TypedBinding`2[[OIL.ISA.ViewModels.SettingsViewModel, OIL.ISA, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].<…>
搜索MAUI相关的InvalidProgramException未找到有效解决思路,现分析问题原因及解决方案。
相关代码
ViewModel代码
public class SettingsViewModel : MainMenuPageViewModel { public SettingsViewModel(ViewModelServices services, IPushNotificationsService pushNotificationsService, IDatabaseUploader databaseUploader, ISecureStorage secureStorage) : base(services) { _pushNotificationsService = pushNotificationsService; _databaseUploader = databaseUploader; _databaseUploader.OnProgressChanged += OnDatabaseUploadProgressChanged; _secureStorage = secureStorage; Title = BaseApp.Settings; PushNotificationsEnabled = pushNotificationsService.DeviceToken != null; PushNotificationsEnabledMessage = PushNotificationsEnabled ? BaseApp.PushNotificationsEnabled : BaseApp.PushNotificationsNotEnabled; Logout = new Command(DoLogout); SendDatabase = new Command(UploadDatabase); ShowPushNotificationDetails = new Command(ShowNotificationDetails); using var context = new Context(); UserInformation = BaseApp.LoggedInAs + " " + LocalSettings.GetUsername(context); UpdateSettingsInformation(); Settings.OnRefresh += (sender, e) => UpdateSettingsInformation(); } private void UpdateSettingsInformation() { StoreInformation = Settings.Store == null ? "" : Settings.Store.Number + " - " + Settings.Store.Name; OnPropertyChanged(nameof(StoreInformation)); } private void OnDatabaseUploadProgressChanged(object sender, ProgressChangedEventArgs e) { Progress = e.ProgressPercentage / 100f; } private readonly IPushNotificationsService _pushNotificationsService; private readonly IDatabaseUploader _databaseUploader; private readonly ISecureStorage _secureStorage; public string UserInformation { get; } public string StoreInformation { get; private set; } public bool PushNotificationsEnabled { get; } public string PushNotificationsEnabledMessage { get; } public string AppVersion => AppInfo.VersionString; public ICommand Logout { get; } public ICommand SendDatabase { get; } public ICommand ShowPushNotificationDetails { get; } ... }
页面XAML代码
<?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" xmlns:controls="clr-namespace:OIL.ISA.Controls" xmlns:vm="clr-namespace:OIL.ISA.ViewModels" xmlns:r="clr-namespace:OIL.ISA.Resources" x:DataType="vm:SettingsViewModel" x:Class="OIL.ISA.Views.SettingsPage" Title="{Binding Title}" Shell.NavBarIsVisible="{Binding NavBarIsVisible}"> <ContentPage.Content> <AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <Image AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" Source="background.jpg" Aspect="AspectFill" /> <StackLayout AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds=".5,0" WidthRequest="320" BackgroundColor="#D0FFFFFF" Spacing="16" Padding="16" Margin="0,16"> <Label Text="{Binding UserInformation}" HorizontalOptions="Center" /> <Label Text="{Binding StoreInformation}" HorizontalOptions="Center" /> <Button Style="{StaticResource SettingsButton}" Text="{x:Static r:BaseApp.LogoutButton}" Command="{Binding Logout}" /> <Button Style="{StaticResource SettingsButton}" Text="{x:Static r:BaseApp.SendDatabaseButton}" Command="{Binding SendDatabase}" /> <StackLayout Orientation="Horizontal"> <StackLayout.GestureRecognizers> <TapGestureRecognizer Command="{Binding ShowPushNotificationDetails}" /> </StackLayout.GestureRecognizers> <CheckBox IsChecked="{Binding PushNotificationsEnabled}" VerticalOptions="Center" IsEnabled="False" /> <Label Text="{Binding PushNotificationsEnabledMessage}" VerticalOptions="Center" /> </StackLayout> <Label Text="{Binding Path=AppVersion, StringFormat={x:Static r:BaseApp.Version}}" HorizontalOptions="Center" /> </StackLayout> <controls:BlockingActivityIndicator AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0,0,1,1" IsVisible="{Binding IsBusy}" Message="{Binding BusyMessage}" HasProgress="{Binding HasProgress}" Progress="{Binding Progress}" /> </AbsoluteLayout> </ContentPage.Content> </ContentPage>
问题原因与解决方案
原因分析
问题出在ViewModel的AppVersion属性定义上:
public string AppVersion => AppInfo.VersionString;
这是一个表达式体只读属性,在iOS Release模式的AOT编译过程中,MAUI的数据绑定系统无法正确处理这种形式的属性,导致InvalidProgramException。Debug模式下JIT编译不会触发此问题,所以模拟器运行正常。
解决方案
将表达式体属性改为标准的只读属性形式即可解决:
public string AppVersion { get; } = AppInfo.VersionString;
或者如果需要延迟加载,也可以写成:
public string AppVersion { get { return AppInfo.VersionString; } }
修改后重新编译Release版本部署到iPad真机,异常即可消失。
内容的提问来源于stack exchange,提问作者Glorfindel
相关产品推荐
相关产品推荐

