在Xamarin.iOS

如何解决在Xamarin.iOS

我们刚刚使用azure通知中心作为提供程序为Xamarin.forms应用实现了新的推送通知功能。在iOS上,当将应用程序全新安装在iOS设备上(即设备上未安装该应用程序的先前版本)时,通知可以正常运行。但是,当我尝试通过在顶部安装较新版本来升级iOS设备上的现有应用程序时,我没有收到任何通知。

调试时,我发现仅在应用程序升级场景中,iOS应用程序会引发 UIKit.UIKitThreadAccessException:'UIKit一致性错误:您正在调用只能从UI线程调用的UIKit方法。' 由于此例外,该设备未在Apple Push Notification Services中注册,因此也没有任何推送通知。

以下是stacktrace的完整异常:

UIKit.UIKitThreadAccessException: 'UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.'

UIKit.UIKitThreadAccessException
  Message=UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.
  Source=mscorlib
  StackTrace:
  at UIKit.UIApplication.EnsureUIThread () [0x00020] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/UIKit/UIApplication.cs:96 
  at UIKit.UIGestureRecognizer..ctor (Foundation.NSObject target,System.IntPtr action) [0x00016] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/UIGestureRecognizer.g.cs:102 
  at UIKit.UIGestureRecognizer..ctor (System.IntPtr sel,UIKit.UIGestureRecognizer+Token token) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/UIKit/UIGestureRecognizer.cs:66 
  at UIKit.UITapGestureRecognizer..ctor (System.Action`1[T] action) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/UIKit/UIGestureRecognizer.cs:208 
  at Xamarin.Forms.Platform.iOS.EventTracker.CreateTapRecognizer (System.Int32 numTaps,System.Action`1[T] action,System.Int32 numFingers) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\EventTracker.cs:462 
  at Xamarin.Forms.Platform.iOS.EventTracker.GetNativeRecognizer (Xamarin.Forms.IGestureRecognizer recognizer) [0x00049] in D:\a\1\s\Xamarin.Forms.Platform.iOS\EventTracker.cs:258 
  at Xamarin.Forms.Platform.iOS.EventTracker.LoadRecognizers () [0x00042] in D:\a\1\s\Xamarin.Forms.Platform.iOS\EventTracker.cs:572 
  at Xamarin.Forms.Platform.iOS.EventTracker.ModelGestureRecognizersOnCollectionChanged (System.Object sender,System.Collections.Specialized.NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\EventTracker.cs:624 
  at (wrapper delegate-invoke) <Module>.invoke_void_object_NotifyCollectionChangedEventArgs(object,System.Collections.Specialized.NotifyCollectionChangedEventArgs)
  at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00018] in <b912bfaf235d4ed8af62226c84967349>:0 
  at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedAction action,System.Object item,System.Int32 index) [0x00009] in <b912bfaf235d4ed8af62226c84967349>:0 
  at System.Collections.ObjectModel.ObservableCollection`1[T].InsertItem (System.Int32 index,T item) [0x0001a] in <b912bfaf235d4ed8af62226c84967349>:0 
  at System.Collections.ObjectModel.Collection`1[T].Add (T item) [0x00020] in <cbddc4225b2f45f09f3a1d43a1268bc0>:0 
  at Xamarin.Forms.View.<.ctor>g__AddItems|14_1 (Xamarin.Forms.View+<>c__DisplayClass14_0& ) [0x00032] in D:\a\1\s\Xamarin.Forms.Core\View.cs:85 
  at Xamarin.Forms.View.<.ctor>b__14_0 (System.Object sender,System.Collections.Specialized.NotifyCollectionChangedEventArgs args) [0x0002f] in D:\a\1\s\Xamarin.Forms.Core\View.cs:101 
  at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00018] in <b912bfaf235d4ed8af62226c84967349>:0 
  at System.Collections.ObjectModel.ObservableCollection`1[T].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedAction action,T item) [0x0001a] in <b912bfaf235d4ed8af62226c84967349>:0 
  at System.Collections.ObjectModel.Collection`1[T].Add (T item) [0x00020] in <cbddc4225b2f45f09f3a1d43a1268bc0>:0 
  at SWAPA.MemberMobileApp.UI.Views.Login.CommonSetup () [0x002a1] in C:\MemberMobileApp\SWAPA.MemberMobileApp.UI\SWAPA.MemberMobileApp.UI\SWAPA.MemberMobileApp.UI\Views\Login.xaml.cs:369 
  at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_1 (System.Object state) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1037 
  at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object state) [0x0000d] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:1370 
  at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext,System.Threading.ContextCallback callback,System.Object state,System.Boolean preserveSyncCtx) [0x00071] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:968 
  at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext,System.Boolean preserveSyncCtx) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:910 
  at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00021] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:1341 
  at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00074] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:899 
  at ObjCRuntime.Runtime.ThreadPoolDispatcher (System.Func`1[TResult] callback) [0x00006] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.18.2.1/src/Xamarin.iOS/ObjCRuntime/Runtime.cs:288 
  at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00009] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/mcs/class/referencesource/mscorlib/system/threading/threadpool.cs:1258 

我在AppDelegate中完成的唯一实现是向Apple Push Notification Services注册设备,然后将该设备注册ID发送到主UI应用程序以向Azure通知中心注册设备。

下面是我的代码,并带有一些注释:

    [Register("AppDelegate")]
    public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate,IUNUserNotificationCenterDelegate
    {
        //
        // This method is invoked when the application has loaded and is ready to run. In this 
        // method you should instantiate the window,load the UI into it and then make the window
        // visible.
        //
        // You have 17 seconds to return from this method,or iOS will terminate your application.
        //
        public override bool FinishedLaunching(UIApplication app,NSDictionary options)
        {
            global::Xamarin.Forms.Forms.Init();

            //----Block needed for App Center Testing-----
#if ENABLE_TEST_CLOUD
            //Xamarin.Calabash.Start();
#endif
            //----Block needed for App Center Testing-----

            new SfCalendarRenderer();

            LoadApplication(new App());
            SfImageEditorRenderer.Init();
            SfListViewRenderer.Init();
            SfCheckBoxRenderer.Init();
            SfPdfDocumentViewRenderer.Init();
            SfPickerRenderer.Init();
            Syncfusion.SfChart.XForms.iOS.Renderers.SfChartRenderer.Init();
            new Syncfusion.SfAutoComplete.XForms.iOS.SfAutoCompleteRenderer();

            UITabBar.Appearance.SelectedImageTintColor = UIColor.FromRGB(213,84,39);

            // Color of the tabbar background:
            UITabBar.Appearance.BarTintColor = UIColor.LightGray;

            // Color of the selected tab text color:
            UITabBarItem.Appearance.SetTitleTextAttributes(
                new UITextAttributes()
                {
                    TextColor = UIColor.FromRGB(213,39)
                },UIControlState.Selected);

            // Color of the unselected tab icon & text:
            UITabBarItem.Appearance.SetTitleTextAttributes(
                new UITextAttributes()
                {
                    TextColor = UIColor.FromRGB(65,64,66)
                },UIControlState.Normal);

            base.FinishedLaunching(app,options);

            /*Register device with Apple Push Notification Service*/
            RegisterForRemoteNotifications();

            if (options != null && options.ContainsKey(UIApplication.LaunchOptionsRemoteNotificationKey))
            {
                NSDictionary userInfo = (NSDictionary)options[UIApplication.LaunchOptionsRemoteNotificationKey];
                if (userInfo != null)
                {
                    PushNotifications.IsNotifictaionClick_AppInActive = true;
                    // To remove all delivered notifications
                    RemoveAllDeliveredPushNotifications();
                }
            }
            return true;
        }

        //Register device with Apple Push Notification Services
        void RegisterForRemoteNotifications()
        {
            //register for remote notifications based on system version
            if (UIDevice.CurrentDevice.CheckSystemVersion(10,0))
            {
                UNUserNotificationCenter.Current.RequestAuthorization(UNAuthorizationOptions.Alert |
                    UNAuthorizationOptions.Sound |
                    UNAuthorizationOptions.Sound,(granted,error) =>
                    {
                        if (granted)
                            InvokeOnMainThread(UIApplication.SharedApplication.RegisterForRemoteNotifications); // Ask user for permission to receive notifications on device.
                    });
            }
            else if (UIDevice.CurrentDevice.CheckSystemVersion(8,0))
            {
                var pushSettings = UIUserNotificationSettings.GetSettingsForTypes(
                UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound,new NSSet());

                UIApplication.SharedApplication.RegisterUserNotificationSettings(pushSettings);
                UIApplication.SharedApplication.RegisterForRemoteNotifications();
            }
            else
            {
                UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | UIRemoteNotificationType.Sound;
                UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
            }

            UNUserNotificationCenter.Current.Delegate = this;
        }

        //Send the PNS handle to UI app for device installation with Azure Notificaiton Hub.
        public override void RegisteredForRemoteNotifications(UIApplication application,NSData deviceToken)
        {
            //Format the pns handle before registering with Azure notification hub.
            PushNotifications.PNSHandle = deviceToken.DebugDescription.Replace("<",string.Empty)
                                                                      .Replace(">",string.Empty)
                                                                      .Replace(" ",string.Empty)
                                                                      .ToUpper();
        }

        // Process notification when received.
        public override void ReceivedRemoteNotification(UIApplication application,NSDictionary userInfo)
        {
            ProcessNotification(userInfo);
        }

        void ProcessNotification(NSDictionary options)
        {
            // make sure we have a payload
            if (options != null && options.ContainsKey(new NSString("aps")))
            {
                // get the APS dictionary and extract message payload. Message JSON will be converted
                // into a NSDictionary so more complex payloads may require more processing
                NSDictionary aps = options.ObjectForKey(new NSString("aps")) as NSDictionary;
                NSDictionary alertMessage = aps.ObjectForKey(new NSString("alert")) as NSDictionary;

                //Extract notification content
                NSString messageKey = new NSString("body");
                NSString titleKey = new NSString("title");

                string messageBody = alertMessage.ContainsKey(messageKey) ? alertMessage[titleKey].ToString() : string.Empty;
                string title = alertMessage.ContainsKey(titleKey) ? alertMessage[titleKey].ToString() : string.Empty;

                if (!string.IsNullOrWhiteSpace(title) || !string.IsNullOrWhiteSpace(messageBody))
                {
                    var content = new UNMutableNotificationContent();
                    content.Title = title;
                    content.Body = messageBody;

                    var requestID = title;
                    var request = UNNotificationRequest.FromIdentifier(requestID,content,null);

                    UNUserNotificationCenter.Current.AddNotificationRequest(request,(err) =>
                    {
                        if (err != null)
                        {
                            // TODO: log error messages in error data table.
                            Debug.WriteLine($"Received request to process notification but something went wrong.");
                        }
                    });
                }
            }
            else
            {
                // TODO: log error messages in error data table.
                Debug.WriteLine($"Received request to process notification but there was no payload.");
            }
        }

        [Export("userNotificationCenter:willPresentNotification:withCompletionHandler:")]
        public void WillPresentNotification(UNUserNotificationCenter center,UNNotification notification,Action<UNNotificationPresentationOptions> completionHandler)
        {
            completionHandler(UNNotificationPresentationOptions.Sound | UNNotificationPresentationOptions.Alert);
        }

        [Export("userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:")]
        public void DidReceiveNotificationResponse(UNUserNotificationCenter center,UNNotificationResponse response,Action
        completionHandler)
        {
            completionHandler();

            /*Logic to open NotificationInboxPage onclick of notification when app was active */
            if (!App.IsAppLaunching)
            {
                var modalStack = App.Current.MainPage.Navigation.ModalStack;

                if (modalStack.Count > 0 && modalStack.Last().ToString().Contains("NotificationInbox"))
                    App.Current.MainPage.Navigation.PopModalAsync();

                App.Current.MainPage.Navigation.PushModalAsync(new NotificationInboxPage());
            }
            App.IsAppLaunching = false;

            //To remove all delivered notifications
            RemoveAllDeliveredPushNotifications();
        }

        private void RemoveAllDeliveredPushNotifications()
        {
            if (UIDevice.CurrentDevice.CheckSystemVersion(10,0))
            {
                UNUserNotificationCenter.Current.RemoveAllDeliveredNotifications();
            }
            else
            {
                UIApplication.SharedApplication.CancelAllLocalNotifications();
            }
        }
}

该异常表明我正在调用只能从UI线程调用的UIKit方法。我要调用的唯一操作是 InvokeOnMainThread(UIApplication.SharedApplication.RegisterForRemoteNotifications); ,我已经在主线程上调用了。因此,我不确定所讨论的异常还有什么其他功能。为什么只在升级应用程序时抱怨而不是在全新安装应用程序时抱怨呢?

我查看了该帖子here,但并没有太大帮助。由于这一点,我现在完全陷入困境,确实需要一些帮助来解决问题。知道我可能会缺少什么吗?

谢谢。

解决方法

正如您从问题中提供的堆栈跟踪中看到的那样,该错误实际上发生在“ Login.xaml.cs”文件的第369行。

如果放置“异常捕获点”,它应该告诉您确切的行导致该问题。在其周围放置try-catch应该可以解决崩溃问题,但由于通常情况下异常情况不好,因此也应尝试解决该问题。

除此之外,您还可以改为使用DispatchAsync

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-