iOS 16.3.1更新后Xamarin.iOS中UIActivityViewController显示空白
iOS 16.3.1 下 UIActivityViewController 空白问题修复(Xamarin.iOS)
问题重现
以下Xamarin.iOS代码在iOS 15及iOS 16早期版本能正常运行,但更新到iOS 16.3.1后,弹出的UIActivityViewController直接空白。之前iOS 16版本里虽然有Outlook无法发送PDF的问题,但弹窗至少不会空:
public void sendEmail(NSData pdfData) { sharedItems[0] = pdfData; var activityController = new UIActivityViewController(sharedItems, null); activityController.PopoverPresentationController.SourceView = this.View; activityController.PopoverPresentationController.SourceRect = new CoreGrapCGRect(View.Frame.Width/2 + 240, View.Frame.Width / 2 - 160, 0, 0); activityController.PopoverPresentationController.PermittedArrowDirections = UIPopoverArrowDirection.Down; PresentViewController(activityController, true, null); }
核心问题与修复方案
1. 修正SourceRect的无效宽高
iOS 16.3+对SourceRect的校验变严格了,你现在设置的宽高都是0,这会让popover无法正确计算布局,直接导致空白。另外代码里的CoreGrapCGRect是拼写错误,正确是CGRect。
改成有效的矩形区域,比如用视图中心的小方块当锚点:
var centerPoint = new CGPoint(View.Frame.Width / 2, View.Frame.Height / 2); activityController.PopoverPresentationController.SourceRect = new CGRect(centerPoint.X - 1, centerPoint.Y - 1, 2, 2);
如果是用按钮触发的,直接用按钮的Frame更合理:
activityController.PopoverPresentationController.SourceRect = yourTriggerButton.Frame;
2. 确保sharedItems正确初始化
你代码里直接给sharedItems[0]赋值,但没展示这个变量的初始化逻辑。如果它是未初始化的数组,UIActivityViewController找不到可共享的内容,自然就空白了。必须初始化一个包含PDF数据的NSObject[]:
// 直接初始化数组,不要用未定义的sharedItems var sharedItems = new NSObject[] { pdfData };
3. 用临时文件URL包装PDF数据(解决Outlook发送问题)
之前iOS 16里Outlook无法发送PDF,是因为直接传NSData的话,部分第三方应用识别不了。把PDF存成临时文件,用NSUrl传递,系统和第三方应用都能正确识别:
// 生成临时PDF文件 var tempDir = NSTemporaryDirectory(); var tempFilePath = Path.Combine(tempDir, "temp_attachment.pdf"); File.WriteAllBytes(tempFilePath, pdfData.ToArray()); var fileUrl = NSUrl.FromFilename(tempFilePath); // iOS 10+需要获取安全访问权限 fileUrl.StartAccessingSecurityScopedResource(); // 用URL作为共享内容 var sharedItems = new NSObject[] { fileUrl };
别忘了在完成共享后清理资源:
activityController.CompletionWithItemsHandler = (activityType, completed, returnedItems, error) => { fileUrl.StopAccessingSecurityScopedResource(); if (File.Exists(tempFilePath)) { File.Delete(tempFilePath); } };
4. 完善Popover配置
确保SourceView正确指向当前视图,同时适配iPad和iPhone的展示逻辑:
if (activityController.PopoverPresentationController != null) { activityController.PopoverPresentationController.SourceView = this.View; // 设置有效的SourceRect activityController.PopoverPresentationController.SourceRect = this.View.Bounds; activityController.PopoverPresentationController.PermittedArrowDirections = UIPopoverArrowDirection.Down; }
完整修复后的代码示例
public void sendEmail(NSData pdfData) { // 生成临时PDF文件URL var tempDir = NSTemporaryDirectory(); var tempFilePath = Path.Combine(tempDir, "email_attachment.pdf"); File.WriteAllBytes(tempFilePath, pdfData.ToArray()); var fileUrl = NSUrl.FromFilename(tempFilePath); fileUrl.StartAccessingSecurityScopedResource(); // 初始化共享内容数组 var sharedItems = new NSObject[] { fileUrl }; var activityController = new UIActivityViewController(sharedItems, null); // 配置Popover展示参数 if (activityController.PopoverPresentationController != null) { activityController.PopoverPresentationController.SourceView = this.View; // 用视图中心的小矩形作为锚点 var center = new CGPoint(View.Frame.Width / 2, View.Frame.Height / 2); activityController.PopoverPresentationController.SourceRect = new CGRect(center.X - 5, center.Y - 5, 10, 10); activityController.PopoverPresentationController.PermittedArrowDirections = UIPopoverArrowDirection.Down; } // 清理临时资源 activityController.CompletionWithItemsHandler = (activityType, completed, returnedItems, error) => { fileUrl.StopAccessingSecurityScopedResource(); if (File.Exists(tempFilePath)) { File.Delete(tempFilePath); } }; PresentViewController(activityController, true, null); }
内容的提问来源于stack exchange,提问作者Drake
相关产品推荐
相关产品推荐

