如何在Xamarin Forms(C#跨平台)中通过iOS Share Extension获取图片与文本?
我刚帮几个开发者解决过类似的Xamarin.iOS Share Extension问题,给你整理一套完整的C#实现方案,以及从照片应用取图的具体步骤:
虽然你说已经配置好了,但还是要确保Info.plist里的激活规则包含图片和文本类型,这样照片应用才会显示你的扩展:
<key>NSExtension</key> <dict> <key>NSExtensionAttributes</key> <dict> <key>NSExtensionActivationRule</key> <dict> <key>NSExtensionActivationSupportsImageWithMaxCount</key> <integer>10</integer> <!-- 支持最多10张图片 --> <key>NSExtensionActivationSupportsText</key> <true/> </dict> </dict> <key>NSExtensionMainStoryboard</key> <string>MainInterface</string> <key>NSExtensionPointIdentifier</key> <string>com.apple.share-services</string> </dict>
二、用C#获取图片和文本的核心代码
在你的ShareViewController(继承自SLComposeServiceViewController)中,重写DidSelectPost方法(或者在ViewDidLoad里提前处理),核心逻辑是遍历ExtensionContext的输入项,解析每个附件:
public override void DidSelectPost() { var extensionItems = ExtensionContext.InputItems.Cast<NSExtensionItem>(); var processingTasks = new List<Task>(); foreach (var item in extensionItems) { var attachments = item.Attachments.Cast<NSItemProvider>(); foreach (var attachment in attachments) { // 处理文本内容 if (attachment.HasItemConformingTo("public.text")) { var textTask = Task.Run(() => { var tcs = new TaskCompletionSource<string>(); attachment.LoadItem("public.text", null, (data, error) => { if (error == null && data != null) { tcs.SetResult(data.ToString()); } else { tcs.SetResult(null); } }); return tcs.Task; }); processingTasks.Add(textTask.ContinueWith(t => { if (!string.IsNullOrEmpty(t.Result)) { // 这里拿到文本,可存到共享容器或做其他处理 Console.WriteLine("获取到文本: " + t.Result); } })); } // 处理图片(照片应用的图片属于public.image类型) if (attachment.HasItemConformingTo("public.image")) { var imageTask = Task.Run(() => { var tcs = new TaskCompletionSource<byte[]>(); attachment.LoadItem("public.image", null, (data, error) => { if (error == null && data != null) { byte[] imageBytes = null; if (data is NSUrl imageUrl) { // 照片应用的图片通常以NSUrl形式传递 var imageData = NSData.FromUrl(imageUrl); imageBytes = imageData.ToArray(); } else if (data is UIImage image) { // 少数情况直接返回UIImage imageBytes = image.AsJPEG(0.8).ToArray(); } tcs.SetResult(imageBytes); } else { tcs.SetResult(null); } }); return tcs.Task; }); processingTasks.Add(imageTask.ContinueWith(t => { if (t.Result != null) { // 拿到图片字节数组,可转存到共享目录或传给主应用 Console.WriteLine("获取到图片,大小: " + t.Result.Length + " bytes"); } })); } } } // 等待所有处理完成后,结束扩展 Task.WhenAll(processingTasks).ContinueWith(_ => { ExtensionContext.CompleteRequest(null, null); }); }
三、从iOS照片应用获取图片的具体操作流程
- 确保你的Share Extension已经安装到测试设备/模拟器上
- 打开iOS照片应用,选择1张或多张图片
- 点击底部的「分享」按钮,在弹出的菜单中找到你的应用扩展并点击
- 你的Share Extension界面加载后,上面的代码会自动解析选中的图片
- 处理完成后,扩展会自动关闭并返回照片应用
四、关键注意事项
- 共享容器:Share Extension和主应用是独立进程,要传递数据必须配置App Groups。在Entitlements.plist中添加相同的App Group ID,然后用以下代码获取共享目录:
var sharedContainerUrl = NSFileManager.DefaultManager.GetContainerUrl("group.your.app.bundle.id"); var sharedFilePath = Path.Combine(sharedContainerUrl.Path, "image.jpg"); File.WriteAllBytes(sharedFilePath, imageBytes); // 把图片存到共享目录 - 异步处理:
LoadItem是异步方法,必须等待所有处理完成再调用CompleteRequest,否则会导致数据丢失 - 权限:通过Share Extension获取选中的图片不需要额外的照片库权限,不需要在Extension的Info.plist中添加
NSPhotoLibraryUsageDescription
内容的提问来源于stack exchange,提问作者Chris




