简体   繁体   English

NSTableView无限滚动或分页

[英]NSTableView infinite scroll or pagination

In relation to How to determine if a user has scrolled to the end of an NSTableView Thanks Josh. 关于如何确定用户是否已滚动到NSTableView的结尾感谢Josh。

Is there a way to use this mechanism to implement a NSTableView that provides some sort of infinite scroll or pagination. 有没有办法使用这种机制来实现提供某种无限滚动或分页的NSTableView。

The idea is to tell NSTableView to load up to a certain number of records, say 1k records at once and than as user scrolls closer to the end pull another 1k records and maybe forget the first 1k records. 这个想法是告诉NSTableView加载一定数量的记录,比如说一次记录1k记录,而当用户滚动到最后时,拉出另外1k记录并且可能忘记前1k记录。

This pattern is well defined/used in web applications and java. 这种模式在Web应用程序和java中得到了很好的定义/使用。 Only the visible number of rows is loaded initially and the rest is pulled async as user scrolls up and down the table. 最初只加载可见行数,其余部分在用户向上和向下滚动表格时拉动异步。

I am interested in some obj-c code or tips on how to code this. 我对一些obj-c代码或如何编写代码的技巧感兴趣。 I know about filtering/limiting the number of records that go into the tableview but lets ignore that for a moment. 我知道过滤/限制进入tableview的记录数量,但我们暂时忽略它。

Thanks. 谢谢。

I know more about iOS, but I think the answer is similar. 我对iOS有更多了解,但我认为答案是类似的。 Table views are intrinsically finite, but you can roll your own custom scroll view to do this. 表视图本质上是有限的,但您可以滚动自己的自定义滚动视图来执行此操作。 The trick is to set a large content size and implement layout in your subclass (which will get called on every scroll change). 诀窍是设置一个大的内容大小并在子类中实现布局(每次滚动更改都会调用它)。 In that method, check to see if the content offset is near zero or near the content size. 在该方法中,检查内容偏移是否接近零或接近内容大小。 If it is, then translate the content offset back to the center of the content size and translate all the subviews (keep them on one parent content view) by the same distance so the user doesn't see any motion. 如果是,则将内容偏移量转换回内容大小的中心,并将所有子视图(将它们保留在一个父内容视图上)转换相同的距离,以便用户看不到任何动作。 Make a datasource protocol and keep asking your datasource for "cells" that tile the visible part of the view. 制作数据源协议,并不断向数据源询问平铺视图可见部分的“单元格”。

It should be up to the datasource to recognize what we would have called a page-fault in the olden days, to decide that some of the model in memory should be discarded in favor of the model where the user is scrolling. 应该由数据源来识别我们在过去的日子里所谓的页面错误,以确定应该丢弃内存中的某些模型以支持用户滚动的模型。

I poked around for an NS equivalent, but didn't see one on cursory search. 我捅了一下同等级的NS,但没有看到一个粗略的搜索。 Here's a decent-looking reference on the idea done in iOS . 这是关于在iOS中完成的想法的一个体面的参考

Given the details you've provided, I'll generalize a bit but here's how I might solve it: 鉴于你提供的细节,我会稍微概括一下,但这是我可以解决的方法:

First, I'd set a MUCH SMALLER batch size than 1000 records. 首先,我设置了一个小于1000条记录的小批量。 If the result count or "the most anybody is ever going to want to see" is indeterminate (and it sounds like it is in your case), the user probably doesn't even care past the first 100 or so. 如果结果计数或“大多数人都想要看到”是不确定的(听起来就像你的情况),用户可能甚至不关心前100个左右。 If your user often requests a large, expensive list and immediately wants to see stuff so far away from the beginning they hurl the scroller downward for two minutes straight before they stop and look around, perhaps a more intuitive sort order is needed instead of asking Google Image for 1000 more animated kitten gifs. 如果您的用户经常请求一个大型,昂贵的名单,并立即想看到的东西,所以远离他们投掷滚轮向下两分钟,他们停下来看看周围直前开始,或许需要更直观的排序顺序,而不是要求谷歌1000张更多动画小猫GIF的图像。 ;-) ;-)

The controller behind the (definitely view-based for view reuse) table view will need some sort of request queue since I assume you're batching things in because they're expensive to retrieve individually. (基本上是基于视图的视图重用)表视图后面的控制器将需要某种请求队列,因为我假设您正在批量处理,因为它们单独检索是昂贵的。 This will manage the asynchronous requesting/okay-now-it's-loaded machinery (I know that's vague but more detail is needed to get more specific). 这将管理异步请求/现在已经加载的机器(我知道这很模糊,但需要更多细节才能更具体)。 You'll make sure any "currently alive" views will somehow get this "it's ready" notification and will go from some "busy" UI state to displaying the ready item (since we NEVER want to keep the table waiting for a ready-to-display view for the object at a given row, so the view should at least show some "still waiting for details" indication so quick scrolls over lots of rows won't stall anything). 您将确保任何“当前活动”视图以某种方式获得此“已准备好”通知,并将从一些“忙碌”UI状态转到显示就绪项目(因为我们从不想让表格等待准备就绪 - 显示给定行上对象的视图,因此视图至少应显示一些“仍在等待详细信息”的指示,因此快速滚动大量行不会拖延任何内容。

Using a view-based NSTableView and associated data source methods will let the table view handle only keeping enough copies of your custom NSTableCellView around to reuse during scrolling. 使用基于视图的NSTableView和关联的数据源方法将使表视图句柄只保留自定义NSTableCellView的足够副本,以便在滚动期间重用。 Since you have to provide a configured view when asked, the view's default state can either be "draw nothing if not ready" or some visually generic placeholder until the object is realized and ready (then you can just reload that row instead of the whole table). 由于您在被询问时必须提供已配置的视图,因此视图的默认状态可以是“如果没有准备就绘制任何内容”或一些可视通用占位符,直到对象实现并准备就绪(然后您可以重新加载该行而不是整个表)。 This way the table keeps scrolling and drawing rapidly because it doesn't care about what your controller is doing to fulfill the promise of updating the visible rows (that custom cell view of yours will observe its represented object's updates). 这样,表可以快速滚动和绘制,因为它不关心控制器正在做什么来履行更新可见行的承诺(您的自定义单元视图将观察其表示的对象的更新)。

You probably want the scrollers to reflect the total number of rows batched in so far if the upper bound is astronomical - reflecting that size would make the scroll grip both tiny and very sensitive. 如果上限是天文数字的话,您可能希望滚动条能够反映到目前为止批量的行总数 - 反映出该尺寸会使滚动夹具既微小又非常敏感。 Instead, just grow the scroller (via the table view's row count) by what the user has "requested" so far, all the way back to the beginning of the list. 相反,只需按用户到目前为止“请求”的内容(通过表视图的行数)增长,一直回到列表的开头。 Any time more are batched in, you'll want to add the batch size to your controller's total batched row count. 无论何时批量处理,您都需要将批量大小添加到控制器的总批次行数中。 This still lets the scroller zoom by rows the user couldn't distinguish at that speed anyway. 这仍然允许滚动器按行缩放,用户无论如何都无法以该速度进行区分。 You communicate the row count change to the table view by sending it -noteNumberOfRowsChanged and replying to its resulting data source request ( -numberOfRowsInTableView: ) with the updated total row count you stashed in a property of your controller. 通过发送-noteNumberOfRowsChanged并回复其结果数据源请求( -numberOfRowsInTableView: -noteNumberOfRowsChanged ,将行计数更改传递给表视图,其中-noteNumberOfRowsChanged您在控制器属性中保存的更新总行数。 It'll ask for views for the newly visible rows as needed (which will be in some neutral, unfulfilled visual state until it's realized as before), update the scroll view, lather, rinse, repeat. 它将根据需要询问新可见行的视图(这将是一些中性,未实现的视觉状态,直到它像以前一样实现),更新滚动视图,泡沫,冲洗,重复。

You could use NSCache to keep memory usage low. 您可以使用NSCache来降低内存使用率。 Set its countLimit to several times your batch size and let it drop previous batches if it decides it needs to dump the first n model objects, then batch them back in if the table view suddenly asks for a view for a row no longer in the batch window's range. 将其countLimit设置为批次大小的几倍,如果它确定需要转储前n个模型对象,则让它删除以前的批次,然后如果表视图突然要求批处理中的行不再显示,则将它们重新批处理窗口的范围。

Without knowing more about your requirements and architecture, it's hard to get more specific. 如果不了解您的要求和架构,就很难更具体。 If I haven't hit the mark, consider editing your question to include more detail. 如果我没有达到标记,请考虑编辑您的问题以包含更多细节。 If I'm totally off base from what you're asking for, please clarify. 如果我完全偏离你的要求,请澄清。 :-) :-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM