You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI:如何正确使用ShareLink的items参数分享多内容?

正确使用SwiftUI ShareLink的items参数分享图片与文本

问题分析

你直接将image(假设是SwiftUI的Image视图)和文本放入items数组的写法存在两个问题:

  1. SwiftUI的Image本身不遵循Transferable协议,无法直接作为分享项;
  2. 即使将符合Transferable的UIImage和String放入数组,系统会将它们视为两个独立的分享内容,而非组合在一起的整体。

正确实现方式

根据你分享图片+文本组合内容的需求,推荐以下两种方案:

方案1:自定义Transferable类型(最灵活)

定义一个包含文本和图片的自定义类型,实现Transferable协议,让系统能将它们作为整体分享:

import SwiftUI
import UniformTypeIdentifiers

struct PostShareItem: Transferable {
    let text: String
    let image: UIImage

    static var transferRepresentation: some TransferRepresentation {
        // 支持富文本格式分享(文本+图片组合)
        DataRepresentation(exportedContentType: .richText) { item in
            let attrString = NSMutableAttributedString(string: item.text)
            // 添加图片到文本末尾
            let attachment = NSTextAttachment()
            attachment.image = item.image
            attachment.bounds = CGRect(x: 0, y: -5, width: item.image.size.width, height: item.image.size.height)
            attrString.append(NSAttributedString(string: "\n"))
            attrString.append(NSAttributedString(attachment: attachment))
            
            return try NSKeyedArchiver.archivedData(withRootObject: attrString, requiringSecureCoding: false)
        }

        // 兼容单独分享图片的场景
        FileRepresentation(contentType: .png) { item in
            guard let data = item.image.pngData() else {
                throw TransferError.exportFailed
            }
            return .init(data: data, filename: "shared_post.png")
        }

        // 兼容单独分享文本的场景
        StringRepresentation(exportedContentType: .plainText) { item in
            item.text
        }
    }

    enum TransferError: Error {
        case exportFailed
    }
}

// 使用示例
// 假设你已经有UIImage类型的图片数据(如果是SwiftUI Image需要先转成UIImage)
ShareLink(items: [PostShareItem(text: vm.post.text, image: yourUIImage)],
          preview: SharePreview(vm.post.text, image: Image(uiImage: yourUIImage))) {
    Image(systemName: "square.and.arrow.up")
        .font(.system(size: 19))
        .foregroundColor(Color("SpaceBlue"))
}

方案2:使用AttributedString(更简洁)

将文本和图片组合成AttributedString(它天然遵循Transferable),直接作为分享项:

import SwiftUI
import UniformTypeIdentifiers

// SwiftUI Image转UIImage的扩展
extension Image {
    func asUIImage() -> UIImage? {
        let host = UIHostingController(rootView: self)
        host.view.frame = CGRect(x: 0, y: 0, width: 200, height: 200) // 根据图片实际尺寸调整
        let renderer = UIGraphicsImageRenderer(size: host.view.bounds.size)
        return renderer.image { _ in
            host.view.drawHierarchy(in: host.view.bounds, afterScreenUpdates: true)
        }
    }
}

// 构建分享内容
private var sharedContent: AttributedString {
    var content = AttributedString(vm.post.text)
    if let uiImage = image.asUIImage() {
        let attachment = NSTextAttachment()
        attachment.image = uiImage
        content.append(AttributedString("\n"))
        content.append(AttributedString(NSAttributedString(attachment: attachment)))
    }
    return content
}

// 使用ShareLink
ShareLink(item: sharedContent,
          preview: SharePreview(vm.post.text, image: image)) {
    Image(systemName: "square.and.arrow.up")
        .font(.system(size: 19))
        .foregroundColor(Color("SpaceBlue"))
}

可选场景:独立分享图片或文本

如果你希望用户可以选择分享图片或者文本中的任意一个,只需确保数组中的每个元素都遵循Transferable(比如用UIImage而非SwiftUI的Image):

// 注意:这里的image必须是UIImage类型
ShareLink(items: [yourUIImage, vm.post.text],
          preview: SharePreview(vm.post.text, image: Image(uiImage: yourUIImage))) {
    Image(systemName: "square.and.arrow.up")
        .font(.system(size: 19))
        .foregroundColor(Color("SpaceBlue"))
}

内容的提问来源于stack exchange,提问作者AppleMango

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:32:41