我正在尝试在 SwiftUI 中执行基本的拖放操作到 NSTextView,但在 macOS 12 beta 中发生了一些变化,虽然此代码在 macOS 11 上运行良好,但它不再适用:
var body: some View {
VStack {
ActionControl()
.padding()
.onDrag { () -> NSItemProvider in
let value = Action(string: "hello, world").string
let p = ActionProfile(value: value)
return NSItemProvider(item: p, typeIdentifier: ActionProfile.pasteboardType)
}
MyTextView()
.padding()
}
}
class ActionProfile: NSObject, NSCoding, NSSecureCoding {
static var supportsSecureCoding: Bool = true
static var pasteboardType = "com.my.app.action.profile"
@objc var rawValue: String
func encode(with aCoder: NSCoder) {
aCoder.encode(rawValue, forKey: "value")
}
required init(value: String) {
self.rawValue = value
}
required init?(coder aDecoder: NSCoder) {
self.rawValue = aDecoder.decodeObject(of: NSString.self, forKey: "value")! as String
}
required init?(pasteboardPropertyList propertyList: Any, ofType type: NSPasteboard.PasteboardType) {
return nil
}
}
extension ActionProfile: NSPasteboardWriting, NSPasteboardReading {
static var nsPasteboardType: NSPasteboard.PasteboardType = .init(pasteboardType)
static func readingOptions(forType type: NSPasteboard.PasteboardType, pasteboard: NSPasteboard) -> NSPasteboard.ReadingOptions {
return .asKeyedArchive
}
func writableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] {
return [ActionProfile.nsPasteboardType]
}
func pasteboardPropertyList(forType type: NSPasteboard.PasteboardType) -> Any? {
if type == ActionProfile.nsPasteboardType {
return try! NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: false)
}
return nil
}
static func readableTypes(for pasteboard: NSPasteboard) -> [NSPasteboard.PasteboardType] {
return [ActionProfile.nsPasteboardType]
}
}
extension MyTextViewControl {
override internal var writablePasteboardTypes: [NSPasteboard.PasteboardType] {
return [ActionProfile.nsPasteboardType] + super.writablePasteboardTypes
}
override func prepareForDragOperation(_ sender: NSDraggingInfo) -> Bool {
return true
}
override func draggingUpdated(_ sender: NSDraggingInfo) -> NSDragOperation {
let location = self.characterIndexForInsertion(at: self.convert(sender.draggingLocation, from: nil))
self.setSelectedRange(NSRange(location: location, length: 0))
return sender.draggingSource is MyTextViewControl ? .move : .copy
}
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool {
let pboard = sender.draggingPasteboard
if pboard.availableType(from: [ActionProfile.nsPasteboardType]) == ActionProfile.nsPasteboardType {
if let profiles = pboard.readObjects(forClasses: [ActionProfile.self], options: nil) as? [ActionProfile], !profiles.isEmpty {
let alert = NSAlert()
alert.messageText = "WORKS"
alert.runModal()
return true
}
else {
let alert = NSAlert()
alert.messageText = "FAILED"
alert.runModal()
return super.performDragOperation(sender)
}
}
return super.performDragOperation(sender)
}
}
在 macOS 12 beta 上,调用 pboard.readObjects(...) 时,尝试将项目拖入 NSTextView 时出现此错误:
Failed to initialize keyed unarchiver for pasteboard data: Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: data is empty; did you forget to send -finishEncoding to the NSKeyedArchiver?" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: data is empty; did you forget to send -finishEncoding to the NSKeyedArchiver?}
我注意到既不是supportsSecureCoding
也不encode(with aCoder: NSCoder)
是 macOS 12,而是在 macOS 11 上。
macOS 12 中是否有关于 NSCoding 或 NSSecureCoding 的任何更改,或者这只是一个错误?