- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个符合 NSCoding 协议(protocol)的自定义类。下面是我如何实现协议(protocol)的方法。
User.swift
required init?(coder aDecoder: NSCoder) {
self.name = aDecoder.decodeObject(forKey: #keyPath(name)) as! String
self.age = aDecoder.decodeInteger(forKey: #keyPath(age))
}
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: #keyPath(name))
aCoder.encode(age, forKey: #keyPath(age))
}
我将阅读选项设置为:
static func readingOptions(forType type: String, pasteboard: NSPasteboard) -> NSPasteboardReadingOptions {
return .asKeyedArchive
}
每当用户在 NSOutlineView
上拖动单元格行时,此对象将被放入 NSDragPboard
中。你可以看到下面的实现:
UserViewController.h
var users: User // Store the users to be used in the outlineView
.
.
.
func outlineView(_ outlineView: NSOutlineView, writeItems items: [Any], to pasteboard: NSPasteboard) -> Bool {
if let user = items.first as? User {
pasteboard.clearContents()
pasteboard.writeObjects([user])
return true
}
return false
}
用户通过释放鼠标按钮完成拖动后,应用程序将获取粘贴板内容,方法是:
func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
let pasteboard = info.draggingPasteboard()
if let userInPasteboard = pasteboard.readObjects(forClasses: [User.self], options: nil)?.first as? User {
// We can access the user in pasteboard here
}
}
但问题是,粘贴板中的数据与 outlineView 中的数据具有不同的内存地址。
如果我们尝试使用 pasteBoard 中的用户在 outlineView 中查找用户,我们找不到它。
for user in self.users {
if user == userInPasteboard {
print("We found the user that was placed on pasteboard") // Never executed
}
}
我可以为 User 类实现 Equatable
协议(protocol)。但我认为,如果我们能以某种方式使从粘贴板读取的对象与写入粘贴板的对象具有相同的指针地址,它就可以工作。
下面是我要实现的目标:
有可能实现吗?怎么办?
最佳答案
有很多方法可以解决这个问题。既然你说(在评论中)这只是为了在单个大纲 View 中重新排序,我将解释我是如何做到的。
首先,我向我的数据源添加了一个私有(private)变量来跟踪被拖动的项目:
private var itemsBeingDragged = [MyItem]()
因为我将在放置时使用它来获取拖动的项目,所以粘贴板上的内容并不重要。我这样实现了 outlineView(_:pasteboardWriterForItem:)
:
func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? {
guard let node = item as? MyNode else { return nil }
let pasteboardItem = NSPasteboardItem()
pasteboardItem.setString(String(describing: node), forType: dragType)
return pasteboardItem
}
为了设置和清除 itemsBeingDragged
,我实现了这些方法:
func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItems draggedItems: [Any]) {
itemsBeingDragged = draggedItems.flatMap({ $0 as? MyItem })
}
func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation) {
itemsBeingDragged = []
}
最后,我像这样实现了 outlineView(_:acceptDrop:item:childIndex:)
:
func outlineView(_ outlineView: NSOutlineView, acceptDrop info: NSDraggingInfo, item: Any?, childIndex index: Int) -> Bool {
guard
(info.draggingSource() as? NSOutlineView) === outlineView,
let dropTarget = item as? MyItem
else { return false }
// Update model using `dropTarget`, `index`, and `itemsBeingDragged`.
// Update `outlineView` to match.
return true
}
如果拖动来自另一个应用程序,则 info.draggingSource()
为 nil
。如果拖动来自同一个应用程序,则它是提供拖动项的对象。因此,我做的第一件事是确保拖动来自与拖放所在的同一轮廓 View 。
如果拖动源位于另一个应用程序中,则获取指向原始拖动项的指针毫无意义,因为指针在跨进程边界时无效——原始拖动项在您的进程中不存在。跨进程边界拖动项目的唯一有意义的方法是实际提供被拖动项目的序列化表示。
如果拖动源也在您的应用程序中,那么您可以将指针粘贴到粘贴板上,但这样做仍然不是内存安全的。最好做一些事情,比如定义一个协议(protocol)来从源中获取被拖动的项目:
protocol MyDragSource {
var itemsBeingDragged: [Any]?
}
然后,在acceptDrop
中:
guard
let sameAppSource = info.draggingSource(),
let source = (sameAppSource as? MyDragSource) ?? (sameAppSource as? NSTableView)?.dataSource as? MyDragSource,
let draggedItems = source.itemsBeingDragged?.flatMap({ $0 as? AcceptableItem }),
draggedItems.count > 0
else { return false }
…其中 AcceptableItem
是您用于大纲 View 项目的任何类型。
使用 info.draggingSource()
并不丢脸。这是有原因的。
关于swift - 如何写入 NSPasteboard 并使用相同的指针获取它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45330382/
将字符串或数字数组发送到粘贴板的最佳方法是什么? 我尝试过使用 [pasteBoard writeObjects:] 但看起来我必须子类化 NSArray 才能做到这一点,它需要一个协议(protoc
从后台线程将数据写入 NSPasteboard 对象是否安全?我似乎无法在任何地方找到明确的答案。我认为假设是在拖动开始之前数据将被写入粘贴板。 背景: 我有一个从 Evernote 获取数据的应用程
有没有办法取消对 NSPasteboard 的过滤,以获取源应用程序明确声明的它将提供的内容? 我正在尝试在我的应用程序中序列化粘贴板数据。当另一个应用程序将 RTF 文件放在粘贴板上,然后我询问可用
我无法让此方法返回 YES: - (BOOL) writeToPasteBoard:(NSString *)stringToWrite { return [pasteBoard setStri
虽然我有工作代码,但我很困惑我是否对 NSPasteboard 采用了正确的方法,并且我正在联系以查看是否有人可以帮助我阐明最佳方法。 自 2012 年以来,Apple 似乎没有编写任何关于拖放的完整
有没有一种方法可以从粘贴板中全局删除当前项目(在任何应用程序中按 Command+V 时将显示的项目)并使其能够按 Command+ V 粘贴最后复制的项目? 假设我复制 foo 然后复制 bar,我
我正在使用 NSPasteboardWriting 协议(protocol)在 NSPasteboard 上编写自定义对象。如何为自定义对象创建UTI? - (NSArray *)writableTy
我一直在尝试不同的文件路径和不同类型的组合,但基本上我想做的是复制一个名为“test”的文件夹,该文件夹位于我的资源文件夹内。 当我给出绝对路径(例如:/Users/dw/src/Menulet)时,
我想使用 NSPasteboard 数据启动应用程序(或使用 AppleEvents 发送给它们),就像在 Finder 中将文件、文本、图像拖放到应用程序(或 Dock 中)并启动时所做的那样或调用
您可以像这样调用NSPasteboard: [pboard declareTypes:types owner:self]; 这意味着粘贴板稍后会要求所有者根据需要提供类型的数据。然而,我无法从文档中找
我有一个属于此类的对象,其中包含以下声明: 标题 @interface MyClassObject : NSObject @property (nonatomic, strong) NSArray
我已阅读 Apple 的 Pasteboard Programming Guide ,但它没有回答我的特定问题。 我正在尝试编写一个 Cocoa 应用程序(适用于 OS X,而不是 iOS),它将跟踪
我正在开发一个可在两个 NSTableView 之间拖放文件的 Cocoa 应用程序。我不想只使用 URL,而是想使用自定义结构,这样我就可以在需要时访问更多数据,而不是不断调用 FileManage
我有一个符合 NSCoding 协议(protocol)的自定义类。下面是我如何实现协议(protocol)的方法。 User.swift required init?(coder aDecoder:
好的,这是我正在使用的代码: if let image = NSImage(pasteboard: pasteboard){ //.. } 我有 3 种方式将图像输入应用程序: 如果将图像拖到
我们应该如何使用NSPasteboard剪切和粘贴文件?目前我通过写入和读取文件 URL 来实现复制和粘贴。 cut 的问题是,在我将 URL 写入粘贴板后,我必须删除该文件。当我尝试粘贴该文件时,它
我正在尝试将 html 数据复制到 MAC 上的剪贴板。但是当我使用(Finder->编辑菜单->显示剪贴板)检查剪贴板时,它什么也不显示。我希望按原样粘贴格式化数据。下面是我正在使用的代码: NSP
我们的一位客户在粘贴时有时会遇到这样的崩溃: 0 com.apple.Foundation 0x9143bd1d readPointerAt + 9 1 com.apple.Foundation 0x
我有一个 NSBroswer,其中包含一系列查找文本 blob 的条目。如果 Blob 存在那么- (BOOL)browser:canDragRowsWithIndexes:inColumn:with
我希望将 NSPasteboard.generalPasteboard() 暂时切换为我的应用使用 NSPasteboard.pasteboardWithUniqueName() 生成的自定义版本 这
我是一名优秀的程序员,十分优秀!