You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Xamarin Forms(C#跨平台)中通过iOS Share Extension获取图片与文本?

我刚帮几个开发者解决过类似的Xamarin.iOS Share Extension问题,给你整理一套完整的C#实现方案,以及从照片应用取图的具体步骤:

一、快速确认Share Extension的基础配置

虽然你说已经配置好了,但还是要确保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

火山引擎 最新活动