通过在 Lion 中拖动来重新排列表格行
我在使用新的 Lion 功能重新排列应用程序中的行时遇到问题。我正在使用 outlineView:pasteboardWriterForItem: 来存储行索引,以便稍后在验证/接受放置时可以访问它们。我创建一个新的 NSPasteboardItem 来返回,并尝试按如下方式存储行号:
[pbItem setData: [NSKeyedArchiver archivedDataWithRootObject: [NSNumber numberWithInteger: [fTableView rowForItem: item]]]
forType: TABLE_VIEW_DATA_TYPE];
TABLE_VIEW_DATA_TYPE 是一个自定义字符串,我用来区分拖动粘贴板中的自定义数据。除了拖动这些行之外我不会使用它。
尝试拖动时,我在控制台中收到:'TableViewDataType' 不是有效的 UTI 字符串。无法为无效的 UTI 设置数据。
当然,我可以使用一些用于粘贴板的内置 UTI,但它们都不适用(并且使用它们会导致拖动接受除行之外的拖动,而它应该't)。我是否缺少一些东西,比如定义一个仅用于拖动的自定义 UTI 的方法(而不使其成为“真正的”UTI,因为我在内部拖动之外没有使用它,所以它不应该公开)。
感谢您的帮助!
I am having trouble using the new Lion functionality to rearrange rows in my app. I am using outlineView:pasteboardWriterForItem:
to store the row indexes so that I can access them later when I validate/accept the drop. I create a new NSPasteboardItem to return, and am attempting to store the row number as so:
[pbItem setData: [NSKeyedArchiver archivedDataWithRootObject: [NSNumber numberWithInteger: [fTableView rowForItem: item]]]
forType: TABLE_VIEW_DATA_TYPE];
TABLE_VIEW_DATA_TYPE is a custom string I'm using to distinguish my custom data in the dragging pasteboard. I don't use it outside of dragging these rows.
When attempting the drag, I receive in Console: 'TableViewDataType' is not a valid UTI string. Cannot set data for an invalid UTI.
Of course I could use some of the built-in UTIs for pasteboards, but none of them apply (and using them causes the drag to accept drags other than the rows, which it shouldn't). Is there something I'm missing, like a way to define a custom UTI just for dragging (without making it a "real" UTI since I have no use for it outside of the internal dragging, so it shouldn't be public).
Thanks for any help!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我有类似的要求,除了我有一个对象网格,我想通过将选定的对象拖动到新位置来重新排列。有多种方法可以做到这一点,包括创建自定义对象并实现
NSPasteboardWriting
和NSPasteboardReading
协议(以及NSCoding
协议,如果您愿意)将数据读取为NSPasteboardReadingAsKeyedArchive
),但这对于拖动保留在应用程序内部的对象来说似乎有点过分了。我所做的涉及使用
NSPasteboardItem
作为自定义 UTI 类型的包装器(它已经实现了NSPasteboardWriting
和NSPasteboardReading
协议)。首先声明一个自定义 UTI 类型:#define kUTIMyCustomType @“com.mycompany.MyApp.MyCustomType”
这需要以“com.domain.MyApp”格式定义,否则您将收到以下形式的错误: “XXX 不是有效的 UTI 字符串。无法为无效的 UTI 设置数据。”苹果在他们的文档中提到了这一点。
然后,您必须在将发生拖动的视图中注册此自定义 UTI 类型。这可以在运行时完成,并且不需要添加任何 .plist。在视图的 init 方法中添加以下内容:
现在,确保为此视图设置了委托,并且委托对象实现了所需的
NSDraggingSource
和NSDraggingDestination
协议方法。这将使您避免破坏 MVC 设计模式,允许指定的控制器对象处理将数据放置在粘贴板上,这可能涉及查询模型数据(即索引)。具体来说,为了将拖动开始时要移动的对象的索引放置在拖动粘贴板上,作为索引数据的
NSPasteboardItem
包装器:当拖动操作完成时,读取拖动的索引
NSPasteboardItem< /代码> 数据:
I had similar requirements except I had a grid of objects that I wanted to rearrange by dragging selected objects to a new location. There are several ways of doing this, including creating a custom object and implementing the
NSPasteboardWriting
andNSPasteboardReading
protocols, (andNSCoding
protocols if you will be reading data asNSPasteboardReadingAsKeyedArchive
), but this seems to be overkill for dragging of objects that remain internal to the application.What I did involves using the
NSPasteboardItem
as a wrapper with a custom UTI type (it already implements theNSPasteboardWriting
andNSPasteboardReading
protocols). First declare a custom UTI type:#define kUTIMyCustomType @“com.mycompany.MyApp.MyCustomType”
This needs to be defined in the ‘com.domain.MyApp’ format otherwise you will get errors of the form: “XXX is not a valid UTI string. Cannot set data for an invalid UTI.” Apple mentions this in their documentation.
Then you must register this custom UTI type in the view in which your dragging will occur. This can be done at runtime, and does not require any .plist additions. In your view's init method add the following:
Now, make sure that the delegate is set for this view, and the delegate object implements the required
NSDraggingSource
andNSDraggingDestination
protocol methods. This will allow you to avoid breaking the MVC design pattern, by allowing the designated controller object to handle placing the data on the pasteboard which will likely involve querying model data (i.e., indexes).Specifically, for placing on the dragging pasteboard the indexes of objects to be moved when dragging begins as
NSPasteboardItem
wrappers of your index data:And when the dragging operation completes, to read the dragged index
NSPasteboardItem
data:您可以使用的另一种技术是将正在拖动的对象的索引存储在侧面的实例变量中。将所有内容都放在粘贴板上并不是绝对必要的,除非您从另一个应用程序接受项目,反之亦然。
希望有帮助......我正在使用表视图的技术,但它对于大纲视图应该几乎相同。
Another technique you can use is to just store the indices of the objects you're dragging in an instance variable on the side. Putting everything on the pasteboard isn't strictly necessary unless you're accepting items from another app or vice versa.
Hope that helps… I'm using the technique for a table view, but it should be virtually identical for an outline view.
您应该创建一个符合
NSPasteboardWriting
协议。在您的自定义对象中,您可以实现
writableTypesForPasteboard:
以返回您的粘贴板项支持的自定义 UTI 列表。然后,您可以实现pasteboardPropertyListForType:
,以便在粘贴板要求时返回相应自定义 UTI 对象的 plist 表示形式。您可以使用
NSPropertyListSerialization
的+propertyListWithData:options:format:error:
方法从任意数据创建 plist。然后,您可以在表视图数据源中重写
tableView:pasteboardWriterForRow:
以返回自定义对象的实例。Instead of using a vanilla
NSPasteboardItem
, you should create a custom object that conforms to theNSPasteboardWriting
protocol.In your custom object, you can implement
writableTypesForPasteboard:
to return a list of custom UTIs that your pasteboard item supports. You then implementpasteboardPropertyListForType:
to return a plist representation of your object for the appropriate custom UTI when the pasteboard asks for it.You can create a plist from arbitrary data using the
+propertyListWithData:options:format:error:
method ofNSPropertyListSerialization
.You would then override
tableView:pasteboardWriterForRow:
in your table view data source to return an instance of your custom object.