调用Shiny IBeaconRangingManager的RequestAccess在iOS 13.5上崩溃
问题分析与解决方案
崩溃原因
从崩溃日志核心信息 -[CLLocationManager authorizationStatus]: unrecognized selector sent to instance 可明确原因:
- iOS 13.5 及更早版本中,
authorizationStatus是CLLocationManager的类方法,而非实例方法。 - Shiny 库的
LocationExtensions.GetCurrentStatus方法在处理 iOS 13.5 时,错误调用了CLLocationManager实例的AuthorizationStatus属性(对应 Objective-C 实例方法),而非类方法CLLocationManager.AuthorizationStatus(),导致系统抛出无法识别选择器的异常。
解决方案
1. 升级 Shiny NuGet 包
优先检查 Shiny 库最新版本,官方大概率已修复 iOS 版本兼容性问题。更新至最新稳定版后,重新测试 iOS 13.5 设备,确认崩溃是否消失。
2. 自定义 iOS 平台特定权限兼容逻辑
若暂时无法升级 Shiny,可在 iOS 项目中添加平台特定代码,手动处理权限检查,规避 Shiny 的兼容问题:
// iOS 平台代码文件(如 Platforms/iOS/BeaconAccessHandler.cs) using CoreLocation; using Shiny.Locations; using UIKit; public static class BeaconAccessHelper { public static AccessState GetCurrentLocationAccessStatus(bool background) { var osVersion = UIDevice.CurrentDevice.SystemVersion; if (Version.Parse(osVersion) <= new Version(13, 5)) { // iOS 13.5 及以下调用类方法获取权限状态 var status = CLLocationManager.AuthorizationStatus; return MapStatusToAccessState(status, background); } else { // iOS 14+ 使用实例方法 using var manager = new CLLocationManager(); var status = manager.AuthorizationStatus; return MapStatusToAccessState(status, background); } } private static AccessState MapStatusToAccessState(CLAuthorizationStatus status, bool background) { return status switch { CLAuthorizationStatus.AuthorizedAlways => AccessState.Available, CLAuthorizationStatus.AuthorizedWhenInUse => background ? AccessState.Denied : AccessState.Available, CLAuthorizationStatus.Denied => AccessState.Denied, CLAuthorizationStatus.Restricted => AccessState.Restricted, _ => AccessState.Unknown }; } }
修改原 CheckAccess 方法,针对 iOS 平台调用自定义逻辑:
public async Task<string?> CheckAccess() { var translationService = _serviceProvider.GetService<ITranslationService>(); if (translationService == null) return null; #if IOS var accessState = BeaconAccessHelper.GetCurrentLocationAccessStatus(false); if (accessState != AccessState.Available) { using var manager = new CLLocationManager(); if (UIDevice.CurrentDevice.CheckSystemVersion(14, 0)) await manager.RequestWhenInUseAuthorizationAsync(); else manager.RequestWhenInUseAuthorization(); accessState = BeaconAccessHelper.GetCurrentLocationAccessStatus(false); if (accessState != AccessState.Available) return translationService.GetText("global_syn_permission_bluetooth"); } #else var beaconRangingManager = _serviceProvider.GetService<IBeaconRangingManager>(); if (beaconRangingManager != null) { var accessState = await beaconRangingManager.RequestAccess(); if (accessState != AccessState.Available) return translationService.GetText("global_syn_permission_bluetooth"); } #endif return null; }
3. 捕获异常并降级处理
若上述方案无法快速实施,可在 CheckAccess 方法中捕获特定异常,直接返回权限提示:
public async Task<string?> CheckAccess() { var beaconRangingManager = _serviceProvider.GetService<IBeaconRangingManager>(); var translationService = _serviceProvider.GetService<ITranslationService>(); if (beaconRangingManager != null && translationService != null) { try { var accessState = await beaconRangingManager.RequestAccess(); if (accessState != AccessState.Available) return translationService.GetText("global_syn_permission_bluetooth"); } catch (Exception ex) when (ex.Message.Contains("unrecognized selector sent to instance") && ex.Message.Contains("authorizationStatus")) { return translationService.GetText("global_syn_permission_bluetooth"); } } return null; }
内容的提问来源于stack exchange,提问作者BeRo
相关产品推荐
相关产品推荐

