NSPasteboard 是 macOS(AppKit 框架)中的一个类,代表系统剪贴板(粘贴板),用于处理复制、剪切和粘贴操作的数据传输。
常见用途
1、⌘C / ⌘V 操作:拷贝或粘贴文本、图片、链接。
2、拖放功能:拖动文件到 App 中。
3、自定义格式共享:应用间传递特殊数据格式(如颜色、富文本)。
4、文件路径共享:拖入文件后读取路径。
常用属性
1、general:NSPasteboard类型,获取系统通用剪贴板(⌘C/⌘V 使用的)【静态属性】。
let pb = NSPasteboard.general
2、name:NSPasteboard.Name类型,当前 pasteboard 的名称(如 .general, .find, .drag 等)。
print(pb.name.rawValue) // "NSGeneralPboard"
3、types:[NSPasteboard.PasteboardType]?类型,当前剪贴板中包含的数据类型列表。
if let types = pb.types {
print("剪贴板数据类型:\(types)")
}
表示当前剪贴板中有哪些数据类型,如:.string, .tiff, .png, .fileURL, .html。
4、pasteboardItems:[NSPasteboardItem]?类型,当前剪贴板的所有条目(用于多项支持)。
for item in pb.pasteboardItems ?? [] {
print(item.types) // 查看每个 item 支持的类型
}
每个剪贴板 item 可以包含多个类型的数据(如同一项有文本 + HTML)。
5、changeCount:Int类型,当前剪贴板的版本号(每次写入会 +1)。
let count = pb.changeCount
每次调用 clearContents() 或写入数据时,这个数就会 +1,会随系统重启重置为0或初始值。
可用来监听剪贴板变化(结合 Timer 或 KVO),例如监听该值判断剪切板是否发生变更:
var lastChangeCount = NSPasteboard.general.changeCount
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in
let newCount = NSPasteboard.general.changeCount
if newCount != lastChangeCount {
lastChangeCount = newCount
print("剪贴板更新了")
}
}
常用方法
一、读取数据方法
1、data(forType: NSPasteboard.PasteboardType):读取原始二进制数据(如图片、PDF);
2、string(forType: NSPasteboard.PasteboardType):读取纯文本类型内容(.string、.rtf 等);
3、propertyList(forType: NSPasteboard.PasteboardType):读取支持 Property List 的内容(RTF、HTML、URL 等),需要手动转型,在需要兼容老数据格式、数组、RTF、颜色时使用;
if let list = pb.propertyList(forType: .fileURL) as? [String] {
print("剪贴板中的 fileURL 字符串为:\(list)")
}
4、readObjects(forClasses:options:):使用 UTType 类型读取多个 item(数组),用于读取URL、String、NSImage等类型,可替代propertyList;
if let urls = pb.readObjects(forClasses: [NSURL.self], options: nil) as? [URL] {
print("用户复制的文件:\(urls.first!)")
}
5、canReadItem(withDataConformingToTypes:):判断是否存在符合某类型的数据。
示例:
let pb = NSPasteboard.general
if let imageData = pb.data(forType: .tiff) {
print("图片数据大小:\(imageData.count) 字节")
}
二、写入数据的方法
1、clearContents():清除剪贴板所有内容(必须调用后才能写入);
2、setString(_:forType:):设置字符串(通常配合 .string);
3、setData(_:forType:):设置二进制数据(图像、PDF、HTML);
4、writeObjects(_:):让一组符合 NSPasteboardWriting 的对象写入剪贴板。
示例:
let pb = NSPasteboard.general
pb.clearContents()
pb.setString("Hello from clipboard!", forType: .string)
三、关于剪贴板条目的操作
1、pasteboardItems:获取所有剪贴板 item(每项可能支持多个类型);
2、numberOfItems:剪贴板中条目的数量;
3、availableType(from:):获取剪贴板中支持的第一个匹配类型。
四、系统剪贴板获取方式
1、NSPasteboard.general:系统通用剪贴板(大多数使用这个);
2、NSPasteboard.withUniqueName():创建一个唯一命名的临时剪贴板(适用于 App 内通信);
3、NSPasteboard(name: NSPasteboard.Name):创建自定义剪贴板;
4、NSPasteboard.Name.find:系统预定义名字,如 .general、.drag、.find、.font。
使用场景
1、NSPasteboard.general – 通用剪贴板
let pasteboard = NSPasteboard.general
表示系统的全局剪贴板(⌘C ⌘V 都用这个)。
2、写入文本(设置剪贴板内容)
let pasteboard = NSPasteboard.general
pasteboard.clearContents() // 清空旧内容
pasteboard.setString("Hello, world!", forType: .string)
3、读取文本(从剪贴板获取字符串)
if let str = NSPasteboard.general.string(forType: .string) {
print("剪贴板内容:\(str)")
}
4、写入图片
let image = NSImage(named: "example")!
let pasteboard = NSPasteboard.general
pasteboard.clearContents()
pasteboard.writeObjects([image])
注意:图片必须符合 NSPasteboardWriting 协议(NSImage 已支持)。
5、读取文件路径(如拖入 Finder 文件)
let items = NSPasteboard.general.pasteboardItems
for item in items ?? [] {
if let path = item.string(forType: .fileURL) {
print("拖入文件路径:\(path)")
}
}
6、读取图片
可以扩展测试多个图像类型:
let imageTypes: [NSPasteboard.PasteboardType] = [.png, .tiff]
for type in imageTypes {
if let data = pb.data(forType: type),
let image = NSImage(data: data) {
print("粘贴的是 \(type.rawValue) 图像")
pastedImage = image
break
}
}
支持的数据类型
1、.string:UTF-8 编码文本;
2、.pdf:PDF 文档;
3、.tiff:TIFF 图像;
4、.png:PNG 图像;
5、.rtf:RTF 富文本;
6、.rtfd:RTFD(带附件);
7、.html:HTML 内容;
8、.tabularText:表格文本;
9、.font:字体对象;
10、.ruler:标尺信息;
11、.color:NSColor 对象;
12、.sound:NSSound 对象;
13、.multipleTextSelection:多文本选择;
14、.textFinderOptions:文本查找选项;
15、.url:任意 URL;
16、.fileURL:本地文件 URL;
17、自定义类型:NSPasteboard.PasteboardType(“com.yourapp.custom”)。
注意事项
1、写入前要 clearContents():否则可能会有多个项干扰读取。
2、类型必须匹配:比如读取 .string 时,剪贴板里得有字符串类型。
3、支持多个 item:剪贴板可以存多个对象,用 .pasteboardItems 遍历。
4、多种用途:不只是拷贝粘贴,还支持拖放、服务菜单、Handoff。
总结
NSPasteboard管理剪贴板的对象,可以写入/读取剪贴板的内容。
如果想要支持原生生 ⌘V 快捷键监听,就需要使用NSEvent拦截⌘V,并在SwiftUI中响应。
如果不使用NSEvent,SwiftUI的TextField, TextEditor等组件可以响应⌘V,系统自动粘贴文本,对于SwiftUI自定义的视图则不会响应⌘V,就需要主动处理剪贴板。
相关文章
macOS用户输入事件NSEvent:https://fangjunyu.com/2025/07/04/macos%e7%94%a8%e6%88%b7%e8%be%93%e5%85%a5%e4%ba%8b%e4%bb%b6nsevent/
如何从剪贴板确定图像格式?
因为NSPasteboard的图像数据通常只有统一的public.tiff类型,不会保留原始的图片格式信息,也就是说:
NSPasteboard.general.data(forType: .tiff)
图像无论是从浏览器还是Photoshop获取,都只能获取获取的TIFF格式的Data数据。
此外,在Finder中复制图片文件时,粘贴板读取的实际是图标图像。

所以,可以尝试读取fileURL:
let pb = NSPasteboard.general
if let urls = pb.readObjects(forClasses: [NSURL.self], options: nil) as? [URL] {
for url in urls {
print("原始文件路径:", url.path)
let imageData = try? Data(contentsOf: url) // 正确方式
let fileExtension = url.pathExtension.lowercased()
print("图片格式为:\(fileExtension),原始大小:\(imageData?.count ?? 0) 字节")
}
}
拿到文件URL后,再读取文件原始内容。