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

在iPad/MacCatalyst上用SwiftUI复制自定义结构体到剪贴板

实现选中自定义结构体后通过Cmd+C复制到剪贴板

要实现这个需求,需要结合系统命令监听和剪贴板操作,以下是具体实现方案:

关键实现步骤

  1. 监听Mac系统的「复制」命令(包含Cmd+C快捷键和菜单栏「编辑>复制」选项)
  2. 仅当条目处于选中状态时,将Item结构体编码为可复制的格式(如JSON)并写入剪贴板
  3. 利用Item已遵循的Codable协议完成序列化

修改后的完整代码

import SwiftUI
import AppKit // 引入AppKit以使用NSPasteboard

struct ContentView: View {
    
    @State var item: Item = Item()
    @State var isSelected: Bool = false
    
    var body: some View {
        ZStack {
            Color.clear
                .contentShape(Rectangle())
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .edgesIgnoringSafeArea(.all)
                .onTapGesture {
                    isSelected = false
                }
            
            ItemRepresentation(item: item)
                .onTapGesture {
                    isSelected = true
                }
            
            if isSelected {
                SelectionIndicator(item: item)
            }
        }
        .onAppear {
            item.width = Double.random(in: 20...500)
            item.height = Double.random(in: 20...500)
            item.cornerRadius = Double.random(in: 1...100)
        }
        .onCommand("copy") { // 监听系统复制命令
            guard isSelected else { return }
            copyItemToClipboard(item)
        }
    }
    
    // 将Item复制到剪贴板的方法
    private func copyItemToClipboard(_ item: Item) {
        do {
            let encoder = JSONEncoder()
            encoder.outputFormatting = .prettyPrinted // 生成格式化的JSON,方便查看
            let data = try encoder.encode(item)
            guard let jsonString = String(data: data, encoding: .utf8) else {
                print("无法将数据转换为字符串")
                return
            }
            
            let pasteboard = NSPasteboard.general
            pasteboard.clearContents()
            pasteboard.setString(jsonString, forType: .string)
        } catch {
            print("编码Item失败: \(error.localizedDescription)")
        }
    }
    
    @ViewBuilder func ItemRepresentation(item: Item) -> some View {
        Text(item.title)
            .frame(width: item.width, height: item.height)
            .background(Color.red)
            .cornerRadius(item.cornerRadius, antialiased: true)
    }  
    
    @ViewBuilder func SelectionIndicator(item: Item) -> some View {
        Rectangle()
            .stroke(Color.blue, lineWidth: 2)
            .frame(width: item.width + 20, height: item.height + 20)
    }  
}

struct Item: Codable {
    var title: String = "Text"
    var width: Double = 0
    var height: Double = 0
    var cornerRadius: Double = 0
}

代码说明

  • onCommand("copy"):SwiftUI中监听系统标准命令的修饰符,会响应Cmd+C快捷键和菜单栏的「复制」选项
  • copyItemToClipboard方法:
    • 使用JSONEncoder将Item实例序列化为JSON字符串,.prettyPrinted让输出的JSON更易读
    • 通过NSPasteboard.general获取系统剪贴板实例,清空原有内容后写入JSON字符串
  • 选中状态判断:只有isSelected为true时才执行复制逻辑,避免未选中时误操作

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:54:58