Xamarin.Forms调用iOS原生控制器遇空值及导航创建咨询
Let's break down your two issues step by step to get things working smoothly:
Your initial code uses UIApplication.SharedApplication.KeyWindow, but this can return null on iOS 13+ due to the introduction of multi-scene support. Here's a more reliable approach, plus a clean way to integrate it with Xamarin.Forms:
Step 1: Use DependencyService to Encapsulate Native Code
First, define a shared interface in your Xamarin.Forms project so you don't tie shared code to iOS specifics:
// Shared project public interface IDocumentScannerService { void LaunchScanner(); }
Step 2: Implement the Service in iOS
In your iOS project, create the native implementation and find the correct top-level view controller (not just the root, since modals might be active):
[assembly: Dependency(typeof(DocumentScannerService))] namespace YourAppNamespace.iOS { public class DocumentScannerService : IDocumentScannerService { public void LaunchScanner() { // Get the active scene's key window (iOS 13+ compatible) var activeScene = UIApplication.SharedApplication.ConnectedScenes .OfType<UIWindowScene>() .FirstOrDefault(scene => scene.ActivationState == UISceneActivationState.ForegroundActive); var keyWindow = activeScene?.Windows.FirstOrDefault(w => w.IsKeyWindow); if (keyWindow == null) return; // Traverse to the top-most presented view controller var topViewController = keyWindow.RootViewController; while (topViewController.PresentedViewController != null) { topViewController = topViewController.PresentedViewController; } // Launch the scanner RGLDocReader.Shared.ShowScanner(topViewController, HandleScannerCompletion); } private void HandleScannerCompletion(RGLDocumentReaderResults results) { // Send results back to Xamarin.Forms (use MessagingCenter or an event) MessagingCenter.Send(this, "ScannerResultsReceived", results); } } }
Step 3: Call from Xamarin.Forms
In your Forms page, trigger the scanner with:
DependencyService.Get<IDocumentScannerService>().LaunchScanner();
If you're hitting null values when working with navigation controllers, here are the most common fixes:
Check Your Navigation Controller Setup
Make sure you're initializing the navigation controller properly and setting it as the window's root. A common mistake is setting a plainUIViewControlleras the root instead of wrapping it in aUINavigationController:// Correct setup in SceneDelegate/AppDelegate var mainVc = new YourMainViewController(); var navController = new UINavigationController(mainVc); window.RootViewController = navController; window.MakeKeyAndVisible();Avoid Accessing ViewControllers Too Early
Don't try to access navigation controllers or child view controllers in aUIViewController's constructor. Wait untilViewDidLoadorViewWillAppear—this is when the view hierarchy is fully initialized:public override void ViewDidLoad() { base.ViewDidLoad(); // Safe to access NavigationController or other view elements here Console.WriteLine($"Navigation Controller: {NavigationController}"); }For Xamarin.Forms Integration
If you're mixing Forms and native iOS navigation, get the native view controller corresponding to your current Forms page:var currentFormsPage = Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault(); var nativeViewController = currentFormsPage?.GetViewController(); if (nativeViewController != null) { // Push a native view controller nativeViewController.NavigationController.PushViewController(new YourNativeDetailVc(), true); }Debug with Logs
Add quick console logs to pinpoint where the null is coming from:Console.WriteLine($"Root VC: {window.RootViewController}"); Console.WriteLine($"Nav Controller: {window.RootViewController?.NavigationController}");
内容的提问来源于stack exchange,提问作者brucaqs

